wip: internal working as normal
diff --git a/configure.py b/configure.py
index b5c5865..3d35a39 100755
--- a/configure.py
+++ b/configure.py
@@ -263,32 +263,34 @@
         assigns = """
         localparam NUM_MACROS = {};
         wire [NUM_MACROS:0] data, scan, latch, clk;
-        wire ready, slow_clk;
-        wire [8:0] active_select    = io_in[20:12];
-        wire [7:0] inputs           = io_in[28:21];
-        wire set_clk_div            = io_in[11];
-        wire [7:0] outputs;
-        assign io_out[36:29]        = outputs;
-        assign io_out[37]           = ready;
-        assign io_out[10]           = slow_clk;
         """
 
         scan_controller_template = """
         scan_controller #(.NUM_DESIGNS(NUM_MACROS)) scan_controller(
-            .clk            (wb_clk_i),
-            .reset          (wb_rst_i),
-            .active_select  (active_select),
-            .inputs         (inputs),
-            .outputs        (outputs),
-            .ready          (ready),
-            .slow_clk       (slow_clk),
-            .set_clk_div    (set_clk_div),
-            .scan_clk       (clk[0]),
-            .scan_data_out  (data[0]),
-            .scan_data_in   (data[NUM_MACROS]),
-            .scan_select    (scan[0]),
-            .scan_latch_enable(latch[0]),
-            .oeb            (io_oeb[37:29])
+            .clk                    (wb_clk_i),
+            .reset                  (wb_rst_i),
+            .active_select          (io_in[20:12]),
+            .inputs                 (io_in[28:21]),
+            .outputs                (io_out[36:29]),
+            .ready                  (io_out[37]),
+            .slow_clk               (io_out[10]),
+            .set_clk_div            (io_in[11]),
+
+            .scan_clk               (clk[0]),
+            .scan_data_out          (data[0]),
+            .scan_data_in           (data[NUM_MACROS]),
+            .scan_select            (scan[0]),
+            .scan_latch_en          (latch[0]),
+
+            .la_scan_clk            (la_data_in[0]),
+            .la_scan_data_in        (la_data_in[1]),
+            .la_scan_data_out       (la_data_out[0]),
+            .la_scan_select         (la_data_in[2]),
+            .la_scan_latch_en       (la_data_in[3]),
+
+            .driver_sel             (io_in[9:8]),
+
+            .oeb                    (io_oeb)
         );
 
         """
diff --git a/verilog/dv/scan_controller/test_scan_controller.py b/verilog/dv/scan_controller/test_scan_controller.py
index 9c5616d..fd64c35 100644
--- a/verilog/dv/scan_controller/test_scan_controller.py
+++ b/verilog/dv/scan_controller/test_scan_controller.py
@@ -33,12 +33,13 @@
         return '?'
 
 @cocotb.test()
-async def test(dut):
+async def internal_controller(dut):
     clock = Clock(dut.clk, 100, units="ns") # 10 MHz
     cocotb.fork(clock.start())
 
     dut.reset.value = 1
     dut.set_clk_div.value = 0
+    dut.driver_sel.value = 0b01   # internal controller
     dut.active_select.value = 12 # 7 seg seconds
     await ClockCycles(dut.clk, 10)
     dut.reset.value = 0
@@ -62,3 +63,4 @@
         #assert decode_seg(dut.seven_seg.value) == i
         #await single_cycle(dut)
         await FallingEdge(dut.slow_clk)
+
diff --git a/verilog/dv/scan_controller/test_scan_controller_tb.v b/verilog/dv/scan_controller/test_scan_controller_tb.v
index c8cea33..15e5082 100644
--- a/verilog/dv/scan_controller/test_scan_controller_tb.v
+++ b/verilog/dv/scan_controller/test_scan_controller_tb.v
@@ -8,6 +8,7 @@
     input wire clk,
     input wire reset,
 
+    input wire [1:0] driver_sel,
     input wire [8:0] active_select,
     input wire [7:0] inputs,
     input wire set_clk_div,
@@ -25,6 +26,7 @@
     assign io_in[20:12] = active_select;
     assign io_in[28:21] = inputs;
     assign io_in[11]    = set_clk_div;
+    assign io_in[9:8]  = driver_sel;
     assign outputs = io_out[36:29];
     assign ready = io_out[37];
     assign slow_clk = io_out[10];
