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
 
13
 
14
 target_sources(trackball PUBLIC
14
 target_sources(trackball PUBLIC
15
     src/main.c
15
     src/main.c
16
+    src/console.c
16
     src/log.c
17
     src/log.c
18
+    src/util.c
17
     src/pmw3360.c
19
     src/pmw3360.c
18
     src/usb.c
20
     src/usb.c
19
     src/usb_cdc.c
21
     src/usb_cdc.c
24
 # Make sure TinyUSB can find tusb_config.h
26
 # Make sure TinyUSB can find tusb_config.h
25
 target_include_directories(trackball PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
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
 # pull in common dependencies
34
 # pull in common dependencies
28
 target_link_libraries(trackball
35
 target_link_libraries(trackball
29
     pico_stdlib
36
     pico_stdlib

+ 1
- 1
firmware/debug.sh View File

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

+ 1
- 1
firmware/flash.sh View File

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

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

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
 #ifndef __LOG_H__
5
 #ifndef __LOG_H__
6
 #define __LOG_H__
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
         to_ms_since_boot(get_absolute_time()), \
12
         to_ms_since_boot(get_absolute_time()), \
13
         __func__, \
13
         __func__, \
14
         ##__VA_ARGS__)
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
 void log_dump_to_usb(void);
20
 void log_dump_to_usb(void);
17
 
21
 
18
 #endif // __LOG_H__
22
 #endif // __LOG_H__

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

7
 
7
 
8
 int pmw_init(void);
8
 int pmw_init(void);
9
 
9
 
10
+void print_pmw_status(void);
11
+
10
 #endif // __PMW3360_H__
12
 #endif // __PMW3360_H__

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

57
 
57
 
58
 #define WRITE_BIT 0x80
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
 struct pmw_motion_report {
65
 struct pmw_motion_report {
61
     uint8_t motion;
66
     uint8_t motion;
62
     uint8_t observation;
67
     uint8_t observation;

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

11
 // Firmware "PMW3360DM_srom_0x04"
11
 // Firmware "PMW3360DM_srom_0x04"
12
 
12
 
13
 static const uint16_t pmw_fw_length = 4094;
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
 0x01, 0x04, 0x8e, 0x96, 0x6e, 0x77, 0x3e, 0xfe, 0x7e, 0x5f, 0x1d, 0xb8, 0xf2, 0x66, 0x4e,
15
 0x01, 0x04, 0x8e, 0x96, 0x6e, 0x77, 0x3e, 0xfe, 0x7e, 0x5f, 0x1d, 0xb8, 0xf2, 0x66, 0x4e,
16
 0xff, 0x5d, 0x19, 0xb0, 0xc2, 0x04, 0x69, 0x54, 0x2a, 0xd6, 0x2e, 0xbf, 0xdd, 0x19, 0xb0,
16
 0xff, 0x5d, 0x19, 0xb0, 0xc2, 0x04, 0x69, 0x54, 0x2a, 0xd6, 0x2e, 0xbf, 0xdd, 0x19, 0xb0,
17
 0xc3, 0xe5, 0x29, 0xb1, 0xe0, 0x23, 0xa5, 0xa9, 0xb1, 0xc1, 0x00, 0x82, 0x67, 0x4c, 0x1a,
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
 #ifndef __USB_H__
5
 #ifndef __USB_H__
6
 #define __USB_H__
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
 void usb_init(void);
8
 void usb_init(void);
17
 void usb_run(void);
9
 void usb_run(void);
18
 
10
 
19
-void usb_cdc_write(const char *buf, uint32_t count);
20
-
21
 #endif // __USB_H__
11
 #endif // __USB_H__

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

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
 #ifndef USB_DESCRIPTORS_H_
25
 #ifndef USB_DESCRIPTORS_H_
26
 #define USB_DESCRIPTORS_H_
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
 #endif /* USB_DESCRIPTORS_H_ */
38
 #endif /* USB_DESCRIPTORS_H_ */

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

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

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

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
 #include <stdarg.h>
5
 #include <stdarg.h>
6
 #include <stdio.h>
6
 #include <stdio.h>
7
 #include "pico/stdlib.h"
7
 #include "pico/stdlib.h"
8
-#include "usb.h"
8
+#include "usb_cdc.h"
9
 #include "log.h"
9
 #include "log.h"
10
 
10
 
11
 char log_buff[4096];
11
 char log_buff[4096];
66
     return l;
66
     return l;
67
 }
67
 }
68
 
68
 
69
-void debug_log(const char* format, ...) {
69
+void debug_log(bool log, const char* format, ...) {
70
     static char line_buff[256];
70
     static char line_buff[256];
71
 
71
 
72
     va_list args;
72
     va_list args;
76
 
76
 
77
     if ((l > 0) && (l <= sizeof(line_buff))) {
77
     if ((l > 0) && (l <= sizeof(line_buff))) {
78
         usb_cdc_write(line_buff, l);
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
 
4
 
5
 #include "pico/stdlib.h"
5
 #include "pico/stdlib.h"
6
 
6
 
7
+#include "util.h"
8
+#include "console.h"
7
 #include "log.h"
9
 #include "log.h"
8
 #include "usb.h"
10
 #include "usb.h"
9
 #include "pmw3360.h"
11
 #include "pmw3360.h"
10
 
12
 
11
 int main(void) {
13
 int main(void) {
14
+    heartbeat_init();
15
+    cnsl_init();
12
     usb_init();
16
     usb_init();
13
     pmw_init();
17
     pmw_init();
14
     debug("init done");
18
     debug("init done");
15
 
19
 
16
     while (1) {
20
     while (1) {
21
+        heartbeat_run();
17
         usb_run();
22
         usb_run();
18
     }
23
     }
19
 
24
 

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

21
 #include "pico/binary_info.h"
21
 #include "pico/binary_info.h"
22
 #include "hardware/spi.h"
22
 #include "hardware/spi.h"
23
 
23
 
24
+#define PMW_IRQ_COUNTERS
25
+
24
 #include "log.h"
26
 #include "log.h"
25
 #include "pmw3360_registers.h"
27
 #include "pmw3360_registers.h"
26
 #include "pmw3360_srom.h"
28
 #include "pmw3360_srom.h"
32
 
34
 
33
 #define PMW_MOTION_PIN 20
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
 static inline void pmw_cs_select() {
63
 static inline void pmw_cs_select() {
36
     asm volatile("nop \n nop \n nop");
64
     asm volatile("nop \n nop \n nop");
37
     gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 0); // Active low
65
     gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 0); // Active low
66
     return buf;
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
     reg |= WRITE_BIT;
98
     reg |= WRITE_BIT;
71
     pmw_cs_select();
99
     pmw_cs_select();
72
     spi_write_blocking(spi_default, &reg, 1);
100
     spi_write_blocking(spi_default, &reg, 1);
83
     reg &= ~WRITE_BIT;
111
     reg &= ~WRITE_BIT;
84
     pmw_cs_select();
112
     pmw_cs_select();
85
     spi_write_blocking(spi_default, &reg, 1);
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
     pmw_cs_deselect();
116
     pmw_cs_deselect();
89
-    sleep_us(1); // TODO tBEXIT
117
+    sleep_us(1);
90
 }
118
 }
91
 
119
 
92
 static uint8_t pmw_srom_download(void) {
120
 static uint8_t pmw_srom_download(void) {
102
     // Write 0x18 to SROM_Enable register again to start SROM Download
130
     // Write 0x18 to SROM_Enable register again to start SROM Download
103
     pmw_write_register(REG_SROM_ENABLE, 0x18);
131
     pmw_write_register(REG_SROM_ENABLE, 0x18);
104
 
132
 
133
+    sleep_us(120);
134
+
105
     // Write SROM file into SROM_Load_Burst register, 1st data must start with SROM_Load_Burst address.
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
     // Read the SROM_ID register to verify the ID before any other register reads or writes
140
     // Read the SROM_ID register to verify the ID before any other register reads or writes
109
     uint8_t srom_id = pmw_read_register(REG_SROM_ID);
141
     uint8_t srom_id = pmw_read_register(REG_SROM_ID);
127
     return srom_id;
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
     // Write any value to Motion_Burst register
163
     // Write any value to Motion_Burst register
132
     pmw_write_register(REG_MOTION_BURST, 0x42);
164
     pmw_write_register(REG_MOTION_BURST, 0x42);
133
 
165
 
135
     struct pmw_motion_report motion_report;
167
     struct pmw_motion_report motion_report;
136
     pmw_read_register_burst(REG_MOTION_BURST, (uint8_t *)&motion_report, sizeof(motion_report));
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
 static uint16_t pmw_srom_checksum(void) {
173
 static uint16_t pmw_srom_checksum(void) {
161
     gpio_set_dir(PICO_DEFAULT_SPI_CSN_PIN, GPIO_OUT);
193
     gpio_set_dir(PICO_DEFAULT_SPI_CSN_PIN, GPIO_OUT);
162
     gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 1);
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
     bi_decl(bi_3pins_with_func(PICO_DEFAULT_SPI_RX_PIN, PICO_DEFAULT_SPI_TX_PIN, PICO_DEFAULT_SPI_SCK_PIN, GPIO_FUNC_SPI));
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
     bi_decl(bi_1pin_with_name(PICO_DEFAULT_SPI_CSN_PIN, "SPI CS"));
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
 static void pmw_motion_irq(void) {
240
 static void pmw_motion_irq(void) {
170
     if (gpio_get_irq_event_mask(PMW_MOTION_PIN) & GPIO_IRQ_EDGE_FALL) {
241
     if (gpio_get_irq_event_mask(PMW_MOTION_PIN) & GPIO_IRQ_EDGE_FALL) {
171
         gpio_acknowledge_irq(PMW_MOTION_PIN, GPIO_IRQ_EDGE_FALL);
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
 
257
 
187
     debug("SROM ID: 0x%02X", srom_id);
258
     debug("SROM ID: 0x%02X", srom_id);
188
     debug("Product ID: 0x%02X", prod_id);
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
     debug("Revision ID: 0x%02X", rev_id);
261
     debug("Revision ID: 0x%02X", rev_id);
191
     debug("SROM CRC: 0x%04X", srom_checksum);
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
         debug("SPI communication error (0x%02X != ~0x%02X)", prod_id, inv_prod_id);
265
         debug("SPI communication error (0x%02X != ~0x%02X)", prod_id, inv_prod_id);
195
         return -1;
266
         return -1;
196
     }
267
     }
202
     pmw_write_register(REG_CONFIG2, 0x00);
273
     pmw_write_register(REG_CONFIG2, 0x00);
203
 #endif
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
     return 0;
282
     return 0;
209
 }
283
 }

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

27
 #include "tusb.h"
27
 #include "tusb.h"
28
 
28
 
29
 #include "usb_descriptors.h"
29
 #include "usb_descriptors.h"
30
+#include "usb_cdc.h"
31
+#include "usb_hid.h"
30
 #include "usb.h"
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
 void usb_init(void) {
34
 void usb_init(void) {
38
     usb_descriptor_init_id();
35
     usb_descriptor_init_id();
39
 
36
 
43
 
40
 
44
 void usb_run(void) {
41
 void usb_run(void) {
45
     tud_task();
42
     tud_task();
46
-    led_blinking_task();
47
-
48
-    cdc_task();
49
     hid_task();
43
     hid_task();
50
 }
44
 }
51
 
45
 
52
-uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
53
-
54
 // Invoked when device is mounted
46
 // Invoked when device is mounted
55
 void tud_mount_cb(void) {
47
 void tud_mount_cb(void) {
56
-    blink_interval_ms = BLINK_MOUNTED;
57
 }
48
 }
58
 
49
 
59
 // Invoked when device is unmounted
50
 // Invoked when device is unmounted
60
 void tud_umount_cb(void) {
51
 void tud_umount_cb(void) {
61
-    blink_interval_ms = BLINK_NOT_MOUNTED;
62
 }
52
 }
63
 
53
 
64
 // Invoked when usb bus is suspended
54
 // Invoked when usb bus is suspended
66
 // Within 7ms, device must draw an average of current less than 2.5 mA from bus
56
 // Within 7ms, device must draw an average of current less than 2.5 mA from bus
67
 void tud_suspend_cb(bool remote_wakeup_en) {
57
 void tud_suspend_cb(bool remote_wakeup_en) {
68
     (void) remote_wakeup_en;
58
     (void) remote_wakeup_en;
69
-    blink_interval_ms = BLINK_SUSPENDED;
70
 }
59
 }
71
 
60
 
72
 // Invoked when usb bus is resumed
61
 // Invoked when usb bus is resumed
73
 void tud_resume_cb(void) {
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
 
25
 
26
 #include "bsp/board.h"
26
 #include "bsp/board.h"
27
 #include "tusb.h"
27
 #include "tusb.h"
28
-#include "pico/bootrom.h"
29
 
28
 
29
+#include "console.h"
30
 #include "log.h"
30
 #include "log.h"
31
+#include "util.h"
31
 #include "usb_descriptors.h"
32
 #include "usb_descriptors.h"
32
-#include "usb.h"
33
+#include "usb_cdc.h"
33
 
34
 
34
 void usb_cdc_write(const char *buf, uint32_t count) {
35
 void usb_cdc_write(const char *buf, uint32_t count) {
35
 #ifndef DISABLE_CDC_DTR_CHECK
36
 #ifndef DISABLE_CDC_DTR_CHECK
38
     }
39
     }
39
 #endif // DISABLE_CDC_DTR_CHECK
40
 #endif // DISABLE_CDC_DTR_CHECK
40
 
41
 
42
+    // implemented similar to Pico SDK stdio usb
41
     uint32_t len = 0;
43
     uint32_t len = 0;
42
-
43
     while (len < count) {
44
     while (len < count) {
44
         uint32_t n = count - len;
45
         uint32_t n = count - len;
45
         uint32_t available = tud_cdc_write_available();
46
         uint32_t available = tud_cdc_write_available();
46
 
47
 
48
+        // only write as much as possible
47
         if (n > available) {
49
         if (n > available) {
48
             n = available;
50
             n = available;
49
         }
51
         }
50
 
52
 
51
         len += tud_cdc_write(buf + len, n);
53
         len += tud_cdc_write(buf + len, n);
54
+
55
+        // run tud_task to actually move stuff from FIFO
52
         tud_task();
56
         tud_task();
53
         tud_cdc_write_flush();
57
         tud_cdc_write_flush();
54
     }
58
     }
55
 }
59
 }
56
 
60
 
57
 void cdc_task(void) {
61
 void cdc_task(void) {
62
+    const uint32_t cdc_buf_len = 64;
63
+
58
     if (tud_cdc_available()) {
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
             debug("switching to bootloader");
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
         } else {
72
         } else {
72
             // echo back
73
             // echo back
73
             usb_cdc_write(buf, count);
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
     static bool last_dtr = false;
86
     static bool last_dtr = false;
86
 
87
 
87
     if (dtr && !last_dtr) {
88
     if (dtr && !last_dtr) {
89
+        // clear left-over console input
90
+        cnsl_init();
91
+
92
+        // show past history
88
         log_dump_to_usb();
93
         log_dump_to_usb();
94
+
89
         debug("terminal connected");
95
         debug("terminal connected");
90
     } else if (!dtr && last_dtr) {
96
     } else if (!dtr && last_dtr) {
91
         debug("terminal disconnected");
97
         debug("terminal disconnected");
97
 // invoked when CDC interface received data from host
103
 // invoked when CDC interface received data from host
98
 void tud_cdc_rx_cb(uint8_t itf) {
104
 void tud_cdc_rx_cb(uint8_t itf) {
99
     (void) itf;
105
     (void) itf;
106
+    cdc_task();
100
 }
107
 }

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

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

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