Hi.
Those of you who answer my threads may remember me.
My mp3 player project is coming along nicely.
I have now got the menu logic working and I'm quite happy with it so far.
My problem is that I am currently struggling to implement some functionality.
My menu logic works like this:
1. Setup code sets the initial menu and position of the cursor.
2. Main loop reads menu value and position value and waits for input
3. Input is received, code is executed and menu changed if applicable.
First, I am trying to implement a timeout. If no input is received for 10 seconds, it should go to a special "menu" where OLED screen power save is turned on and the menu navigation buttons are redefined to change songs instead. This is important. Currently I start a function that waits for 10 secs then sets the menu to that special case, this doesnt work at all because it does not run continously. How could I implement this?
Secondly I am trying to implement volume up and down and play/pause button. The problem is that my menu code is waiting for input, so it does not recognise when these buttons are pressed. I cannot use interrupts because the Seeeduino Xiao stops using pins 5 and 7 which I use for serial communication with the player and I2C communication with the OLED screen. I want these buttons to work at all times because volume up/down is important in case of sudden volume increase due to whatever reason.
Options: I could add these buttons to my code in each and every case of the menu, but this is very excessive. I could abandon my requirement to always have them functional by implementing functionality only in the timeout menu above. However I was hoping there may be easier ways.
Regarding pins 7 and 5 not working when using interrupts, it says to see this: https://github.com/Seeed-Studio/ArduinoCore-samd/blob/master/variants/XIAO_m0/variant.cpp for more info, but I am not too sure what I am looking at.
I'll post my code, since I know you'll ask, but it is very long, messy some places, contains legacy snippets commented out and things that needs to be redone and finally misses some functionality. I don't really expect you to read it entirely.
I welcome any improvement on the code regardless of being out of scope with my questions.
Sorry if I missed something, let me know if I need to provide more info or anything else.
Those of you who answer my threads may remember me.
My mp3 player project is coming along nicely.
I have now got the menu logic working and I'm quite happy with it so far.
My problem is that I am currently struggling to implement some functionality.
My menu logic works like this:
1. Setup code sets the initial menu and position of the cursor.
2. Main loop reads menu value and position value and waits for input
3. Input is received, code is executed and menu changed if applicable.
First, I am trying to implement a timeout. If no input is received for 10 seconds, it should go to a special "menu" where OLED screen power save is turned on and the menu navigation buttons are redefined to change songs instead. This is important. Currently I start a function that waits for 10 secs then sets the menu to that special case, this doesnt work at all because it does not run continously. How could I implement this?
Secondly I am trying to implement volume up and down and play/pause button. The problem is that my menu code is waiting for input, so it does not recognise when these buttons are pressed. I cannot use interrupts because the Seeeduino Xiao stops using pins 5 and 7 which I use for serial communication with the player and I2C communication with the OLED screen. I want these buttons to work at all times because volume up/down is important in case of sudden volume increase due to whatever reason.
Options: I could add these buttons to my code in each and every case of the menu, but this is very excessive. I could abandon my requirement to always have them functional by implementing functionality only in the timeout menu above. However I was hoping there may be easier ways.
Regarding pins 7 and 5 not working when using interrupts, it says to see this: https://github.com/Seeed-Studio/ArduinoCore-samd/blob/master/variants/XIAO_m0/variant.cpp for more info, but I am not too sure what I am looking at.
I'll post my code, since I know you'll ask, but it is very long, messy some places, contains legacy snippets commented out and things that needs to be redone and finally misses some functionality. I don't really expect you to read it entirely.
I welcome any improvement on the code regardless of being out of scope with my questions.
Sorry if I missed something, let me know if I need to provide more info or anything else.
Code:
#include <SoftwareSerial.h>
#include <DFPlayerMini_Fast.h>
#include <Button.h>
#include <U8g2lib.h>
#include <U8x8lib.h>
#include <Wire.h>
DFPlayerMini_Fast player;
Button btnMenu(10);
Button btnLeft(9);
Button btnRight(8);
Button btnPlayPause(3);
Button btnVolUp(1);
Button btnVolDown(2);
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ A5, /* data=*/ A4);
//SoftwareSerial mySerial(1, 2); // RX, TX
int menuState = 1; //0 menu is continue playing music. 1 is main menu, 2 is folder menu, 7 is folder 2, 3 is play mode, 4 is EQ menu, 5 is music menu
int cursorPos = 0; //0 is first position in every menu, but specifics may depend on menu
int folderNr = 0; //number to pass to shuffle function
unsigned long int tracks[999];
unsigned long timeout = 0;
const byte busyPin = 0;
// 'pixil-frame-0(1)', 128x32px
const uint8_t mainMenu[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x0e, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xff, 0xff, 0x01,
0x00, 0x00, 0x03, 0x00, 0x00, 0x80, 0x09, 0x00, 0x00, 0x18, 0x0c, 0x00,
0x80, 0x00, 0x00, 0x02, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x60, 0x10, 0x00,
0x00, 0x04, 0x10, 0x00, 0x80, 0x08, 0x21, 0x02, 0x00, 0x00, 0x19, 0x00,
0x00, 0x18, 0x70, 0x00, 0x00, 0x02, 0x20, 0x00, 0x80, 0x08, 0x21, 0x02,
0x00, 0x00, 0x13, 0x00, 0x00, 0x06, 0x4c, 0x00, 0x00, 0xc2, 0x21, 0x00,
0x80, 0x08, 0x71, 0x02, 0x00, 0x00, 0x37, 0x00, 0x00, 0x01, 0x43, 0x01,
0x00, 0x21, 0x42, 0x00, 0x80, 0x1c, 0x51, 0x02, 0x00, 0x00, 0x6f, 0x00,
0x00, 0xc1, 0x40, 0x03, 0xc0, 0xf1, 0x44, 0x00, 0x80, 0x94, 0x53, 0x02,
0x00, 0x00, 0xf9, 0x00, 0x00, 0x3a, 0x40, 0x07, 0x40, 0xc0, 0x44, 0x00,
0x80, 0x94, 0x52, 0x02, 0x00, 0x00, 0x01, 0x00, 0x80, 0x16, 0x40, 0x03,
0x80, 0x60, 0x44, 0x00, 0x80, 0x94, 0x72, 0x02, 0x00, 0x78, 0x01, 0x00,
0xc0, 0x1a, 0x40, 0x01, 0x80, 0x60, 0x44, 0x00, 0x80, 0x9c, 0x72, 0x02,
0x00, 0x84, 0x01, 0x00, 0xe0, 0x14, 0x40, 0x00, 0x00, 0x31, 0x42, 0x00,
0x80, 0x9c, 0x23, 0x02, 0x00, 0x82, 0x01, 0x00, 0xc0, 0x1c, 0x60, 0x00,
0x00, 0x31, 0x21, 0x00, 0x80, 0x88, 0x23, 0x02, 0x00, 0xc6, 0x01, 0x00,
0x80, 0x18, 0x18, 0x00, 0x00, 0x1a, 0x22, 0x00, 0x80, 0x08, 0x21, 0x02,
0x00, 0xfe, 0x01, 0x00, 0x00, 0x18, 0x06, 0x00, 0x00, 0x1a, 0x14, 0x00,
0x00, 0xff, 0xff, 0x01, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00,
0x00, 0x0c, 0x08, 0x00, 0x00, 0xfe, 0xff, 0x00, 0x00, 0xfc, 0x00, 0x00,
0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
// 'folder1', 128x32px
const uint8_t folder1[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1c, 0x00,
0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00,
0x00, 0x00, 0x13, 0x00, 0x00, 0x80, 0x09, 0x00, 0x00, 0xc0, 0x20, 0x00,
0x00, 0xc0, 0x20, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x00, 0x60, 0x10, 0x00,
0x00, 0x30, 0xe0, 0x00, 0x00, 0x30, 0xe0, 0x00, 0x00, 0x30, 0xe0, 0x00,
0x00, 0x18, 0x70, 0x00, 0x00, 0x0c, 0x98, 0x00, 0x00, 0x0c, 0x98, 0x00,
0x00, 0x0c, 0x98, 0x00, 0x00, 0x06, 0x4c, 0x00, 0x00, 0x02, 0x86, 0x00,
0x00, 0x02, 0x86, 0x00, 0x00, 0x02, 0x86, 0x00, 0x00, 0x01, 0x43, 0x00,
0x00, 0x82, 0x81, 0x00, 0x00, 0x82, 0x81, 0x00, 0x00, 0x82, 0x81, 0x00,
0x00, 0xc1, 0x40, 0x00, 0x00, 0x74, 0x80, 0x00, 0x00, 0x74, 0x80, 0x00,
0x00, 0x74, 0x80, 0x00, 0x00, 0x3a, 0x40, 0x00, 0x00, 0x2c, 0x80, 0x00,
0x00, 0x2c, 0x80, 0x00, 0x00, 0x2c, 0x80, 0x00, 0x00, 0x16, 0x40, 0x00,
0x00, 0x34, 0x80, 0x00, 0x00, 0x34, 0x80, 0x00, 0x00, 0x34, 0x80, 0x00,
0x00, 0x1a, 0x40, 0x00, 0x00, 0x28, 0x80, 0x00, 0x00, 0x28, 0x80, 0x00,
0x00, 0x28, 0x80, 0x00, 0x00, 0x14, 0x40, 0x00, 0x00, 0x38, 0xc0, 0x00,
0x00, 0x38, 0xc0, 0x00, 0x00, 0x38, 0xc0, 0x00, 0x00, 0x1c, 0x60, 0x00,
0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00,
0x00, 0x18, 0x18, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x30, 0x0c, 0x00,
0x00, 0x30, 0x0c, 0x00, 0x00, 0x18, 0x06, 0x00, 0x00, 0x20, 0x03, 0x00,
0x00, 0x20, 0x03, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00, 0x90, 0x01, 0x00,
0x00, 0xe0, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00,
0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x08, 0x00,
0x00, 0x38, 0x1c, 0x00, 0x00, 0x38, 0x1c, 0x00, 0x00, 0x1c, 0x08, 0x00,
0x00, 0x44, 0x0e, 0x00, 0x00, 0x44, 0x22, 0x00, 0x00, 0x44, 0x22, 0x00,
0x00, 0x22, 0x0c, 0x00, 0x00, 0x64, 0x08, 0x00, 0x00, 0x64, 0x20, 0x00,
0x00, 0x64, 0x20, 0x00, 0x00, 0x32, 0x0a, 0x00, 0x00, 0x54, 0x08, 0x00,
0x00, 0x54, 0x10, 0x00, 0x00, 0x54, 0x18, 0x00, 0x00, 0x2a, 0x09, 0x00,
0x00, 0x4c, 0x08, 0x00, 0x00, 0x4c, 0x08, 0x00, 0x00, 0x4c, 0x20, 0x00,
0x00, 0x26, 0x1f, 0x00, 0x00, 0x44, 0x08, 0x00, 0x00, 0x44, 0x04, 0x00,
0x00, 0x44, 0x20, 0x00, 0x00, 0x22, 0x08, 0x00, 0x00, 0x44, 0x08, 0x00,
0x00, 0x44, 0x02, 0x00, 0x00, 0x44, 0x22, 0x00, 0x00, 0x22, 0x08, 0x00,
0x00, 0x38, 0x3e, 0x00, 0x00, 0x38, 0x3e, 0x00, 0x00, 0x38, 0x1c, 0x00,
0x00, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
// 'folder2', 128x32px
const uint8_t folder2[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1c, 0x00,
0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00,
0x00, 0x00, 0x13, 0x00, 0x00, 0x80, 0x09, 0x00, 0x00, 0xc0, 0x20, 0x00,
0x00, 0xc0, 0x20, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x00, 0x60, 0x10, 0x00,
0x00, 0x30, 0xe0, 0x00, 0x00, 0x30, 0xe0, 0x00, 0x00, 0x30, 0xe0, 0x00,
0x00, 0x18, 0x70, 0x00, 0x00, 0x0c, 0x98, 0x00, 0x00, 0x0c, 0x98, 0x00,
0x00, 0x0c, 0x98, 0x00, 0x00, 0x06, 0x4c, 0x00, 0x00, 0x02, 0x86, 0x00,
0x00, 0x02, 0x86, 0x00, 0x00, 0x02, 0x86, 0x00, 0x00, 0x01, 0x43, 0x00,
0x00, 0x82, 0x81, 0x00, 0x00, 0x82, 0x81, 0x00, 0x00, 0x82, 0x81, 0x00,
0x00, 0xc1, 0x40, 0x00, 0x00, 0x74, 0x80, 0x00, 0x00, 0x74, 0x80, 0x00,
0x00, 0x74, 0x80, 0x00, 0x00, 0x3a, 0x40, 0x00, 0x00, 0x2c, 0x80, 0x00,
0x00, 0x2c, 0x80, 0x00, 0x00, 0x2c, 0x80, 0x00, 0x00, 0x16, 0x40, 0x00,
0x00, 0x34, 0x80, 0x00, 0x00, 0x34, 0x80, 0x00, 0x00, 0x34, 0x80, 0x00,
0x00, 0x1a, 0x40, 0x00, 0x00, 0x28, 0x80, 0x00, 0x00, 0x28, 0x80, 0x00,
0x00, 0x28, 0x80, 0x00, 0x00, 0x14, 0x40, 0x00, 0x00, 0x38, 0xc0, 0x00,
0x00, 0x38, 0xc0, 0x00, 0x00, 0x38, 0xc0, 0x00, 0x00, 0x1c, 0x60, 0x00,
0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00,
0x00, 0x18, 0x18, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00, 0x30, 0x0c, 0x00,
0x00, 0x30, 0x0c, 0x00, 0x00, 0x18, 0x06, 0x00, 0x00, 0x20, 0x03, 0x00,
0x00, 0x20, 0x03, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00, 0x90, 0x01, 0x00,
0x00, 0xe0, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00,
0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x3e, 0x00,
0x00, 0x38, 0x1c, 0x00, 0x00, 0x38, 0x3e, 0x00, 0x00, 0x1c, 0x0e, 0x00,
0x00, 0x44, 0x02, 0x00, 0x00, 0x44, 0x02, 0x00, 0x00, 0x44, 0x20, 0x00,
0x00, 0x22, 0x11, 0x00, 0x00, 0x64, 0x02, 0x00, 0x00, 0x64, 0x02, 0x00,
0x00, 0x64, 0x20, 0x00, 0x00, 0x32, 0x11, 0x00, 0x00, 0x54, 0x1e, 0x00,
0x00, 0x54, 0x1e, 0x00, 0x00, 0x54, 0x10, 0x00, 0x00, 0x2a, 0x0e, 0x00,
0x00, 0x4c, 0x20, 0x00, 0x00, 0x4c, 0x22, 0x00, 0x00, 0x4c, 0x08, 0x00,
0x00, 0x26, 0x11, 0x00, 0x00, 0x44, 0x20, 0x00, 0x00, 0x44, 0x22, 0x00,
0x00, 0x44, 0x08, 0x00, 0x00, 0x22, 0x11, 0x00, 0x00, 0x44, 0x22, 0x00,
0x00, 0x44, 0x22, 0x00, 0x00, 0x44, 0x08, 0x00, 0x00, 0x22, 0x11, 0x00,
0x00, 0x38, 0x1c, 0x00, 0x00, 0x38, 0x1c, 0x00, 0x00, 0x38, 0x08, 0x00,
0x00, 0x1c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
void setup() {
btnMenu.begin();
btnLeft.begin();
btnRight.begin();
btnVolDown.begin();
btnVolUp.begin();
btnPlayPause.begin();
Wire.begin();
Serial.begin(115200);
Serial1.begin(9600);
player.begin(Serial1, true);
u8g2.begin();
u8g2.setFont(u8g2_font_profont12_mf); //if space is required, use mr not mf
u8g2.setDrawColor(1);
u8g2.clearBuffer();
u8g2.drawStr(0, 15, "starting");
u8g2.sendBuffer();
Serial.println("reached end of setup");
delay(200);
player.startDAC();
player.volumeAdjustSet(1);
player.volumeAdjustSet(1);
player.volume(4);
player.volume(4);
}
void loop() { //frame Coords: 0,0 , 32,0 , 64,0 , 96,0 32 width 21 length
//add menuState 0 (music player default)
if (menuState == 0) {
u8g2.clearBuffer();
menuFrameClear();
u8g2.setPowerSave(1);
//menuTimeout();
while (!btnMenu.pressed() && !btnLeft.pressed() && !btnRight.pressed()) {
//menuTimeout();
if (btnMenu.released()) {
u8g2.setPowerSave(0);
menuState = 1;
break;
}
if (btnLeft.released()) {
player.playPrevious();
break;
}
if (btnRight.released()) {
player.playNext();
break;
}
}
}
//menuState 1, main menu
if (menuState == 1) { //main menu, does not handle any commands to DFplayer
u8g2.clearBuffer(); //this clears the buffer entirely, add the main menu bitmap, draws a frame around the first item then pushes it to screen.
u8g2.drawXBMP(0, 0, 128, 32, mainMenu);
//u8g2.drawFrame(0, 0, 32, 21);
u8g2.sendBuffer();
Serial.println("draw menu"); //debug
//cursorPos = 0;
Serial.println(cursorPos); //debug
//menuTimeout();
cursorChange:
switch (cursorPos) { //each case instance handles removal and insertion of applicable frame
case 0: //cursor is folders
menuFrameClear(); //makes all frames transparent in buffer
u8g2.drawFrame(0, 0, 32, 21); //add correct frame, push to screen
u8g2.sendBuffer();
Serial.println("frame drawn"); //debug
while (!btnMenu.pressed() && !btnLeft.pressed() && !btnRight.pressed()) { //required to make code pause until input is received
//menuTimeout();
if (btnMenu.released()) { //if menu button is pressed, enter folder menu
menuState = 2; //this changes the menu state. Program should then exit the parent if loop and proceed to next if loop (next menu). This rarely happens.
cursorPos = 0; //menuState 2 handles removal of previous menu. Cursor remains in 0 position.
Serial.println("menu case 0"); //debug
break;
}
if (btnRight.released()) {
cursorPos = 1; //move cursor to right
Serial.println("right case 0"); //debug
break;
}
if (btnLeft.released()) {
cursorPos = 3; //loop around to the left
Serial.println("left case 0"); //debug
break;
}
}
break;
case 1: //cursor is at play mode
menuFrameClear(); //remove all frames, add new one
u8g2.drawFrame(32, 0, 32, 21);
u8g2.sendBuffer();
while (!btnMenu.pressed() && !btnLeft.pressed() && !btnRight.pressed()) {
//menuTimeout();
if (btnMenu.released()) {
menuState = 3; //set menu to play mode, state 3 menu handles delete of previous screen
cursorPos = 0;
Serial.println("menu case 1");
break;
}
if (btnRight.released()) {
cursorPos = 2; //send cursor to the right
Serial.println("right case 1");
break;
}
if (btnLeft.released()) {
cursorPos = 0; //send cursor to the Left
Serial.println("left case 1");
break;
}
}
break;
case 2:
menuFrameClear(); //remove all frames add new one
u8g2.drawFrame(64, 0, 32, 21);
u8g2.sendBuffer();
while (!btnMenu.pressed() && !btnLeft.pressed() && !btnRight.pressed()) {
//menuTimeout();
if (btnMenu.released()) {
menuState = 4; //set menu to EQ mode, state 4 menu handles delete of previous screen
cursorPos = 0;
Serial.println("menu case 2");
break;
}
if (btnRight.released()) {
cursorPos = 3; //send cursor to the right
Serial.println("right case 2");
break;
}
if (btnLeft.released()) {
cursorPos = 1; //send cursor to the Left
Serial.println("left case 2");
break;
}
}
break;
case 3:
menuFrameClear(); //remove all frames
u8g2.drawFrame(96, 0, 32, 21);
u8g2.sendBuffer();
while (!btnMenu.pressed() && !btnLeft.pressed() && !btnRight.pressed()) {
//menuTimeout();
if (btnMenu.released()) {
menuState = 5; //set menu to music mode, state 5 menu handles delete of previous screen
cursorPos = 0;
Serial.println("menu case 3");
break;
}
if (btnRight.released()) {
cursorPos = 0; //send cursor to the right
Serial.println("right case 3");
break;
}
if (btnLeft.released()) {
cursorPos = 2; //send cursor to the Left
Serial.println("left case 3");
break;
}
}
break;
}
if (menuState != 1){
}
else {
goto cursorChange;
}
}
//menuState 2 (folders)
if (menuState == 2) { //folder menu 1
u8g2.clearBuffer(); //this clears the buffer entirely, add the folder 1 bitmap, draws a frame around the first item then pushes it to screen.
u8g2.drawXBM(0, 0, 128, 32, folder1);
//u8g2.drawFrame(0, 0, 32, 21);
u8g2.sendBuffer();
//cursorPos == 0
//menuTimeout();
cursorChange2:
switch (cursorPos) { //each case instance handles removal and insertion of applicable frame
case 0: //cursor is at folder 01
menuFrameClear(); //makes all frames transparent in buffer, adds a frame then pushed buffer to screen
u8g2.drawFrame(0, 0, 32, 21);
u8g2.sendBuffer();
while (!btnMenu.pressed() && !btnLeft.pressed() && !btnRight.pressed()) {
//menuTimeout();
if (btnMenu.released()) { //if menu button is released, play folder 01
player.repeatFolder(1); //player large folder 1
//add sending to menu 0
folderNr = 1;
delay(100); //time for playing to start
//nextHandler();
menuState = 1;
Serial.println(player.currentVolume());
Serial.println(player.currentEQ());
Serial.println(player.currentMode());
Serial.println(player.currentVersion());
Serial.println(player.currentSdTrack());
break;
}
if (btnRight.released()) {
cursorPos = 1; //move cursor to right
break;
}
if (btnLeft.released()) {
menuState = 7;
cursorPos = 3; //loop around to the left
break;
}
}
break;
case 1: //cursor is at folder 2
menuFrameClear(); //remove all frames, add new one
u8g2.drawFrame(32, 0, 32, 21);
u8g2.sendBuffer();
while (!btnMenu.pressed() && !btnLeft.pressed() && !btnRight.pressed()) {
//menuTimeout();
if (btnMenu.released()) {
player.repeatFolder(2); //play large folder 2
//add sending to menu 0
folderNr = 2;
delay(100); //time for playing to start
//nextHandler();
Serial.println(player.currentSdTrack());
break;
}
if (btnRight.released()) {
cursorPos = 2; //send cursor to the right
break;
}
if (btnLeft.released()) {
cursorPos = 0; //send cursor to the Left
break;
}
}
break;
case 2: //cursor is at folder 3
menuFrameClear(); //remove all frames add new one
u8g2.drawFrame(64, 0, 32, 21);
u8g2.sendBuffer();
while (!btnMenu.pressed() && !btnLeft.pressed() && !btnRight.pressed()) {
//menuTimeout();
if (btnMenu.released()) {
player.repeatFolder(3); //play large folder 3
folderNr = 3;
delay(100); //time for playing to start
//nextHandler();
break;
}
if (btnRight.released()) {
cursorPos = 3; //send cursor to the right
break;
}
if (btnLeft.released()) {
cursorPos = 1; //send cursor to the Left
break;
}
}
break;
case 3: //cursor is at folder 4
menuFrameClear(); //remove all frames add new one
u8g2.drawFrame(96, 0, 32, 21);
u8g2.sendBuffer();
while (!btnMenu.pressed() && !btnLeft.pressed() && !btnRight.pressed()) {
//menuTimeout();
if (btnMenu.released()) {
player.repeatFolder(4);
folderNr = 4;
delay(100); //time for playing to start
//nextHandler();
break;
}
if (btnRight.released()) {
menuState = 7;
cursorPos = 0; //send cursor to the right
break;
}
if (btnLeft.released()) {
cursorPos = 2; //send cursor to the Left
break;
}
}
break;
}
if (menuState == 2) {
goto cursorChange2;
}
else {
}
}
//menuState 7 (folders 2)
if (menuState == 7) { //folder menu 1
u8g2.clearBuffer(); //this clears the buffer entirely, add the folder 1 bitmap, draws a frame around the first item then pushes it to screen.
u8g2.drawXBM(0, 0, 128, 32, folder1);
u8g2.drawFrame(0, 0, 32, 21);
u8g2.sendBuffer(); //exception: menustate 7 does not override previous cursorpos due to navigation from menustate 2 from cursorpos 0
//menuTimeout();
cursorChange7:
switch (cursorPos) { //each case instance handles removal and insertion of applicable frame
case 0: //cursor is at folder 05
menuFrameClear(); //makes all frames transparent in buffer, adds a frame then pushed buffer to screen
u8g2.drawFrame(0, 0, 32, 21);
u8g2.sendBuffer();
while (!btnMenu.pressed() && !btnLeft.pressed() && !btnRight.pressed()) {
//menuTimeout();
if (btnMenu.released()) { //if menu button is released, play folder 01
player.repeatFolder(5); //player large folder 5
folderNr = 5;
delay(100); //time for playing to start
//nextHandler();
break;
}
if (btnRight.released()) {
cursorPos = 1; //move cursor to right
break;
}
if (btnLeft.released()) {
cursorPos = 3; //loop around to the left
menuState = 2;
break;
}
}
break;
case 1: //cursor is at folder 6
menuFrameClear(); //remove all frames, add new one
u8g2.drawFrame(32, 0, 32, 21);
u8g2.sendBuffer();
while (!btnMenu.pressed() && !btnLeft.pressed() && !btnRight.pressed()) {
//menuTimeout();
if (btnMenu.released()) {
player.repeatFolder(6); //play large folder 6
folderNr = 6;
delay(100); //time for playing to start
//nextHandler();
break;
}
if (btnRight.released()) {
cursorPos = 2; //send cursor to the right
break;
}
if (btnLeft.released()) {
cursorPos = 0; //send cursor to the Left
break;
}
}
break;
case 2: //cursor is at folder 7
menuFrameClear(); //remove all frames add new one
u8g2.drawFrame(64, 0, 32, 21);
u8g2.sendBuffer();
while (!btnMenu.pressed() && !btnLeft.pressed() && !btnRight.pressed()) {
//menuTimeout();
if (btnMenu.released()) {
player.repeatFolder(7); //play large folder 7
folderNr = 7;
delay(100); //time for playing to start
//nextHandler();
break;
}
if (btnRight.released()) {
cursorPos = 3; //send cursor to the right
break;
}
if (btnLeft.released()) {
cursorPos = 1; //send cursor to the Left
break;
}
}
break;
case 3: //cursor is at folder 8
menuFrameClear(); //remove all frames add new one
u8g2.drawFrame(96, 0, 32, 21);
u8g2.sendBuffer();
while (!btnMenu.pressed() && !btnLeft.pressed() && !btnRight.pressed()) {
//menuTimeout();
if (btnMenu.released()) {
player.repeatFolder(8);
folderNr = 8;
delay(100); //give time for the playing to start
//nextHandler();
break;
}
if (btnRight.released()) {
cursorPos = 0; //send cursor to the right
menuState = 2;
break;
}
if (btnLeft.released()) {
cursorPos = 2; //send cursor to the Left
break;
}
}
break;
}
}
if (menuState != 7) {
}
else {
goto cursorChange7;
}
}
//add menuState 3 (play mode), 4 modes, make new bitmap, C/P main menu code
//
//add menuState 4 (EQ mode) 6 options, make new bitmap need 6 cursorPositions, new frame clear function
//add mennuState 5 (music mode) requires selecting folder then track number. may need to let DFplayer know to continue after song is played. (this may need a function)
void menuFrameClear() {
u8g2.setDrawColor(0);
u8g2.drawFrame(0, 0, 32, 21);
u8g2.drawFrame(32, 0, 32, 21);
u8g2.drawFrame(64, 0, 32, 21);
u8g2.drawFrame(96, 0, 32, 21);
u8g2.setDrawColor(1);
return;
}
/*void nextHandler() {
attachInterrupt(digitalPinToInterrupt(busyPin), nextSong, FALLING); //interrupt plays next song when playing song is finished.
}
void nextSong() { //this is function is required to use interrupts when handling next song functionality.
player.playNext();
nextHandler();
}*/
void volDown() {
while (!btnVolDown.pressed()){}
player.decVolume();
volDown();
}
void volUp() {
while (!btnVolUp.pressed()){}
player.incVolume();
volUp();
}
void playPause() {
while (!btnPlayPause.pressed()){}
if (player.isPlaying() == true) {
player.pause();
}
else {
player.resume();
}
playPause();
}
void shuffleFolder(int folderNr) {
//n is array position
int n = 0;
int i = 1;
for (int i = 1; i = player.numTracksInFolder(folderNr); i++) {
//write i to n pos
tracks[n] == i;
n++;
}
shuffleArray(); //no idea if this is what I want it to do
playShuffle();
}
void playShuffle() {
int p = 1; //needs to be fixed, cannot use local variable.
for (int p = 1; p = player.numTracksInFolder(folderNr); p++) {
player.playFolder(folderNr, tracks[p]);
attachInterrupt(digitalPinToInterrupt(busyPin), playShuffle, RISING); //need to redo this
}
}
/*void shuffleArray(int * tracks, int size) //random randomizer code found online
{
int last = 0;
int temp = tracks[last];
for (int i = 0; i < size; i++)
{
int index = random(size);
tracks[last] = tracks[index];
last = index;
}
tracks[last] = temp; */
void shuffleArray() {
const size_t n = sizeof(tracks) / sizeof(tracks[0]);
randomSeed(A1);
for (size_t i = 0; i < n - 1; i++) {
size_t j = random(0, n - i);
int t = tracks[i];
tracks[i] = tracks[j];
tracks[j] = t;
}
}
void menuTimeout() {
while (!btnMenu.pressed() && !btnLeft.pressed() && !btnRight.pressed()) {
timeout = millis();
if (millis() - timeout >= 10000) {
menuState = 0;
}
}
}