Guest User

Untitled

a guest
Mar 13th, 2020
215
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.95 KB | None | 0 0
  1. #include <LiquidCrystal.h>
  2.  
  3. LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
  4.  
  5. int lcd_key     = 0;
  6. int adc_key_in  = 0;
  7. #define btnRIGHT  0
  8. #define btnUP     1
  9. #define btnDOWN   2
  10. #define btnLEFT   3
  11. #define btnSELECT 4
  12. #define btnNONE   5
  13.  
  14. int read_LCD_buttons()
  15. {
  16.   adc_key_in = analogRead(0);
  17.   if (adc_key_in > 1000) return btnNONE;
  18.   if (adc_key_in < 50)   return btnRIGHT;
  19.   if (adc_key_in < 250)  return btnUP;
  20.   if (adc_key_in < 450)  return btnDOWN;
  21.   if (adc_key_in < 650)  return btnLEFT;
  22.   if (adc_key_in < 850)  return btnSELECT;
  23.   return btnNONE;
  24. }
  25.  
  26. void setup()
  27. {
  28.   Serial.begin (115200);
  29.   lcd.begin(16, 2);
  30.   lcd.setCursor(0,0);
  31.   lcd.print("Push the buttons");
  32. }
  33.  
  34. int repeat, lastButton = 0;
  35. unsigned long nextCheck = 0;
  36.  
  37. static byte pml009State[17] = {
  38.   0x0B, 0x58, 0x58, 0x00,
  39.   0x00, 0x00, 0xB0, 0x00,
  40.   0x00, 0x10, 0x00, 0x40,
  41.   0x40, 0xC0, 0x86, 0xC0,
  42.   0x86
  43. };
  44.  
  45. byte readState(byte byteIdx, byte bitShift, byte mask)
  46. {
  47.     return (byte)((pml009State[byteIdx] & mask) >> bitShift);
  48. }
  49.  
  50. void writeState(int value, byte byteIdx, byte bitShift, byte mask)
  51. {
  52.     pml009State[byteIdx] = (byte)(pml009State[byteIdx] & ~mask | (value << bitShift));
  53. }
  54.  
  55. const byte
  56.   byteEqHigh = 3,
  57.   byteEqMid = 4,
  58.   byteEqLow = 5,
  59.   byteLoudness = 6,
  60.   byteEqTreble = 7,
  61.   byteEqBass = 8,
  62.   byteSubwoofer = 9;
  63.  
  64. class Menu {
  65.   public:
  66.     virtual void processButton(int key, int repeat) = 0;
  67.     virtual void show() = 0;
  68.  
  69.   protected:
  70.     printSignedInteger(int value) {
  71.       if (value > 0) lcd.write('+');
  72.       else if (value == 0) lcd.write(' ');
  73.       lcd.print(value);
  74.     }
  75. };
  76.  
  77. class EqMenu : public Menu {
  78.   private:
  79.     byte bandByte = byteEqLow;
  80.  
  81.   int getCurrentValue() {
  82.     return
  83.       (readState(bandByte, 3, 0b00001000) ? -1 : +1) *
  84.       readState(bandByte, 0, 0b00000111);
  85.   }
  86.  
  87.   void processButton(int key, int repeat) override {
  88.     int delta = 0;
  89.    
  90.     if (key == btnRIGHT) bandByte = max(byteEqHigh, bandByte - 1);
  91.     else if (key == btnLEFT) bandByte = min(byteEqLow, bandByte + 1);
  92.     else if (key == btnUP) delta = +1;
  93.     else if (key == btnDOWN) delta = -1;
  94.  
  95.     if (delta != 0) {
  96.       int newValue = min(+6, max(-6, getCurrentValue() + delta));
  97.       writeState(abs(newValue), bandByte, 0, 0b00000111);
  98.       writeState(newValue >= 0 ? 0 : 1, bandByte, 3, 0b00001000);
  99.     }
  100.   }
  101.  
  102.   void show() override {
  103.     switch (bandByte) {
  104.       case byteEqLow:
  105.         lcd.print("EQ Low:  ");
  106.         break;
  107.       case byteEqMid:
  108.         lcd.print("EQ Mid:  ");
  109.         break;
  110.       case byteEqHigh:
  111.         lcd.print("EQ High: ");
  112.         break;
  113.     }
  114.     printSignedInteger(getCurrentValue());
  115.   }
  116. };
  117.  
  118. class BassTrebleMenu : public Menu {
  119.   private:
  120.     byte bandByte = byteEqBass;
  121.  
  122.   int getCurrentValue(int shift) {
  123.     return
  124.       (readState(bandByte, shift + 3, 0b00001000 << shift) ? -1 : +1) *
  125.       readState(bandByte, shift, 0b00000111 << shift);
  126.   }
  127.  
  128.   void processButton(int key, int repeat) override {
  129.     int delta = 0;
  130.    
  131.     if (key == btnRIGHT) bandByte = max(byteEqTreble, bandByte - 1);
  132.     else if (key == btnLEFT) bandByte = min(byteEqBass, bandByte + 1);
  133.     else if (key == btnUP) delta = +1;
  134.     else if (key == btnDOWN) delta = -1;
  135.  
  136.     if (delta != 0) {
  137.       auto shift = (bandByte == byteEqBass ? 1 : 2);
  138.       int newValue = min(+6, max(-6, getCurrentValue(shift) + delta));
  139.       writeState(abs(newValue), bandByte, shift, 0b00000111 << shift);
  140.       writeState(newValue >= 0 ? 0 : 1, bandByte, shift + 3, 0b00001000 << shift);
  141.     }
  142.   }
  143.  
  144.   void show() override {
  145.     switch (bandByte) {
  146.       case byteEqBass:
  147.         lcd.print("Bass:   ");
  148.         break;
  149.       case byteEqTreble:
  150.         lcd.print("Treble: ");
  151.         break;
  152.     }
  153.     printSignedInteger(getCurrentValue(bandByte == byteEqBass ? 1 : 2));
  154.   }
  155. };
  156.  
  157. class LoudnessMenu : public Menu {
  158.   private:
  159.     int lastActiveMode = 1;
  160.     const byte modes[3] = { 4, 11, 15 };
  161.  
  162.   public:
  163.     void processButton(int key, int repeat) override {
  164.       if (key == btnUP) writeState(modes[lastActiveMode], 6, 4, 0b11110000);
  165.       else if (key == btnDOWN) writeState(0, 6, 4, 0b11110000);
  166.       else if (key == btnLEFT) lastActiveMode = max(0, lastActiveMode - 1 );
  167.       else if (key == btnRIGHT) lastActiveMode = min(2, lastActiveMode + 1 );
  168.       if (readState(6, 4, 0b11110000)) writeState(modes[lastActiveMode], 6, 4, 0b11110000);
  169.     }
  170.  
  171.     void show() override {
  172.       lcd.print("Loudness: ");
  173.       switch(readState(6, 4, 0b11110000)) {
  174.         case 0:
  175.           lcd.print("OFF");
  176.           break;
  177.         case 4:
  178.           lcd.print("LOW");
  179.           break;
  180.         case 11:
  181.           lcd.print("MID");
  182.           break;
  183.         case 15:
  184.           lcd.print("HIGH");
  185.           break;
  186.       }
  187.     }
  188. };
  189.  
  190. class SubSwitchMenu : public Menu {
  191.   private:
  192.     int lastActiveMode = 1;
  193.  
  194.   public:
  195.     void processButton(int key, int repeat) override {
  196.       auto state = readState(9, 3, 0b111000);
  197.       if (state & 0b11) lastActiveMode = state;
  198.      
  199.       if (key == btnUP) writeState(lastActiveMode, 9, 3, 0b111000);
  200.       else if (key == btnDOWN) writeState(0, 9, 3, 0b11000);
  201.       else if (key == btnLEFT && (state & 0b11)) writeState(0, 9, 5, 0b100000);
  202.       else if (key == btnRIGHT && (state & 0b11)) writeState(1, 9, 5, 0b100000);
  203.     }
  204.  
  205.     void show() override {
  206.       lcd.print("Sub: ");
  207.       if (readState(9, 3, 0b11000)) {
  208.         lcd.print(readState(9, 3, 0b100000) ? "REVERSE" : "NORMAL");
  209.       } else {
  210.         lcd.print("OFF");
  211.       }
  212.     }
  213. };
  214.  
  215. class SubLevelsMenu : public Menu {
  216.   private:
  217.     int level;
  218.  
  219.   public:
  220.     void processButton(int key, int repeat) override {
  221.       auto cutoff = readState(9, 3, 0b11000);
  222.       if (key == btnUP) level = min(+6, level + 1);
  223.       else if (key == btnDOWN) level = max(-6, level - 1);
  224.       else if (key == btnLEFT) writeState(max(1, cutoff - 1), 9, 3, 0b11000);
  225.       else if (key == btnRIGHT) writeState(min(3, cutoff + 1), 9, 3, 0b11000);
  226.     }
  227.  
  228.     void show() override {
  229.       lcd.print("Sub: ");
  230.       switch(readState(9, 3, 0b11000)) {
  231.         case 0:
  232.           lcd.print("off ");
  233.           break;
  234.         case 1:
  235.           lcd.print("50 Hz ");
  236.           break;
  237.         case 2:
  238.           lcd.print("80 Hz ");
  239.           break;
  240.         case 3:
  241.           lcd.print("125 Hz ");
  242.           break;
  243.       }
  244.       printSignedInteger(level);
  245.     }
  246. };
  247.  
  248. class HighpassMenu : public Menu {
  249.   public:
  250.     void processButton(int key, int repeat) override {
  251.       auto cutoff = readState(9, 6, 0b11000000);
  252.       if (key == btnLEFT) writeState(max(0, cutoff - 1), 9, 6, 0b11000000);
  253.       else if (key == btnRIGHT) writeState(min(3, cutoff + 1), 9, 6, 0b11000000);
  254.     }
  255.  
  256.     void show() override {
  257.       lcd.print("HPF: ");
  258.       switch(readState(9, 6, 0b11000000)) {
  259.         case 0:
  260.           lcd.print("off ");
  261.           break;
  262.         case 1:
  263.           lcd.print("50 Hz ");
  264.           break;
  265.         case 2:
  266.           lcd.print("80 Hz ");
  267.           break;
  268.         case 3:
  269.           lcd.print("125 Hz ");
  270.           break;
  271.       }
  272.     }
  273. };
  274.  
  275. class MainMenu : public Menu {
  276.   private:
  277.     Menu* menus[6] = { new EqMenu(), new BassTrebleMenu(), new LoudnessMenu(), new SubSwitchMenu(), new SubLevelsMenu(), new HighpassMenu() };
  278.     int currentMenu = 0;
  279.    
  280.   public:
  281.     void processButton(int key, int repeat) override {
  282.       if (key == btnSELECT && repeat == 0) {
  283.         currentMenu = (currentMenu + 1) % 6;
  284.       } else {
  285.         menus[currentMenu]->processButton(key, repeat);
  286.       }
  287.     }
  288.  
  289.     void show() override {
  290.       menus[currentMenu]->show();
  291.     }
  292. };
  293.  
  294. class FreqMenu : public Menu {
  295.   private:
  296.     int bandByte = byteEqLow;
  297.  
  298.   public:
  299.  
  300.     void processButton(int key, int repeat) override {
  301.       if (key == btnSELECT && repeat == 0) {
  302.         switch (bandByte) {
  303.           case byteEqLow: bandByte = byteEqMid; break;
  304.           case byteEqMid: bandByte = byteEqHigh; break;
  305.           case byteEqHigh: bandByte = byteEqBass; break;
  306.           case byteEqBass: bandByte = byteEqTreble; break;
  307.           case byteEqTreble: bandByte = byteEqLow; break;
  308.         }
  309.       }
  310.       if (key == btnUP && bandByte <= byteEqBass) {
  311.         auto q = readState(bandByte, 6, 0b11000000);
  312.         writeState(min(3, q + 1), bandByte, 6, 0b11000000);
  313.       }
  314.       else if (key == btnDOWN && bandByte <= byteEqBass) {
  315.         auto q = readState(bandByte, 6, 0b11000000);
  316.         writeState(max(0, q - 1), bandByte, 6, 0b11000000);
  317.       }
  318.       byte shift, mask;
  319.       switch (bandByte) {
  320.         case byteEqLow:
  321.         case byteEqMid:
  322.         case byteEqHigh:
  323.           shift = 4; mask = 0b110000;
  324.           break;
  325.         case byteEqBass:
  326.           shift = 5; mask = 0b1100000;
  327.           break;
  328.         case byteEqTreble:
  329.           shift = 6; mask = 0b11000000;
  330.           break;
  331.       }
  332.       if (key == btnLEFT) {
  333.         auto center = readState(bandByte, shift, mask);
  334.         writeState(max(0, center - 1), bandByte, shift, mask);
  335.       }
  336.       else if (key == btnRIGHT) {
  337.         auto center = readState(bandByte, shift, mask);
  338.         writeState(min(3, center + 1), bandByte, shift, mask);
  339.       }
  340.     }
  341.    
  342.     void show() override {
  343.       switch (bandByte) {
  344.         case byteEqLow:
  345.           lcd.print("L: ");
  346.           switch(readState(bandByte, 4, 0b110000)) {
  347.             case 0: lcd.print("40"); break;
  348.             case 1: lcd.print("80"); break;
  349.             case 2: lcd.print("100"); break;
  350.             case 3: lcd.print("160"); break;
  351.           }
  352.           break;
  353.         case byteEqMid:
  354.           lcd.print("M: ");
  355.           switch(readState(bandByte, 4, 0b110000)) {
  356.             case 0: lcd.print("200"); break;
  357.             case 1: lcd.print("500"); break;
  358.             case 2: lcd.print("1k"); break;
  359.             case 3: lcd.print("2k"); break;
  360.           }
  361.           break;
  362.         case byteEqHigh:
  363.           lcd.print("H: ");
  364.           switch(readState(bandByte, 4, 0b110000)) {
  365.             case 0: lcd.print("3k"); break;
  366.             case 1: lcd.print("8k"); break;
  367.             case 2: lcd.print("10k"); break;
  368.             case 3: lcd.print("12k"); break;
  369.           }
  370.           break;
  371.         case byteEqBass:
  372.           lcd.print("B: ");
  373.           switch(readState(bandByte, 5, 0b1100000)) {
  374.             case 0: lcd.print("160"); break;
  375.             case 1: lcd.print("100"); break;
  376.             case 2: lcd.print("63"); break;
  377.             case 3: lcd.print("40"); break;
  378.           }
  379.           break;
  380.         case byteEqTreble:
  381.           lcd.print("T: ");
  382.           switch(readState(bandByte, 6, 0b11000000)) {
  383.             case 0: lcd.print("10k"); break;
  384.             case 1: lcd.print("6k"); break;
  385.             case 2: lcd.print("4k"); break;
  386.             case 3: lcd.print("2k"); break;
  387.           }
  388.           break;
  389.       }
  390.       if (bandByte <= byteEqLow) {
  391.         lcd.write('/');
  392.         switch (readState(bandByte, 6, 0b11000000)){
  393.           case 0: lcd.print("2W"); break;
  394.           case 1: lcd.print("1W"); break;
  395.           case 2: lcd.print("1N"); break;
  396.           case 3: lcd.print("2N"); break;
  397.         }
  398.       }
  399.     }
  400. };
  401.  
  402. class RootMenu : public Menu {
  403.   private:
  404.     Menu* menus[2] = { new MainMenu(), new FreqMenu() };
  405.     int currentMenu = 0;
  406.    
  407.   public:
  408.     void processButton(int key, int repeat) override {
  409.       if (key == btnSELECT && repeat == 2) {
  410.         currentMenu = (currentMenu + 1) % 2;
  411.       } else {
  412.         menus[currentMenu]->processButton(key, repeat);
  413.       }
  414.       show();
  415.       Serial.write(0xFF);
  416.       Serial.write(pml009State + 3, 7);
  417.     }
  418.  
  419.     void show() override {
  420.       lcd.clear();
  421.       lcd.setCursor(0,0);
  422.       lcd.print(currentMenu == 0 ? "> " : "  ");
  423.       menus[0]->show();
  424.       lcd.setCursor(0,1);
  425.       lcd.print(currentMenu == 1 ? "> " : "  ");
  426.       menus[1]->show();
  427.       lcd.setCursor(13,1);
  428.       lcd.print(pml009State[1]);
  429.     }
  430. };
  431.  
  432. RootMenu root;
  433.  
  434. // filter by:
  435. // repeat==2 is long press (use greater number for longer delay)
  436. // repeat==0 is short single press
  437. // repeat>=1 is repeated action
  438.  
  439. int inputPos = 0;
  440. unsigned long inputTimer = 0;
  441.  
  442. void loop()
  443. {
  444.   while(Serial.available()) {
  445.     if (millis() - inputTimer < 100 && inputPos > 0) {
  446.       pml009State[inputPos++] = Serial.read();
  447.       if (inputPos > 9) {
  448.         inputPos = 0;
  449.         inputTimer = 0;
  450.         root.show();
  451.       }
  452.     }
  453.     else if (Serial.read() == 0xFF) { // sync
  454.       inputPos = 3;
  455.       inputTimer = millis();
  456.     }
  457.   }
  458.  
  459.   lcd_key = read_LCD_buttons();
  460.  
  461.   if (lcd_key < btnNONE && millis() >= nextCheck) {
  462.     ++repeat;
  463.     lastButton = lcd_key;
  464.     if (repeat > 1) {
  465.       root.processButton(lcd_key, repeat);
  466.     }
  467.     nextCheck = millis() + (repeat > 1 ? 150 : 500);
  468.   }
  469.   else if (lcd_key == btnNONE && nextCheck > millis()) {
  470.     if (repeat == 1) {
  471.       root.processButton(lastButton, repeat = 0);
  472.     }
  473.     nextCheck = 0;
  474.     repeat = 0;
  475.   }
  476. }
Add Comment
Please, Sign In to add comment