@@ -135,7 +135,7 @@ void program_ssd1306() {
135
135
.reserved = 0 };
136
136
137
137
sao_driver_basic_io_data_t data_basic_io = {
138
- .io1_function = SAO_DRIVER_BASIC_IO_FUNC_LED_RED , .io2_function = SAO_DRIVER_BASIC_IO_FUNC_LED_BLUE , .reserved = 0 };
138
+ .io1_function = SAO_DRIVER_BASIC_IO_FUNC_LED_BLUE , .io2_function = SAO_DRIVER_BASIC_IO_FUNC_LED_RED , .reserved = 0 };
139
139
140
140
sao_format ("OLED display" , SAO_DRIVER_SSD1306_NAME , (uint8_t * ) & data_ssd1306 , sizeof (data_ssd1306 ), SAO_DRIVER_STORAGE_NAME , (uint8_t * ) & data_storage ,
141
141
sizeof (data_storage ), SAO_DRIVER_BASIC_IO_NAME , (uint8_t * ) & data_basic_io , sizeof (sao_driver_basic_io_data_t ), false);
@@ -162,6 +162,20 @@ void program_ntag() {
162
162
sizeof (data_storage ), SAO_DRIVER_BASIC_IO_NAME , (uint8_t * ) & data_basic_io , sizeof (sao_driver_basic_io_data_t ), false);
163
163
}
164
164
165
+ void program_tilde_butterfly () {
166
+ sao_driver_neopixel_data_t data_neopixel = {.length = 5 , .color_order = SAO_DRIVER_NEOPIXEL_COLOR_ORDER_GRB , .reserved = 0 };
167
+
168
+ sao_driver_storage_data_t data_storage = {.flags = 0 ,
169
+ .address = 0x50 ,
170
+ .size_exp = 11 , // 2 kbit (2^11)
171
+ .page_size_exp = 4 , // 16 bytes (2^4)
172
+ .data_offset = 4 , // 4 pages (64 bytes)
173
+ .reserved = 0 };
174
+
175
+ sao_format ("[~] MCH butterfly" , SAO_DRIVER_NEOPIXEL_NAME , (uint8_t * ) & data_neopixel , sizeof (data_neopixel ), SAO_DRIVER_STORAGE_NAME ,
176
+ (uint8_t * ) & data_storage , sizeof (data_storage ), NULL , NULL , 0 , true);
177
+ }
178
+
165
179
typedef enum action {
166
180
ACTION_NONE = 0 ,
167
181
ACTION_BACK ,
@@ -173,7 +187,8 @@ typedef enum action {
173
187
ACTION_DISKETTE ,
174
188
ACTION_SSD1306 ,
175
189
ACTION_NTAG ,
176
- ACTION_SMALL
190
+ ACTION_SMALL ,
191
+ ACTION_BUTTERFLY
177
192
} menu_dev_action_t ;
178
193
179
194
static void menu_sao_format (xQueueHandle button_queue ) {
@@ -199,6 +214,7 @@ static void menu_sao_format(xQueueHandle button_queue) {
199
214
menu_insert_item (menu , "SSD1306" , NULL , (void * ) ACTION_SSD1306 , -1 );
200
215
menu_insert_item (menu , "NTAG" , NULL , (void * ) ACTION_NTAG , -1 );
201
216
menu_insert_item (menu , "Generic 2kb EEPROM" , NULL , (void * ) ACTION_SMALL , -1 );
217
+ menu_insert_item (menu , "Tilde butterfly" , NULL , (void * ) ACTION_BUTTERFLY , -1 );
202
218
203
219
bool render = true;
204
220
menu_dev_action_t action = ACTION_NONE ;
@@ -268,6 +284,9 @@ static void menu_sao_format(xQueueHandle button_queue) {
268
284
} else if (action == ACTION_SMALL ) {
269
285
program_small ();
270
286
break ;
287
+ } else if (action == ACTION_BUTTERFLY ) {
288
+ program_tilde_butterfly ();
289
+ break ;
271
290
} else if (action == ACTION_BACK ) {
272
291
break ;
273
292
}
@@ -340,6 +359,11 @@ static const char* neopixelColorOrderToString(uint8_t color_order) {
340
359
return neopixel_color_order_strings [color_order ];
341
360
}
342
361
362
+ static bool neopixelColorHasWhite (uint8_t color_order ) {
363
+ if (color_order > SAO_DRIVER_NEOPIXEL_COLOR_ORDER_WRGB ) return true;
364
+ return false;
365
+ }
366
+
343
367
static const char * ntagInterruptToString (uint8_t interrupt_pin ) {
344
368
if (interrupt_pin == 0 ) return "none" ;
345
369
if (interrupt_pin == 1 ) return "IO1" ;
@@ -371,15 +395,22 @@ static bool basicioFunctionIsLED(uint8_t function) {
371
395
return false;
372
396
}
373
397
374
- bool io1_is_led = false;
375
- bool io2_is_led = false;
398
+ bool io1_is_led = false;
399
+ bool io2_is_led = false;
400
+ uint8_t neopixel_length = 0 ;
401
+ bool neopixel_white = false;
376
402
377
403
static void render_sao_status (pax_buf_t * pax_buffer , SAO * sao ) {
378
404
char stringbuf [256 ] = {0 };
379
405
const pax_font_t * font = pax_font_saira_regular ;
380
406
pax_background (pax_buffer , 0xFFFFFF );
381
407
pax_noclip (pax_buffer );
382
408
409
+ io1_is_led = false;
410
+ io2_is_led = false;
411
+ neopixel_length = 0 ;
412
+ neopixel_white = false;
413
+
383
414
if (sao -> type == SAO_BINARY ) {
384
415
bool can_start_app = false;
385
416
render_header (pax_buffer , 0 , 0 , pax_buffer -> width , 34 , 18 , 0xFF491d88 , 0xFF43b5a0 , NULL , sao -> name );
@@ -394,9 +425,11 @@ static void render_sao_status(pax_buf_t* pax_buffer, SAO* sao) {
394
425
} else if (strncmp (sao -> drivers [driver_index ].name , SAO_DRIVER_NEOPIXEL_NAME , strlen (SAO_DRIVER_NEOPIXEL_NAME )) == 0 ) {
395
426
sao_driver_neopixel_data_t * data = (sao_driver_neopixel_data_t * ) sao -> drivers [driver_index ].data ;
396
427
snprintf (stringbuf , sizeof (stringbuf ) - 1 , "%u Neopixel LEDs (%s)" , data -> length , neopixelColorOrderToString (data -> color_order ));
428
+ neopixel_length = data -> length ;
429
+ neopixel_white = neopixelColorHasWhite (data -> color_order );
397
430
} else if (strncmp (sao -> drivers [driver_index ].name , SAO_DRIVER_SSD1306_NAME , strlen (SAO_DRIVER_SSD1306_NAME )) == 0 ) {
398
431
sao_driver_ssd1306_data_t * data = (sao_driver_ssd1306_data_t * ) sao -> drivers [driver_index ].data ;
399
- snprintf (stringbuf , sizeof (stringbuf ) - 1 , "SSD1306 128x%u OLED display @0x%02x" , data -> height , data -> address );
432
+ snprintf (stringbuf , sizeof (stringbuf ) - 1 , "SSD1306 128x%u OLED @0x%02x" , data -> height , data -> address );
400
433
} else if (strncmp (sao -> drivers [driver_index ].name , SAO_DRIVER_NTAG_NAME , strlen (SAO_DRIVER_NTAG_NAME )) == 0 ) {
401
434
sao_driver_ntag_data_t * data = (sao_driver_ntag_data_t * ) sao -> drivers [driver_index ].data ;
402
435
snprintf (stringbuf , sizeof (stringbuf ) - 1 , "NTAG NFC tag @0x%02x %ukb int=%s" , data -> address , intPow (2 , data -> size_exp ) / 1024 ,
@@ -447,18 +480,33 @@ static bool connect_to_wifi() {
447
480
448
481
void reset_sao_io () {
449
482
RP2040 * rp2040 = get_rp2040 ();
483
+ // rp2040_set_ws2812_mode(rp2040, 0); // FIXME: fix bug in RP2040 firmware first, then add this line
450
484
rp2040_set_gpio_value (rp2040 , 0 , false);
451
485
rp2040_set_gpio_value (rp2040 , 1 , false);
452
486
rp2040_set_gpio_dir (rp2040 , 0 , false);
453
487
rp2040_set_gpio_dir (rp2040 , 1 , false);
454
488
}
455
489
456
490
void set_sao_io (uint8_t pin , bool value ) {
491
+ printf ("Set IO: %u to %u\n" , pin , value );
457
492
RP2040 * rp2040 = get_rp2040 ();
458
493
rp2040_set_gpio_dir (rp2040 , pin , true);
459
494
rp2040_set_gpio_value (rp2040 , pin , value );
460
495
}
461
496
497
+ void set_sao_neopixel (uint32_t color ) {
498
+ if (neopixel_length > 0 ) {
499
+ printf ("Set neopixels to %08X\n" , color );
500
+ RP2040 * rp2040 = get_rp2040 ();
501
+ rp2040_set_ws2812_length (rp2040 , neopixel_length );
502
+ rp2040_set_ws2812_mode (rp2040 , neopixel_white ? 2 : 1 );
503
+ for (uint8_t i = 0 ; i < neopixel_length ; i ++ ) {
504
+ rp2040_set_ws2812_data (rp2040 , i , color );
505
+ }
506
+ rp2040_ws2812_trigger (rp2040 );
507
+ }
508
+ }
509
+
462
510
void menu_sao (xQueueHandle button_queue ) {
463
511
rp2040_input_message_t buttonMessage = {0 };
464
512
while (xQueueReceive (button_queue , & buttonMessage , 0 ) == pdTRUE ) {
@@ -527,21 +575,25 @@ void menu_sao(xQueueHandle button_queue) {
527
575
if (io1_is_led ) {
528
576
set_sao_io (0 , true);
529
577
}
578
+ set_sao_neopixel (0xFF000000 );
530
579
break ;
531
580
case RP2040_INPUT_JOYSTICK_DOWN :
532
581
if (io1_is_led ) {
533
582
set_sao_io (0 , false);
534
583
}
584
+ set_sao_neopixel (0x00FF0000 );
535
585
break ;
536
586
case RP2040_INPUT_JOYSTICK_RIGHT :
537
587
if (io2_is_led ) {
538
588
set_sao_io (1 , true);
539
589
}
590
+ set_sao_neopixel (0x0000FF00 );
540
591
break ;
541
592
case RP2040_INPUT_JOYSTICK_LEFT :
542
593
if (io2_is_led ) {
543
594
set_sao_io (1 , false);
544
595
}
596
+ set_sao_neopixel (0x000000FF );
545
597
break ;
546
598
case RP2040_INPUT_BUTTON_START :
547
599
menu_sao_format (button_queue );
0 commit comments