#include #include #include #include #include #include Adafruit_PCD8544 display = Adafruit_PCD8544(14, 15, 16, 17, 18); Button button(4); Encoder encoder(3, 2); // General vars unsigned long time; boolean connected = false; boolean dataReady = false; boolean editing = false; boolean blink = false; // Encoder related vars long position = 0; // Serial related vars const byte numChars = 32; char receivedChars[numChars]; char tempChars[numChars]; char command[numChars] = {0}; boolean newData = false; // Set backlight boolean light = 0; int timeout = 10000; void toggleBacklight(int value = 128) { if (light) { analogWrite(5, 0); light = 0; } else { analogWrite(5, value); light = 1; } } // Set variables for menu int programLenght; int currentProgram = 0; char programName[numChars] = {0}; boolean menuUpdate = true; float volume = -1; // Draw screen void drawMenu() { display.clearDisplay(); display.setFont(&Picopixel); // Check for connection if (connected && dataReady) { // Draw top bar display.setCursor(0, 4); display.print((String)(currentProgram + 1) + "/" + (String)(programLenght)); display.setCursor(73, 4); display.print("USB"); } display.drawLine(0, 6, 84, 6, BLACK); display.setFont(NULL); // Check for connection if (connected && dataReady) { // Program name drawName(); // Volume Bar drawBar(); } else { // Blink connection message if not connected if (time % 500 == 0) { blink = (!blink) ? true : false; } if (!blink) { display.setCursor(9, 10); display.print("Waiting for"); if (!connected) { display.setCursor(12, 18); display.print("Connection"); } else if (!dataReady) { display.setCursor(30, 18); display.print("Data"); } } } // Bottom Bar display.drawLine(0, 38, 84, 38, BLACK); if (connected && dataReady) { display.setCursor(0, 40); if (editing) { display.print(" - OK + "); } else { display.print(" < OK > "); } } display.display(); } // Bar position const int pos[2] = { 4, 26 }; // Draw volume bar and text void drawBar() { // Set fonts and size display.setFont(&Picopixel); display.setCursor(4, pos[1] - 2); display.print("Volume:"); // Blink percentage if editing if (editing && time % 500 == 0) { blink = (!blink) ? 1 : 0; } // Center percentage if (volume == 0) { display.setCursor(39, pos[1] - 2); } else if (volume == 100) { display.setCursor(36, pos[1] - 2); } else { display.setCursor(37, pos[1] - 2); } if (!blink) { display.print((String)round(volume) + "%"); } // Draw volume bar display.drawRect(pos[0], pos[1], 76, 8, BLACK); display.drawLine(pos[0], pos[1] + 8, pos[0], pos[1] + 9, BLACK); display.drawPixel(pos[0] + (76 / 4) * 1 - 1, pos[1] + 8, BLACK); display.drawLine(pos[0] + (76 / 4) * 2 - 1, pos[1] + 8, pos[0] + (76 / 4) * 2 - 1, pos[1] + 9, BLACK); display.drawPixel(pos[0] + (76 / 4) * 3 - 1, pos[1] + 8, BLACK); display.drawLine(pos[0] + 75, pos[1] + 8, pos[0] + 75, pos[1] + 9, BLACK); display.fillRect(pos[0], pos[1], round(volume / 100 * 76), 8, BLACK); display.setFont(NULL); } // Draw program name in the middle of the display or scroll it // TODO: Fix char lenght void drawName() { int width = 0; for (size_t i = 0; i < sizeof(programName); i++) { if (programName[i] != NULL) { width = width + 6; } } if (width > 84) { // TODO: Make the text scroll if the name is too long } else { int x = (84 / 2) - (width / 2); display.setCursor(x, 10); } display.print(programName); } void processData() { if (newData == true) { strcpy(tempChars, receivedChars); char * strtokIndx; strtokIndx = strtok(tempChars,","); strcpy(command, strtokIndx); strtokIndx = strtok(NULL, ","); if (strcmp("HELLO", command) == 0) { connected = true; Serial.println(""); } else if (strcmp("COUNT", command) == 0) { programLenght = atoi(strtokIndx); Serial.println(""); } else if (strcmp("CURRENT", command) == 0) { currentProgram = atoi(strtokIndx); Serial.println(""); } else if (strcmp("NAME", command) == 0) { strcpy(programName, strtokIndx); Serial.println(""); } else if (strcmp("GETVOL", command) == 0) { volume = atoi(strtokIndx); Serial.println(""); } newData = false; dataReady = true; } } void checkSerial() { static boolean recvInProgress = false; static byte ndx = 0; char startMarker = '<'; char endMarker = '>'; char rc; while (Serial.available() > 0 && newData == false) { rc = Serial.read(); if (recvInProgress == true) { if (rc != endMarker) { receivedChars[ndx] = rc; ndx++; if (ndx >= numChars) { ndx = numChars - 1; } } else { receivedChars[ndx] = '\0'; // terminate the string recvInProgress = false; ndx = 0; newData = true; } } else if (rc == startMarker) { recvInProgress = true; } } processData(); } // Check for button input // TODO: Improve encoder input void checkInput(unsigned long time) { long newPosition = encoder.read(); if (newPosition != position) { menuUpdate = true; if (newPosition < position - 3) // Rotating anti-clockwise { if (!editing) { if (currentProgram == 0) { currentProgram = programLenght - 1; } else { currentProgram--; } Serial.println(""); } else { if (volume != 0) { Serial.println(""); } } position = newPosition; } if (newPosition > position + 3) // Rotating clockwise { if (!editing) { if (currentProgram == programLenght - 1) { currentProgram = 0; } else { currentProgram++; } Serial.println(""); } else { if (volume != 100) { Serial.println(""); } } position = newPosition; } } if (button.pressed()) { editing = (editing) ? 0 : 1; } } // Init arduino void setup() { // Start serial connection Serial.begin(115200); // Init button button.begin(); // Init display display.begin(); display.setContrast(50); toggleBacklight(); display.clearDisplay(); display.display(); // TODO: Remove testing variables currentProgram = 0; } void loop() { // Check time time = millis(); menuUpdate = (time % 1000 == 0) ? true : false; if (programLenght == 0 || volume == -1 || strcmp("", programName) == 0) { dataReady = false; } if (!editing && connected && dataReady) { blink = false; } // Check for serial data or commands checkSerial(); // Check if serial connection is established if (connected) { // Draw menu every second or every 0.1 second when editing if (menuUpdate || (editing && time % 100 == 0)) { menuUpdate = false; drawMenu(); } // Check input checkInput(time); } else { if (menuUpdate) { // Draw menu with "Waiting for connection", name and volume are ignored bij drawMenu() menuUpdate = false; drawMenu(); } } }