#include #include #include #include #include #include Adafruit_PCD8544 display = Adafruit_PCD8544(14, 15, 16, 17, 18); Button button(4); Encoder encoder(3, 2); unsigned long time; int connected = 0; int editing = 0; int blink = 0; long position = 0; // Set backlight int 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; int menuUpdate = 1; int volume; // Draw screen void drawMenu(String name, float percentage) { display.clearDisplay(); display.setFont(&Picopixel); // Check for connection if (connected == 1) { // 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 == 1) { // Program name drawName(name); // Volume Bar drawBar(percentage); } else { // Blink connection message if not connected if (time % 500 == 0) { blink = (blink == 0) ? 1 : 0; } if (blink == 0) { display.setCursor(9, 10); display.print("Waiting for"); display.setCursor(12, 18); display.print("Connection"); } } // Bottom Bar display.drawLine(0, 38, 84, 38, BLACK); if (connected == 1) { display.setCursor(0, 40); if (editing == 1) { display.print(" - OK + "); } else { display.print(" < OK > "); } } display.display(); } // Bar position const int pos[2] = { 4, 26 }; // Draw volume bar and text void drawBar(float percentage) { // Set fonts and size display.setFont(&Picopixel); display.setCursor(4, pos[1] - 2); display.print("Volume:"); // Blink percentage if editing if (editing == 1 && time % 500 == 0) { blink = (blink == 0) ? 1 : 0; } // Center percentage if (percentage == 0) { display.setCursor(39, pos[1] - 2); } else if (percentage == 100) { display.setCursor(36, pos[1] - 2); } else { display.setCursor(37, pos[1] - 2); } if (blink == 0) { display.print((String)round(percentage) + "%"); } // 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(percentage / 100 * 76), 8, BLACK); display.setFont(NULL); } // Draw program name in the middle of the display or scroll it void drawName(String name) { int width = name.length() * 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(name); } // Check for button input void checkInput(unsigned long time) { long newPosition = encoder.read(); if (newPosition != position) { menuUpdate = 1; if (newPosition < position) // Rotating anti-clockwise { if (editing != 1) { if (currentProgram == 0) { currentProgram = programLenght - 1; } else { currentProgram--; } } else { volume--; } } if (newPosition > position) // Rotating clockwise { if (editing != 1) { if (currentProgram == programLenght - 1) { currentProgram = 0; } else { currentProgram++; } } else { volume++; } } position = newPosition; } if (button.pressed()) { editing = (editing == 1) ? 0 : 1; blink = 0; } } const byte numChars = 32; char receivedChars[numChars]; char tempChars[numChars]; char command[numChars] = {0}; char data[numChars] = {0}; int intData = 0; boolean newData = false; void processData() { if (newData == true) { Serial.print("Raw data recieved: "); Serial.println(receivedChars); strcpy(tempChars, receivedChars); char * strtokIndx; strtokIndx = strtok(tempChars,","); strcpy(command, strtokIndx); Serial.print("Command: "); Serial.println(command); strtokIndx = strtok(NULL, ","); if (atoi(strtokIndx) > 0) // Integer data { intData = atoi(strtokIndx); } else { // String data strcpy(data, strtokIndx); } newData = false; } } 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(); } // 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 programLenght = 3; currentProgram = 0; volume = 50; connected = 1; } void loop() { // Check time time = millis(); menuUpdate = (time % 1000 == 0) ? 1 : 0; // Check for serial data or commands checkSerial(); // Check if serial connection is established if (connected == 1) { // Draw menu every second or every 0.1 second when editing if (menuUpdate == 1 || (editing == 1 && time % 100 == 0)) { menuUpdate = 0; // TODO: Get serial data for program switch (currentProgram) { case 0: drawMenu("Firefox", volume); break; case 1: drawMenu("Discord", volume); break; case 2: drawMenu("Steam", volume); break; } } // Check input checkInput(time); } else { if (menuUpdate == 1) { // Draw menu with "Waiting for connection", name and volume are ignored bij drawMenu() menuUpdate = 0; drawMenu("", 0.0); } } }