diff --git a/sw/include/rgb.h b/sw/include/rgb.h index da5b342..e6cbbbb 100644 --- a/sw/include/rgb.h +++ b/sw/include/rgb.h @@ -2,5 +2,9 @@ #define _RGB_H_ void rgb_init(void); +void rgb_mode_idle(void); +void rgb_mode_done(void); +void rgb_mode_writing(void); +void rgb_mode_error(void); #endif /* _RGB_H_ */ \ No newline at end of file diff --git a/sw/src/dfu.c b/sw/src/dfu.c index cbdc81e..bc3e4c6 100644 --- a/sw/src/dfu.c +++ b/sw/src/dfu.c @@ -27,6 +27,7 @@ #include #include #include +#include #define ERASE_SIZE 65536 // Erase block size (in bytes) #define WRITE_SIZE 256 // Number of bytes we can write @@ -54,6 +55,14 @@ static uint32_t dfu_bytes_remaining; static uint32_t dfu_target_address; static void set_state(dfu_state_t new_state, dfu_status_t new_status) { + if (new_state == dfuIDLE) + rgb_mode_idle(); + else if (new_status != OK) + rgb_mode_error(); + else if (new_state == dfuMANIFEST_WAIT_RESET) + rgb_mode_done(); + else + rgb_mode_writing(); dfu_state = new_state; dfu_status = new_status; } @@ -305,13 +314,13 @@ bool dfu_getstatus(uint8_t status[8]) case dfuMANIFEST_SYNC: // Ready to reboot. The main thread will take care of this. Also let the DFU tool // know to leave us alone until this happens. - dfu_state = dfuMANIFEST; + set_state(dfuMANIFEST, OK); dfu_poll_timeout_ms = 10; break; case dfuMANIFEST: // Perform the reboot - dfu_state = dfuMANIFEST_WAIT_RESET; + set_state(dfuMANIFEST_WAIT_RESET, OK); dfu_poll_timeout_ms = 1000; break; diff --git a/sw/src/rgb.c b/sw/src/rgb.c index 46d1e50..c63abdb 100644 --- a/sw/src/rgb.c +++ b/sw/src/rgb.c @@ -19,6 +19,23 @@ enum led_registers { #define BREATHE_MODE_MODULATE (1 << 5) #define BREATHE_RATE(x) ((x & 7) << 0) +#define RGB_SWITCH_MODE(x) do { \ + if (rgb_mode == x) \ + return; \ + rgb_mode = x; \ + /* Toggle LEDD_EXE to force the mode to switch */ + rgb_ctrl_write( (1 << 1) | (1 << 2)); \ + rgb_ctrl_write((1 << 0) | (1 << 1) | (1 << 2)); \ +} while(0) + +static enum { + INVALID = 0, + IDLE, + WRITING, + ERROR, + DONE, +} rgb_mode; + static void rgb_write(uint8_t value, uint8_t addr) { rgb_addr_write(addr); rgb_dat_write(value); @@ -28,11 +45,19 @@ void rgb_init(void) { // Turn on the RGB block and current enable, as well as enabling led control rgb_ctrl_write((1 << 0) | (1 << 1) | (1 << 2)); - rgb_write((1 << 7) | (1 << 6), LEDDCR0); + // Enable the LED driver, and set 250 Hz mode. + // Also set quick stop, which we'll use to switch patterns quickly. + rgb_write((1 << 7) | (1 << 6) | (1 << 3), LEDDCR0); // Set clock register to 12 MHz / 64 kHz - 1 rgb_write((12000000/64000)-1, LEDDBR); + rgb_mode_idle(); +} + +void rgb_mode_idle(void) { + RGB_SWITCH_MODE(IDLE); + // rgb_mode_writing(); return; rgb_write(12, LEDDONR); rgb_write(24, LEDDOFR); @@ -43,4 +68,46 @@ void rgb_init(void) { rgb_write(0x00/4, LEDDPWRG); // Red rgb_write(0x4a/4, LEDDPWRB); // Green rgb_write(0xe1/4, LEDDPWRR); // Blue +} + +void rgb_mode_writing(void) { + RGB_SWITCH_MODE(WRITING); + rgb_write(1, LEDDONR); + rgb_write(2, LEDDOFR); + + rgb_write(BREATHE_ENABLE | 0 + | BREATHE_MODE_MODULATE | BREATHE_RATE(1), LEDDBCRR); + rgb_write(BREATHE_ENABLE | BREATHE_MODE_MODULATE | BREATHE_RATE(3), LEDDBCFR); + + rgb_write(0x00/4, LEDDPWRG); // Red + rgb_write(0x7a/4, LEDDPWRB); // Green + rgb_write(0x51/4, LEDDPWRR); // Blue +} + +void rgb_mode_error(void) { + RGB_SWITCH_MODE(ERROR); + rgb_write(3, LEDDONR); + rgb_write(3, LEDDOFR); + + rgb_write(BREATHE_ENABLE | BREATHE_EDGE_BOTH + | BREATHE_MODE_MODULATE | BREATHE_RATE(2), LEDDBCRR); + rgb_write(BREATHE_ENABLE | BREATHE_MODE_MODULATE | BREATHE_RATE(3), LEDDBCFR); + + rgb_write(0xf0/4, LEDDPWRG); // Red + rgb_write(0x0a/4, LEDDPWRB); // Green + rgb_write(0x01/4, LEDDPWRR); // Blue +} + +void rgb_mode_done(void) { + RGB_SWITCH_MODE(DONE); + rgb_write(8, LEDDONR); + rgb_write(8, LEDDOFR); + + rgb_write(BREATHE_ENABLE | BREATHE_EDGE_BOTH + | BREATHE_MODE_MODULATE | BREATHE_RATE(2), LEDDBCRR); + rgb_write(BREATHE_ENABLE | BREATHE_MODE_MODULATE | BREATHE_RATE(3), LEDDBCFR); + + rgb_write(0x14/4, LEDDPWRG); // Red + rgb_write(0xff/4, LEDDPWRB); // Green + rgb_write(0x44/4, LEDDPWRR); // Blue } \ No newline at end of file