55#include < CompositeGraphics.h> // In the 'lib' folder -> Angle brackets
66#include < CompositeOutput.h> // In the 'lib' folder -> Angle brackets
77#include " font6x8.h" // Local file in 'src' -> Quotes
8-
8+ # include < Preferences.h >
99#define RXD2 16 // Connect the C3's TX pin to this pin!
1010#define TXD2 17 // (We won't actually send anything back to the C3)
1111
1212// PAL MAX, half: 324x268 full: 648x536
1313// NTSC MAX, half: 324x224 full: 648x448
1414const int XRES = 320 ;
1515const int YRES = 225 ;
16- String displayText = " REBOOT_\n THE_RISE \n _OF_THE_\n ROBOTS" ;
17-
16+ String displayText = " REBOOT_\n THE_dick \n _OF_THE_\n ROBOTS" ;
17+ Preferences preferences;
1818// Graphics using the defined resolution for the backbuffer
1919CompositeGraphics graphics (XRES , YRES );
2020CompositeOutput composite (CompositeOutput::NTSC , XRES * 2 , YRES * 2 );
2121Font<CompositeGraphics> font (6 , 8 , font6x8::pixels);
2222
2323#include < soc/rtc.h>
2424char currentScene = ' F' ;
25+ String currentPayload = " " ;
2526
2627// --- NOW ACCEPTING 0 to 127 ---
2728int paramBg = 0 ;
@@ -37,7 +38,7 @@ int scene = 0;
3738void compositeCore (void *data);
3839
3940void setup () {
40- Serial.begin (115200 );
41+ Serial.begin (460800 );
4142 Serial.println (" ESP32 Composite Video Started!" );
4243 Serial2.begin (460800 , SERIAL_8N1 , RXD2 , TXD2 );
4344
@@ -49,6 +50,8 @@ void setup() {
4950 graphics.init ();
5051 graphics.setFont (font);
5152
53+ preferences.begin (" synth_mem" , false );
54+
5255 xTaskCreatePinnedToCore (compositeCore, " compositeCoreTask" , 1024 , NULL , 1 , NULL , 0 );
5356}
5457
@@ -58,32 +61,81 @@ void compositeCore(void *data) {
5861 }
5962}
6063
64+ void applyState (const String& payload) {
65+ // If the payload somehow got mangled and is too short, abort to prevent a crash
66+ if (payload.length () < 16 ) return ;
67+
68+ currentScene = payload.charAt (0 );
69+ int len = payload.length ();
70+ int s1Start = len - 15 ;
71+
72+ if (s1Start > 1 ) {
73+ displayText = payload.substring (1 , s1Start);
74+ }
75+
76+ paramBg = payload.substring (s1Start, s1Start + 3 ).toInt ();
77+ paramSize = payload.substring (s1Start + 3 , s1Start + 6 ).toInt ();
78+ paramSpeed = payload.substring (s1Start + 6 , s1Start + 9 ).toInt ();
79+ paramShape = payload.substring (s1Start + 9 , s1Start + 12 ).toInt ();
80+ paramMulti = payload.substring (s1Start + 12 , s1Start + 15 ).toInt ();
81+ }
82+
6183// --- THE NEW FIXED-LENGTH PARSER ---
6284void handleSerial () {
63- if (Serial2.available () > 0 ) {
64- String input = Serial2.readStringUntil (' \n ' );
85+ String input = " " ;
86+
87+ // 1. Check direct USB connection (Web MIDI / Laptop) first
88+ if (Serial.available () > 0 ) {
89+ input = Serial.readStringUntil (' \n ' );
90+ }
91+ // 2. If nothing on USB, check the C3 Wi-Fi Uplink (Serial2)
92+ else if (Serial2.available () > 0 ) {
93+ input = Serial2.readStringUntil (' \n ' );
94+ }
95+
96+ // 3. If we caught a message from EITHER port, process it!
97+ if (input.length () > 0 ) {
6598 input.trim ();
6699 int len = input.length ();
67100
68101 // The shortest possible valid packet (Mode + 5 padded sliders) is 16 chars.
102+ // This handles the encoded video commands
69103 if (len >= 16 ) {
70- currentScene = input.charAt (0 );
71- int s1Start = len - 15 ;
72-
73- if (s1Start > 1 ) {
74- displayText = input.substring (1 , s1Start);
104+ // *Crucial Note*: Make sure you update currentPayload here so your Save commands work!
105+ currentPayload = input;
106+ applyState (currentPayload);
107+ // Warning: If you are sending data TO the board via Serial (USB),
108+ // printing this back out might cause a feedback loop in your Javascript app!
109+ // You may want to comment this out if using the Web MIDI tool.
110+ Serial.print (" message received: " ); Serial.println (input);
111+ }
112+
113+ // This handles the serial control commands (load and display)
114+ else if (len == 2 ) {
115+ char command = input.charAt (0 );
116+ String slot = String (input.charAt (1 ));
117+ String key = " p" + slot; // Creates memory keys like "p1", "p2"
118+
119+ // [ SAVE COMMAND ]
120+ if (command == ' S' || command == ' s' ) {
121+ // Burn the currently active payload into the requested flash memory slot
122+ preferences.putString (key.c_str (), currentPayload);
123+ Serial.println (" --- PRESET SAVED TO SLOT " + slot + " ---" );
124+ }
125+
126+ // [ LOAD COMMAND ]
127+ else if (command == ' L' || command == ' l' ) {
128+ // Retrieve the payload from flash memory
129+ String loadedPayload = preferences.getString (key.c_str (), " " );
130+
131+ if (loadedPayload.length () >= 16 ) {
132+ currentPayload = loadedPayload;
133+ applyState (currentPayload); // Instantly draw the saved scene
134+ Serial.println (" --- PRESET LOADED FROM SLOT " + slot + " ---" );
135+ } else {
136+ Serial.println (" --- ERROR: SLOT " + slot + " IS EMPTY ---" );
137+ }
75138 }
76-
77- paramBg = input.substring (s1Start, s1Start + 3 ).toInt ();
78- paramSize = input.substring (s1Start + 3 , s1Start + 6 ).toInt ();
79- paramSpeed = input.substring (s1Start + 6 , s1Start + 9 ).toInt ();
80- paramShape = input.substring (s1Start + 9 , s1Start + 12 ).toInt ();
81- paramMulti = input.substring (s1Start + 12 , s1Start + 15 ).toInt ();
82-
83- Serial.print (" message recieved: " ); Serial.println (input);
84- Serial.print (" TEXT: " ); Serial.println (displayText);
85- Serial.printf (" SLIDERS: Bg:%d, Size:%d, Spd:%d, Shp:%d, Mlt:%d\n " ,
86- paramBg, paramSize, paramSpeed, paramShape, paramMulti);
87139 }
88140 }
89141}
0 commit comments