Add DAP and UART LED options. Use a debounce for UART LEDs.

Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
diff --git a/include/DAP_config.h b/include/DAP_config.h
index e05e27b..4e2e155 100755
--- a/include/DAP_config.h
+++ b/include/DAP_config.h
@@ -493,14 +493,22 @@
            - 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit.
            - 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit.
 */
-__STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) {}
+__STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) {
+#ifdef PICOPROBE_DAP_CONNECTED_LED
+  gpio_put(PICOPROBE_DAP_CONNECTED_LED, bit);
+#endif
+}
 
 /** Debug Unit: Set status Target Running LED.
 \param bit status of the Target Running LED.
            - 1: Target Running LED ON: program execution in target started.
            - 0: Target Running LED OFF: program execution in target stopped.
 */
-__STATIC_INLINE void LED_RUNNING_OUT (uint32_t bit) {}
+__STATIC_INLINE void LED_RUNNING_OUT (uint32_t bit) {
+#ifdef PICOPROBE_DAP_RUNNING_LED
+  gpio_put(PICOPROBE_DAP_RUNNING_LED, bit);
+#endif
+}
 
 ///@}
 
diff --git a/src/cdc_uart.c b/src/cdc_uart.c
index 45942cf..2eb4ec4 100644
--- a/src/cdc_uart.c
+++ b/src/cdc_uart.c
@@ -36,6 +36,11 @@
 
 static uint8_t tx_buf[CFG_TUD_CDC_TX_BUFSIZE];
 static uint8_t rx_buf[CFG_TUD_CDC_RX_BUFSIZE];
+// Actually s^-1 so 25ms
+#define DEBOUNCE_MS 40
+static uint debounce_ticks = 5;
+static uint tx_led_debounce;
+static uint rx_led_debounce;
 
 void cdc_uart_init(void) {
     gpio_set_function(PICOPROBE_UART_TX, GPIO_FUNC_UART);
@@ -61,21 +66,43 @@
         /* Implicit overflow if we don't write all the bytes to the host.
          * Also throw away bytes if we can't write... */
         if (rx_len) {
+#ifdef PICOPROBE_UART_RX_LED
+          gpio_put(PICOPROBE_UART_RX_LED, 1);
+          rx_led_debounce = debounce_ticks;
+#endif
           written = MIN(tud_cdc_write_available(), rx_len);
           if (written > 0) {
             tud_cdc_write(rx_buf, written);
             tud_cdc_write_flush();
           }
+        } else {
+#ifdef PICOPROBE_UART_RX_LED
+          if (rx_led_debounce)
+            rx_led_debounce--;
+          else
+            gpio_put(PICOPROBE_UART_RX_LED, 0);
+#endif
         }
 
       /* Reading from a firehose and writing to a FIFO. */
       size_t watermark = MIN(tud_cdc_available(), sizeof(tx_buf));
       if (watermark > 0) {
         size_t tx_len;
+#ifdef PICOPROBE_UART_TX_LED
+        gpio_put(PICOPROBE_UART_TX_LED, 1);
+        tx_led_debounce = debounce_ticks;
+#endif
         /* Batch up to half a FIFO of data - don't clog up on RX */
         watermark = MIN(watermark, 16);
         tx_len = tud_cdc_read(tx_buf, watermark);
         uart_write_blocking(PICOPROBE_UART_INTERFACE, tx_buf, tx_len);
+      } else {
+#ifdef PICOPROBE_UART_TX_LED
+          if (tx_led_debounce)
+            tx_led_debounce--;
+          else
+            gpio_put(PICOPROBE_UART_TX_LED, 0);
+#endif
       }
     } else if (was_connected) {
       tud_cdc_write_clear();
@@ -102,10 +129,10 @@
    * fill up half a FIFO. Millis is too coarse for integer divide.
    */
   uint32_t micros = (1000 * 1000 * 16 * 10) / MAX(line_coding->bit_rate, 1);
-
   /* Modifying state, so park the thread before changing it. */
   vTaskSuspend(uart_taskhandle);
   interval = MAX(1, micros / ((1000 * 1000) / configTICK_RATE_HZ));
+  debounce_ticks = MAX(1, configTICK_RATE_HZ / (interval * DEBOUNCE_MS));
   picoprobe_info("New baud rate %d micros %d interval %u\n",
                   line_coding->bit_rate, micros, interval);
   uart_deinit(PICOPROBE_UART_INTERFACE);
@@ -119,8 +146,16 @@
 {
   /* CDC drivers use linestate as a bodge to activate/deactivate the interface.
    * Resume our UART polling on activate, stop on deactivate */
-  if (!dtr && !rts)
+  if (!dtr && !rts) {
     vTaskSuspend(uart_taskhandle);
-  else
+#ifdef PICOPROBE_UART_RX_LED
+    gpio_put(PICOPROBE_UART_RX_LED, 0);
+    rx_led_debounce = 0;
+#endif
+#ifdef PICOPROBE_UART_RX_LED
+    gpio_put(PICOPROBE_UART_TX_LED, 0);
+    tx_led_debounce = 0;
+#endif
+  } else
     vTaskResume(uart_taskhandle);
 }
diff --git a/src/led.c b/src/led.c
index 23fd81b..95a2836 100644
--- a/src/led.c
+++ b/src/led.c
@@ -35,14 +35,27 @@
 
 void led_init(void) {
     led_count = 0;
-
     gpio_init(PICOPROBE_LED);
     gpio_set_dir(PICOPROBE_LED, GPIO_OUT);
     gpio_put(PICOPROBE_LED, 1);
+#ifdef PICOPROBE_DAP_CONNECTED_LED
+    gpio_init(PICOPROBE_DAP_CONNECTED_LED);
+    gpio_set_dir(PICOPROBE_DAP_CONNECTED_LED, GPIO_OUT);
+#endif
+#ifdef PICOPROBE_DAP_RUNNING_LED
+    gpio_init(PICOPROBE_DAP_RUNNING_LED);
+    gpio_set_dir(PICOPROBE_DAP_RUNNING_LED, GPIO_OUT);
+#endif
+#ifdef PICOPROBE_UART_RX_LED
+    gpio_init(PICOPROBE_UART_RX_LED);
+    gpio_set_dir(PICOPROBE_UART_RX_LED, GPIO_OUT);
+#endif
+#ifdef PICOPROBE_UART_TX_LED
+    gpio_init(PICOPROBE_UART_TX_LED);
+    gpio_set_dir(PICOPROBE_UART_TX_LED, GPIO_OUT);
+#endif
 }
 
-
-
 void led_task(void) {
     if (led_count != 0) {
         --led_count;