diff --git a/verilog/rtl/scan_controller/scan_controller.v b/verilog/rtl/scan_controller/scan_controller.v
index 8883c35..60b366b 100644
--- a/verilog/rtl/scan_controller/scan_controller.v
+++ b/verilog/rtl/scan_controller/scan_controller.v
@@ -5,22 +5,30 @@
     input  wire reset,
 
     input  wire [8:0] active_select,    // which design is connected to the inputs and outputs
-    input  wire [7:0] inputs,           // inputs to the design
+    input  wire [7:0] inputs,           // inputs to the design (or external scan chain)
     input  wire set_clk_div,            // set clock divider. See module below
-    output wire [7:0] outputs,          // outputs from the design
+    output wire [7:0] outputs,          // outputs from the design (or external scan chain)
     output wire ready,                  // debug output that goes high once per refresh
     output wire slow_clk,               // debug clock divider output
 
-    output wire scan_clk,               // see diagrams below for how the scan chain works
-    output wire scan_data_out,
-    input  wire scan_data_in,
-    output wire scan_select,
-    output wire scan_latch_enable,
+    output wire scan_clk,               // scan chain interface for the tiny designs
+    output wire scan_data_out,          // see diagrams below for how the scan chain works
+    input  wire scan_data_in,           // will be driven by internal driver, external gpio pins, or Caravel logic analyser
+    output wire scan_select,            // external scan chain driver muxes with ins/outs, eg microcontroller outside the ASIC
+    output wire scan_latch_en,
 
-    output wire [8:0] oeb               // caravel harness needs output enable bar set low to enable outputs
+    input  wire la_scan_clk,            // logic analyser scan chain driver, driven by firmware running on Caravel's VexRisc 
+    input  wire la_scan_data_in,
+    output wire la_scan_data_out,
+    input  wire la_scan_select,
+    input  wire la_scan_latch_en,
+
+    input  wire [1:0] driver_sel,       // 00 = external, 01 = internal, 10 = logic analyser
+
+    output wire [`MPRJ_IO_PADS-1:0] oeb // caravel harness needs output enable bar set low to enable outputs
     );
 
-    assign oeb = 8'b0;
+    assign oeb = {`MPRJ_IO_PADS{1'b0}};
 
     parameter NUM_DESIGNS = 8; 
     parameter NUM_IOS     = 8;
@@ -31,6 +39,19 @@
     localparam CAPTURE_STATE = 3;
     localparam LATCH = 4;
                     
+    // scan chain muxing
+    wire ext_scan_clk;
+    wire ext_scan_data_out;
+    wire ext_scan_data_in;
+    wire ext_scan_select;
+    wire ext_scan_latch_en;
+
+    assign scan_clk         = driver_sel == 2'b00 ? ext_scan_clk      : driver_sel == 2'b01 ? int_scan_clk      : la_scan_clk;
+    assign scan_data_out    = driver_sel == 2'b00 ? ext_scan_data_out : driver_sel == 2'b01 ? int_scan_data_out : la_scan_data_out;
+    assign scan_select      = driver_sel == 2'b00 ? ext_scan_select   : driver_sel == 2'b01 ? int_scan_select   : la_scan_select;
+    assign scan_latch_en    = driver_sel == 2'b00 ? ext_scan_latch_en : driver_sel == 2'b01 ? int_scan_latch_en : la_scan_latch_en;
+
+    wire   int_scan_data_in = scan_data_in;
 
     // reg
     reg [8:0] current_design;
@@ -47,10 +68,10 @@
     assign outputs = outputs_r;
     wire [8:0] active_select_rev = NUM_DESIGNS - 1 - active_select;
     assign ready = state == START;
-    assign scan_latch_enable = state == LATCH;
-    assign scan_clk = scan_clk_r;
-    assign scan_data_out = (state == LOAD && current_design == active_select_rev ) ? inputs_r[NUM_IOS-1-num_io] : 0;
-    assign scan_select = scan_select_out_r;
+    wire int_scan_latch_en = state == LATCH;
+    wire int_scan_clk = scan_clk_r;
+    wire int_scan_data_out = (state == LOAD && current_design == active_select_rev ) ? inputs_r[NUM_IOS-1-num_io] : 0;
+    wire int_scan_select = scan_select_out_r;
 
     // clock divider
     clk_divider clk_divider (
@@ -141,7 +162,7 @@
                     if(scan_clk_r) begin
                         num_io <= num_io + 1;
                         if(current_design == active_select_rev)
-                            output_buf[NUM_IOS-1-num_io] <= scan_data_in;
+                            output_buf[NUM_IOS-1-num_io] <= int_scan_data_in;
 
                         if(num_io == NUM_IOS - 1) begin
                             num_io <= 0;