Browse Source

continue work on firmware. added debug console. pmw irq counters.

Thomas Buck 1 year ago
parent
commit
3902f240d5

+ 7
- 0
firmware/CMakeLists.txt View File

@@ -13,7 +13,9 @@ add_executable(trackball)
13 13
 
14 14
 target_sources(trackball PUBLIC
15 15
     src/main.c
16
+    src/console.c
16 17
     src/log.c
18
+    src/util.c
17 19
     src/pmw3360.c
18 20
     src/usb.c
19 21
     src/usb_cdc.c
@@ -24,6 +26,11 @@ target_sources(trackball PUBLIC
24 26
 # Make sure TinyUSB can find tusb_config.h
25 27
 target_include_directories(trackball PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
26 28
 
29
+target_compile_options(trackball PUBLIC
30
+    -Wall
31
+    -Werror
32
+)
33
+
27 34
 # pull in common dependencies
28 35
 target_link_libraries(trackball
29 36
     pico_stdlib

+ 1
- 1
firmware/debug.sh View File

@@ -15,4 +15,4 @@ echo Opening picocom terminal
15 15
 echo "[C-a] [C-x] to exit"
16 16
 echo
17 17
 
18
-picocom -q $SERIAL
18
+picocom -q --omap crcrlf $SERIAL

+ 1
- 1
firmware/flash.sh View File

@@ -8,7 +8,7 @@ MOUNT=/mnt/tmp
8 8
 if [ ! -e $DISK ]
9 9
 then
10 10
     echo Resetting Raspberry Pi Pico
11
-    echo -n -e "\\x1b" > $SERIAL
11
+    echo -n -e "\\x18" > $SERIAL
12 12
 fi
13 13
 
14 14
 echo -n Waiting for disk to appear

+ 11
- 0
firmware/include/console.h View File

@@ -0,0 +1,11 @@
1
+/*
2
+ * console.h
3
+ */
4
+
5
+#ifndef __CONSOLE_H__
6
+#define __CONSOLE_H__
7
+
8
+void cnsl_init(void);
9
+void cnsl_handle_input(const char *buf, uint32_t len);
10
+
11
+#endif // __CONSOLE_H__

+ 8
- 4
firmware/include/log.h View File

@@ -5,14 +5,18 @@
5 5
 #ifndef __LOG_H__
6 6
 #define __LOG_H__
7 7
 
8
-void debug_log(const char *format, ...) __attribute__((format(printf, 1, 2)));
9
-
10
-#define debug(fmt, ...) debug_log( \
11
-        "%08u %s: " fmt "\r\n", \
8
+// for output that is stored in the debug log.
9
+// will be re-played from buffer when terminal connects
10
+#define debug(fmt, ...) debug_log(true, \
11
+        "%08lu %s: " fmt "\r\n", \
12 12
         to_ms_since_boot(get_absolute_time()), \
13 13
         __func__, \
14 14
         ##__VA_ARGS__)
15 15
 
16
+// for interactive output. is not stored or re-played.
17
+#define print(fmt, ...) debug_log(false, fmt "\r\n", ##__VA_ARGS__)
18
+
19
+void debug_log(bool log, const char *format, ...) __attribute__((format(printf, 2, 3)));
16 20
 void log_dump_to_usb(void);
17 21
 
18 22
 #endif // __LOG_H__

+ 2
- 0
firmware/include/pmw3360.h View File

@@ -7,4 +7,6 @@
7 7
 
8 8
 int pmw_init(void);
9 9
 
10
+void print_pmw_status(void);
11
+
10 12
 #endif // __PMW3360_H__

+ 5
- 0
firmware/include/pmw3360_registers.h View File

@@ -57,6 +57,11 @@
57 57
 
58 58
 #define WRITE_BIT 0x80
59 59
 
60
+#define REG_MOTION_MOT 7
61
+#define REG_MOTION_LIFT 3
62
+#define REG_MOTION_OP_1 1
63
+#define REG_MOTION_OP_2 2
64
+
60 65
 struct pmw_motion_report {
61 66
     uint8_t motion;
62 67
     uint8_t observation;

+ 1
- 1
firmware/include/pmw3360_srom.h View File

@@ -11,7 +11,7 @@
11 11
 // Firmware "PMW3360DM_srom_0x04"
12 12
 
13 13
 static const uint16_t pmw_fw_length = 4094;
14
-static const uint8_t pmw_fw_data[] = {
14
+static const uint8_t pmw_fw_data[4094] = {
15 15
 0x01, 0x04, 0x8e, 0x96, 0x6e, 0x77, 0x3e, 0xfe, 0x7e, 0x5f, 0x1d, 0xb8, 0xf2, 0x66, 0x4e,
16 16
 0xff, 0x5d, 0x19, 0xb0, 0xc2, 0x04, 0x69, 0x54, 0x2a, 0xd6, 0x2e, 0xbf, 0xdd, 0x19, 0xb0,
17 17
 0xc3, 0xe5, 0x29, 0xb1, 0xe0, 0x23, 0xa5, 0xa9, 0xb1, 0xc1, 0x00, 0x82, 0x67, 0x4c, 0x1a,

+ 0
- 10
firmware/include/usb.h View File

@@ -5,17 +5,7 @@
5 5
 #ifndef __USB_H__
6 6
 #define __USB_H__
7 7
 
8
-enum  {
9
-    BLINK_NOT_MOUNTED = 250,
10
-    BLINK_MOUNTED = 1000,
11
-    BLINK_SUSPENDED = 2500,
12
-};
13
-
14
-extern uint32_t blink_interval_ms;
15
-
16 8
 void usb_init(void);
17 9
 void usb_run(void);
18 10
 
19
-void usb_cdc_write(const char *buf, uint32_t count);
20
-
21 11
 #endif // __USB_H__

+ 10
- 0
firmware/include/usb_cdc.h View File

@@ -0,0 +1,10 @@
1
+/*
2
+ * usb_cdc.h
3
+ */
4
+
5
+#ifndef __USB_CDC_H__
6
+#define __USB_CDC_H__
7
+
8
+void usb_cdc_write(const char *buf, uint32_t count);
9
+
10
+#endif // __USB_CDC_H__

+ 8
- 7
firmware/include/usb_descriptors.h View File

@@ -25,13 +25,14 @@
25 25
 #ifndef USB_DESCRIPTORS_H_
26 26
 #define USB_DESCRIPTORS_H_
27 27
 
28
-enum
29
-{
30
-  REPORT_ID_KEYBOARD = 1,
31
-  REPORT_ID_MOUSE,
32
-  REPORT_ID_CONSUMER_CONTROL,
33
-  REPORT_ID_GAMEPAD,
34
-  REPORT_ID_COUNT
28
+enum {
29
+    REPORT_ID_KEYBOARD = 1,
30
+    REPORT_ID_MOUSE,
31
+    REPORT_ID_CONSUMER_CONTROL,
32
+    REPORT_ID_GAMEPAD,
33
+    REPORT_ID_COUNT
35 34
 };
36 35
 
36
+void usb_descriptor_init_id(void);
37
+
37 38
 #endif /* USB_DESCRIPTORS_H_ */

+ 10
- 0
firmware/include/usb_hid.h View File

@@ -0,0 +1,10 @@
1
+/*
2
+ * usb_hid.h
3
+ */
4
+
5
+#ifndef __USB_HID_H__
6
+#define __USB_HID_H__
7
+
8
+void hid_task(void);
9
+
10
+#endif // __USB_HID_H__

+ 13
- 0
firmware/include/util.h View File

@@ -0,0 +1,13 @@
1
+/*
2
+ * util.h
3
+ */
4
+
5
+#ifndef __UTIL_H__
6
+#define __UTIL_H__
7
+
8
+void heartbeat_init(void);
9
+void heartbeat_run(void);
10
+
11
+void reset_to_bootloader(void);
12
+
13
+#endif // __UTIL_H__

+ 77
- 0
firmware/src/console.c View File

@@ -0,0 +1,77 @@
1
+/*
2
+ * console.c
3
+ */
4
+
5
+#include <string.h>
6
+#include "pico/stdlib.h"
7
+#include "log.h"
8
+#include "pmw3360.h"
9
+#include "console.h"
10
+
11
+#define CNSL_BUFF_SIZE 1024
12
+
13
+static char cnsl_line_buff[CNSL_BUFF_SIZE + 1];
14
+static uint32_t cnsl_buff_pos = 0;
15
+
16
+static void cnsl_interpret(const char *line) {
17
+    if ((strcmp(line, "help") == 0)
18
+            || (strcmp(line, "h") == 0)
19
+            || (strcmp(line, "?") == 0)) {
20
+        print("Trackball Firmware Usage:");
21
+        print("    help - print this message");
22
+        print("     pmw - print PMW3360 status");
23
+        print("    \\x18 - reset to bootloader");
24
+    } else if (strcmp(line, "pmw") == 0) {
25
+        print_pmw_status();
26
+    } else {
27
+        print("unknown command \"%s\"", line);
28
+    }
29
+}
30
+
31
+void cnsl_init(void) {
32
+    cnsl_buff_pos = 0;
33
+    for (int i = 0; i < sizeof(cnsl_line_buff); i++) {
34
+        cnsl_line_buff[i] = '\0';
35
+    }
36
+}
37
+
38
+static int32_t cnsl_find_line_end(void) {
39
+    for (int32_t i = 0; i < cnsl_buff_pos; i++) {
40
+        if ((cnsl_line_buff[i] == '\r') || (cnsl_line_buff[i] == '\n')) {
41
+            return i;
42
+        }
43
+    }
44
+    return -1;
45
+}
46
+
47
+void cnsl_handle_input(const char *buf, uint32_t len) {
48
+    if ((cnsl_buff_pos + len) > CNSL_BUFF_SIZE) {
49
+        debug("error: console input buffer overflow! %lu > %u", cnsl_buff_pos + len, CNSL_BUFF_SIZE);
50
+        cnsl_init();
51
+    }
52
+
53
+    memcpy(cnsl_line_buff + cnsl_buff_pos, buf, len);
54
+    cnsl_buff_pos += len;
55
+
56
+    int32_t line_len = cnsl_find_line_end();
57
+    if (line_len < 0) {
58
+        // user has not pressed enter yet
59
+        return;
60
+    }
61
+
62
+    // convert line to C-style string
63
+    cnsl_line_buff[line_len] = '\0';
64
+
65
+    // TODO handle backspace and other terminal commands?
66
+
67
+    cnsl_interpret(cnsl_line_buff);
68
+
69
+    // clear string and move following data over
70
+    uint32_t cnt = line_len + 1;
71
+    if (cnsl_line_buff[line_len + 1] == '\n') {
72
+        cnt++;
73
+    }
74
+    memset(cnsl_line_buff, '\0', cnt);
75
+    memmove(cnsl_line_buff, cnsl_line_buff + cnt, sizeof(cnsl_line_buff) - cnt);
76
+    cnsl_buff_pos -= cnt;
77
+}

+ 6
- 3
firmware/src/log.c View File

@@ -5,7 +5,7 @@
5 5
 #include <stdarg.h>
6 6
 #include <stdio.h>
7 7
 #include "pico/stdlib.h"
8
-#include "usb.h"
8
+#include "usb_cdc.h"
9 9
 #include "log.h"
10 10
 
11 11
 char log_buff[4096];
@@ -66,7 +66,7 @@ static int format_debug_log(char *buff, size_t len, const char *format, va_list
66 66
     return l;
67 67
 }
68 68
 
69
-void debug_log(const char* format, ...) {
69
+void debug_log(bool log, const char* format, ...) {
70 70
     static char line_buff[256];
71 71
 
72 72
     va_list args;
@@ -76,6 +76,9 @@ void debug_log(const char* format, ...) {
76 76
 
77 77
     if ((l > 0) && (l <= sizeof(line_buff))) {
78 78
         usb_cdc_write(line_buff, l);
79
-        add_to_log(line_buff, l);
79
+
80
+        if (log) {
81
+            add_to_log(line_buff, l);
82
+        }
80 83
     }
81 84
 }

+ 5
- 0
firmware/src/main.c View File

@@ -4,16 +4,21 @@
4 4
 
5 5
 #include "pico/stdlib.h"
6 6
 
7
+#include "util.h"
8
+#include "console.h"
7 9
 #include "log.h"
8 10
 #include "usb.h"
9 11
 #include "pmw3360.h"
10 12
 
11 13
 int main(void) {
14
+    heartbeat_init();
15
+    cnsl_init();
12 16
     usb_init();
13 17
     pmw_init();
14 18
     debug("init done");
15 19
 
16 20
     while (1) {
21
+        heartbeat_run();
17 22
         usb_run();
18 23
     }
19 24
 

+ 87
- 13
firmware/src/pmw3360.c View File

@@ -21,6 +21,8 @@
21 21
 #include "pico/binary_info.h"
22 22
 #include "hardware/spi.h"
23 23
 
24
+#define PMW_IRQ_COUNTERS
25
+
24 26
 #include "log.h"
25 27
 #include "pmw3360_registers.h"
26 28
 #include "pmw3360_srom.h"
@@ -32,6 +34,32 @@
32 34
 
33 35
 #define PMW_MOTION_PIN 20
34 36
 
37
+#ifdef PMW_IRQ_COUNTERS
38
+static uint64_t pmw_irq_count_all = 0;
39
+static uint64_t pmw_irq_count_motion = 0;
40
+static uint64_t pmw_irq_count_no_motion = 0;
41
+static uint64_t pmw_irq_count_on_surface = 0;
42
+static uint64_t pmw_irq_count_lifted = 0;
43
+static uint64_t pmw_irq_count_run = 0;
44
+static uint64_t pmw_irq_count_rest1 = 0;
45
+static uint64_t pmw_irq_count_rest2 = 0;
46
+static uint64_t pmw_irq_count_rest3 = 0;
47
+#endif // PMW_IRQ_COUNTERS
48
+
49
+void print_pmw_status(void) {
50
+#ifdef PMW_IRQ_COUNTERS
51
+    print("    pmw_irq_cnt_all = %llu", pmw_irq_count_all);
52
+    print(" pmw_irq_cnt_motion = %llu", pmw_irq_count_motion);
53
+    print("pmw_irq_cnt_no_move = %llu", pmw_irq_count_no_motion);
54
+    print("pmw_irq_cnt_surface = %llu", pmw_irq_count_on_surface);
55
+    print(" pmw_irq_cnt_lifted = %llu", pmw_irq_count_lifted);
56
+    print("    pmw_irq_cnt_run = %llu", pmw_irq_count_run);
57
+    print("  pmw_irq_cnt_rest1 = %llu", pmw_irq_count_rest1);
58
+    print("  pmw_irq_cnt_rest2 = %llu", pmw_irq_count_rest2);
59
+    print("  pmw_irq_cnt_rest3 = %llu", pmw_irq_count_rest3);
60
+#endif // PMW_IRQ_COUNTERS
61
+}
62
+
35 63
 static inline void pmw_cs_select() {
36 64
     asm volatile("nop \n nop \n nop");
37 65
     gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 0); // Active low
@@ -66,7 +94,7 @@ static uint8_t pmw_read_register(uint8_t reg) {
66 94
     return buf;
67 95
 }
68 96
 
69
-static void pmw_write_register_burst(uint8_t reg, uint8_t *buf, uint16_t len) {
97
+static void pmw_write_register_burst(uint8_t reg, const uint8_t *buf, uint16_t len) {
70 98
     reg |= WRITE_BIT;
71 99
     pmw_cs_select();
72 100
     spi_write_blocking(spi_default, &reg, 1);
@@ -83,10 +111,10 @@ static void pmw_read_register_burst(uint8_t reg, uint8_t *buf, uint16_t len) {
83 111
     reg &= ~WRITE_BIT;
84 112
     pmw_cs_select();
85 113
     spi_write_blocking(spi_default, &reg, 1);
86
-    sleep_us(15); // TODO tSRAD_MOTBR
87
-    spi_read_blocking(spi_default, 0x00, buf, len);
114
+    sleep_ms(1);//sleep_us(15); // TODO tSRAD_MOTBR
115
+    spi_read_blocking(spi_default, 0, buf, len);
88 116
     pmw_cs_deselect();
89
-    sleep_us(1); // TODO tBEXIT
117
+    sleep_us(1);
90 118
 }
91 119
 
92 120
 static uint8_t pmw_srom_download(void) {
@@ -102,8 +130,12 @@ static uint8_t pmw_srom_download(void) {
102 130
     // Write 0x18 to SROM_Enable register again to start SROM Download
103 131
     pmw_write_register(REG_SROM_ENABLE, 0x18);
104 132
 
133
+    sleep_us(120);
134
+
105 135
     // Write SROM file into SROM_Load_Burst register, 1st data must start with SROM_Load_Burst address.
106
-    pmw_write_register_burst(REG_SROM_LOAD_BURST, (uint8_t *)pmw_fw_data, pmw_fw_length);
136
+    pmw_write_register_burst(REG_SROM_LOAD_BURST, pmw_fw_data, pmw_fw_length);
137
+
138
+    sleep_us(200);
107 139
 
108 140
     // Read the SROM_ID register to verify the ID before any other register reads or writes
109 141
     uint8_t srom_id = pmw_read_register(REG_SROM_ID);
@@ -127,7 +159,7 @@ static uint8_t pmw_power_up(void) {
127 159
     return srom_id;
128 160
 }
129 161
 
130
-static void pmw_motion_read(void) {
162
+static struct pmw_motion_report pmw_motion_read(void) {
131 163
     // Write any value to Motion_Burst register
132 164
     pmw_write_register(REG_MOTION_BURST, 0x42);
133 165
 
@@ -135,7 +167,7 @@ static void pmw_motion_read(void) {
135 167
     struct pmw_motion_report motion_report;
136 168
     pmw_read_register_burst(REG_MOTION_BURST, (uint8_t *)&motion_report, sizeof(motion_report));
137 169
 
138
-    // TODO do something with data
170
+    return motion_report;
139 171
 }
140 172
 
141 173
 static uint16_t pmw_srom_checksum(void) {
@@ -161,16 +193,55 @@ static void pmw_spi_init(void) {
161 193
     gpio_set_dir(PICO_DEFAULT_SPI_CSN_PIN, GPIO_OUT);
162 194
     gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 1);
163 195
 
164
-    // Make the SPI pins available to picotool
196
+    spi_set_format(spi_default,
197
+                   8, // Number of bits per transfer
198
+                   1, // Polarity (CPOL)
199
+                   1, // Phase (CPHA)
200
+                   SPI_MSB_FIRST);
201
+
202
+    // make the SPI pins available to picotool
165 203
     bi_decl(bi_3pins_with_func(PICO_DEFAULT_SPI_RX_PIN, PICO_DEFAULT_SPI_TX_PIN, PICO_DEFAULT_SPI_SCK_PIN, GPIO_FUNC_SPI));
166 204
     bi_decl(bi_1pin_with_name(PICO_DEFAULT_SPI_CSN_PIN, "SPI CS"));
167 205
 }
168 206
 
207
+static void pmw_handle_interrupt(void) {
208
+    struct pmw_motion_report motion_report = pmw_motion_read();
209
+
210
+#ifdef PMW_IRQ_COUNTERS
211
+    pmw_irq_count_all++;
212
+
213
+    if (motion_report.motion & (1 << REG_MOTION_MOT)) {
214
+        pmw_irq_count_motion++;
215
+    } else {
216
+        pmw_irq_count_no_motion++;
217
+    }
218
+
219
+    if (motion_report.motion & (1 << REG_MOTION_LIFT)) {
220
+        pmw_irq_count_lifted++;
221
+    } else {
222
+        pmw_irq_count_on_surface++;
223
+    }
224
+
225
+    if ((motion_report.motion & (1 << REG_MOTION_OP_1))
226
+            && (motion_report.motion & (1 << REG_MOTION_OP_2))) {
227
+        pmw_irq_count_rest3++;
228
+    } else if (motion_report.motion & (1 << REG_MOTION_OP_1)) {
229
+        pmw_irq_count_rest1++;
230
+    } else if (motion_report.motion & (1 << REG_MOTION_OP_2)) {
231
+        pmw_irq_count_rest2++;
232
+    } else {
233
+        pmw_irq_count_run++;
234
+    }
235
+#endif // PMW_IRQ_COUNTERS
236
+
237
+    // TODO
238
+}
239
+
169 240
 static void pmw_motion_irq(void) {
170 241
     if (gpio_get_irq_event_mask(PMW_MOTION_PIN) & GPIO_IRQ_EDGE_FALL) {
171 242
         gpio_acknowledge_irq(PMW_MOTION_PIN, GPIO_IRQ_EDGE_FALL);
172 243
 
173
-        // TODO
244
+        pmw_handle_interrupt();
174 245
     }
175 246
 }
176 247
 
@@ -186,11 +257,11 @@ int pmw_init(void) {
186 257
 
187 258
     debug("SROM ID: 0x%02X", srom_id);
188 259
     debug("Product ID: 0x%02X", prod_id);
189
-    debug("~Prod. ID: 0x%02X", inv_prod_id);
260
+    debug("~ Prod. ID: 0x%02X", inv_prod_id);
190 261
     debug("Revision ID: 0x%02X", rev_id);
191 262
     debug("SROM CRC: 0x%04X", srom_checksum);
192 263
 
193
-    if (prod_id != (~inv_prod_id)) {
264
+    if (prod_id != ((~inv_prod_id) & 0xFF)) {
194 265
         debug("SPI communication error (0x%02X != ~0x%02X)", prod_id, inv_prod_id);
195 266
         return -1;
196 267
     }
@@ -202,8 +273,11 @@ int pmw_init(void) {
202 273
     pmw_write_register(REG_CONFIG2, 0x00);
203 274
 #endif
204 275
 
205
-    // TODO setup MOTION pin interrupt to handle reading data?
206
-    //gpio_add_raw_irq_handler(PMW_MOTION_PIN, pmw_motion_irq);
276
+    // setup MOTION pin interrupt to handle reading data
277
+    gpio_add_raw_irq_handler(PMW_MOTION_PIN, pmw_motion_irq);
278
+
279
+    // make MOTION pin available to picotool
280
+    bi_decl(bi_1pin_with_name(PMW_MOTION_PIN, "PMW3360 MOTION"));
207 281
 
208 282
     return 0;
209 283
 }

+ 2
- 29
firmware/src/usb.c View File

@@ -27,13 +27,10 @@
27 27
 #include "tusb.h"
28 28
 
29 29
 #include "usb_descriptors.h"
30
+#include "usb_cdc.h"
31
+#include "usb_hid.h"
30 32
 #include "usb.h"
31 33
 
32
-void led_blinking_task(void);
33
-void usb_descriptor_init_id(void);
34
-void cdc_task(void);
35
-void hid_task(void);
36
-
37 34
 void usb_init(void) {
38 35
     usb_descriptor_init_id();
39 36
 
@@ -43,22 +40,15 @@ void usb_init(void) {
43 40
 
44 41
 void usb_run(void) {
45 42
     tud_task();
46
-    led_blinking_task();
47
-
48
-    cdc_task();
49 43
     hid_task();
50 44
 }
51 45
 
52
-uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
53
-
54 46
 // Invoked when device is mounted
55 47
 void tud_mount_cb(void) {
56
-    blink_interval_ms = BLINK_MOUNTED;
57 48
 }
58 49
 
59 50
 // Invoked when device is unmounted
60 51
 void tud_umount_cb(void) {
61
-    blink_interval_ms = BLINK_NOT_MOUNTED;
62 52
 }
63 53
 
64 54
 // Invoked when usb bus is suspended
@@ -66,25 +56,8 @@ void tud_umount_cb(void) {
66 56
 // Within 7ms, device must draw an average of current less than 2.5 mA from bus
67 57
 void tud_suspend_cb(bool remote_wakeup_en) {
68 58
     (void) remote_wakeup_en;
69
-    blink_interval_ms = BLINK_SUSPENDED;
70 59
 }
71 60
 
72 61
 // Invoked when usb bus is resumed
73 62
 void tud_resume_cb(void) {
74
-    blink_interval_ms = BLINK_MOUNTED;
75
-}
76
-
77
-void led_blinking_task(void) {
78
-    static uint32_t start_ms = 0;
79
-    static bool led_state = false;
80
-
81
-    // blink is disabled
82
-    if (!blink_interval_ms) return;
83
-
84
-    // Blink every interval ms
85
-    if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time
86
-    start_ms += blink_interval_ms;
87
-
88
-    board_led_write(led_state);
89
-    led_state = 1 - led_state; // toggle
90 63
 }

+ 21
- 14
firmware/src/usb_cdc.c View File

@@ -25,11 +25,12 @@
25 25
 
26 26
 #include "bsp/board.h"
27 27
 #include "tusb.h"
28
-#include "pico/bootrom.h"
29 28
 
29
+#include "console.h"
30 30
 #include "log.h"
31
+#include "util.h"
31 32
 #include "usb_descriptors.h"
32
-#include "usb.h"
33
+#include "usb_cdc.h"
33 34
 
34 35
 void usb_cdc_write(const char *buf, uint32_t count) {
35 36
 #ifndef DISABLE_CDC_DTR_CHECK
@@ -38,41 +39,41 @@ void usb_cdc_write(const char *buf, uint32_t count) {
38 39
     }
39 40
 #endif // DISABLE_CDC_DTR_CHECK
40 41
 
42
+    // implemented similar to Pico SDK stdio usb
41 43
     uint32_t len = 0;
42
-
43 44
     while (len < count) {
44 45
         uint32_t n = count - len;
45 46
         uint32_t available = tud_cdc_write_available();
46 47
 
48
+        // only write as much as possible
47 49
         if (n > available) {
48 50
             n = available;
49 51
         }
50 52
 
51 53
         len += tud_cdc_write(buf + len, n);
54
+
55
+        // run tud_task to actually move stuff from FIFO
52 56
         tud_task();
53 57
         tud_cdc_write_flush();
54 58
     }
55 59
 }
56 60
 
57 61
 void cdc_task(void) {
62
+    const uint32_t cdc_buf_len = 64;
63
+
58 64
     if (tud_cdc_available()) {
59
-        char buf[64];
60
-        uint32_t count = tud_cdc_read(buf, sizeof(buf));
65
+        char buf[cdc_buf_len + 1];
66
+        uint32_t count = tud_cdc_read(buf, cdc_buf_len);
61 67
 
62
-        if ((count >= 1) && (buf[0] == 27)) {
63
-            // escape key
68
+        if ((count >= 1) && (buf[0] == 0x18)) {
69
+            // ASCII 0x18 = CAN (cancel)
64 70
             debug("switching to bootloader");
65
-
66
-#ifdef PICO_DEFAULT_LED_PIN
67
-            reset_usb_boot(1 << PICO_DEFAULT_LED_PIN, 0);
68
-#else
69
-            reset_usb_boot(0, 0);
70
-#endif
71
+            reset_to_bootloader();
71 72
         } else {
72 73
             // echo back
73 74
             usb_cdc_write(buf, count);
74 75
 
75
-            // TODO handle user input
76
+            cnsl_handle_input(buf, count);
76 77
         }
77 78
     }
78 79
 }
@@ -85,7 +86,12 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) {
85 86
     static bool last_dtr = false;
86 87
 
87 88
     if (dtr && !last_dtr) {
89
+        // clear left-over console input
90
+        cnsl_init();
91
+
92
+        // show past history
88 93
         log_dump_to_usb();
94
+
89 95
         debug("terminal connected");
90 96
     } else if (!dtr && last_dtr) {
91 97
         debug("terminal disconnected");
@@ -97,4 +103,5 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) {
97 103
 // invoked when CDC interface received data from host
98 104
 void tud_cdc_rx_cb(uint8_t itf) {
99 105
     (void) itf;
106
+    cdc_task();
100 107
 }

+ 3
- 3
firmware/src/usb_hid.c View File

@@ -27,7 +27,7 @@
27 27
 #include "tusb.h"
28 28
 
29 29
 #include "usb_descriptors.h"
30
-#include "usb.h"
30
+#include "usb_hid.h"
31 31
 
32 32
 static void send_hid_report(uint8_t report_id, uint32_t btn) {
33 33
     // skip if hid is not ready yet
@@ -179,12 +179,12 @@ void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id,
179 179
 
180 180
             if (kbd_leds & KEYBOARD_LED_CAPSLOCK) {
181 181
                 // Capslock On: disable blink, turn led on
182
-                blink_interval_ms = 0;
182
+                //blink_interval_ms = 0;
183 183
                 board_led_write(true);
184 184
             } else {
185 185
                 // Caplocks Off: back to normal blink
186 186
                 board_led_write(false);
187
-                blink_interval_ms = BLINK_MOUNTED;
187
+                //blink_interval_ms = BLINK_MOUNTED;
188 188
             }
189 189
         }
190 190
     }

+ 39
- 0
firmware/src/util.c View File

@@ -0,0 +1,39 @@
1
+/*
2
+ * util.c
3
+ */
4
+
5
+#include "pico/stdlib.h"
6
+#include "pico/bootrom.h"
7
+#include "util.h"
8
+
9
+#define HEARTBEAT_INTERVAL_MS 500
10
+
11
+#ifdef PICO_DEFAULT_LED_PIN
12
+static uint32_t last_heartbeat = 0;
13
+#endif // PICO_DEFAULT_LED_PIN
14
+
15
+void heartbeat_init(void) {
16
+#ifdef PICO_DEFAULT_LED_PIN
17
+    gpio_init(PICO_DEFAULT_LED_PIN);
18
+    gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
19
+    gpio_put(PICO_DEFAULT_LED_PIN, 1);
20
+#endif // PICO_DEFAULT_LED_PIN
21
+}
22
+
23
+void heartbeat_run(void) {
24
+#ifdef PICO_DEFAULT_LED_PIN
25
+    uint32_t now = to_ms_since_boot(get_absolute_time());
26
+    if (now >= (last_heartbeat + HEARTBEAT_INTERVAL_MS)) {
27
+        last_heartbeat = now;
28
+        gpio_xor_mask(1 << PICO_DEFAULT_LED_PIN);
29
+    }
30
+#endif // PICO_DEFAULT_LED_PIN
31
+}
32
+
33
+void reset_to_bootloader(void) {
34
+#ifdef PICO_DEFAULT_LED_PIN
35
+    reset_usb_boot(1 << PICO_DEFAULT_LED_PIN, 0);
36
+#else // ! PICO_DEFAULT_LED_PIN
37
+    reset_usb_boot(0, 0);
38
+#endif // PICO_DEFAULT_LED_PIN
39
+}

Loading…
Cancel
Save