// MP3 prehravac, minimalisticky model // (c) 18.10.2023 (rev.28.10.2023) Ivan Sivak #include #include #define Start_Byte 0x7E #define Version_Byte 0xFF #define Command_Length 0x06 #define End_Byte 0xEF #define Acknowledge 0x00 //nebude vracet info, [0x01: info, 0x00: no info] #define ADR_TRACK 8 #define ADR_EQUALIZER 10 #define PIN_BUSY 2 #define PIN_NEXT 5 #define PIN_PREV 6 #define PIN_PLAY 8 #define LED_GREEN 7 #define LED_YELLOW 13 #define ROT_CLK 12 #define ROT_DT 11 #define ROT_SW 10 #define MP3_NEXT 0x01 #define MP3_PREV 0x02 #define MP3_PLAY_TRACK 0x03 //parametr cislo stopy #define MP3_VOL_INC 0x04 #define MP3_VOL_DEC 0x05 #define MP3_VOLUME 0x06 #define MP3_EQUALIZER 0x07 #define MP3_PLAY 0x0D #define MP3_PAUSE 0x0E #define MP3_RESET 0x0C #define QUERY_ERROR 0x40 #define QUERY_TRACK 0x4C #define QUERY_TOTAL 0x48 #define LED_INTERVAL 256 #define BLINK_INTERVAL 512 #define TRACK_INTERVAL 4096 #define VOLUME_INIT 12 unsigned long trackTest = 0; unsigned long ledInfo = 0; unsigned long blinkLed = 0; int rotPred, rotCLK, rotSW, track, totalTrack; byte eq = 0; byte inactive = 0; bool playingMode; //----------------------------------------------------------------------- void setWord(int addr, int val) { EEPROM_update(addr, highByte(val)); EEPROM_update(addr + 1, lowByte(val)); } int getWord(int addr) { int result = ((word)EEPROM_read(addr) << 8) | EEPROM_read(addr + 1); if ((result < 1) || (result > 2999)) result = 1; return result; } //------------------------------------------------------------------------ void mp3cmd(byte CMD, byte Par1, byte Par2, int wait) { //odeslani dat Tx word checksum = -(Version_Byte + Command_Length + CMD + Acknowledge + Par1 + Par2); // checksum (2 bytes) byte command_line[10] = { Start_Byte, Version_Byte, Command_Length, CMD, Acknowledge, Par1, Par2, highByte(checksum), lowByte(checksum), End_Byte}; for (byte i = 0; i < 10; i++) { Serial_write(command_line[i]); } delay(wait); } word mp3response() { word result = 0; byte response[10] = {0, 0, 0, 0, 0, 0xff, 0xff, 0, 0, 0}; byte i = 255; do { //ceka se na data Rx delay(1); i--; } while ((!Serial_available()) && (i > 0)); i = 0; while (Serial_available()) { //prijem dat Rx if (i < 10) { response[i] = Serial_read(); } i++; } if (i == 10) { result = response[5]; result = (result << 8) | response[6]; } return result; } word mp3query(byte cmd) { mp3cmd(cmd, 0, 0, 512); return mp3response(); } void mp3play() { playingMode = !playingMode; if (playingMode) { mp3cmd(MP3_PLAY, 0, 0, 256); //play } else { mp3cmd(MP3_PAUSE, 0, 0, 256); //pause } } void mp3seek(int trackNo) { int track = trackNo; if (track > totalTrack) track = totalTrack; if (track < 1) track = 1; mp3cmd(MP3_PLAY_TRACK, highByte(track), lowByte(track), 512); playingMode = true; } void mp3eq(bool change) { if (change) { eq++; if (eq > 5) eq = 0; EEPROM_update(ADR_EQUALIZER, eq); } else { eq = EEPROM_read(ADR_EQUALIZER); if (eq > 5) eq = 0; } mp3cmd(MP3_EQUALIZER, 0, eq, 256); } bool mp3init() { totalTrack = 0; playingMode = true; digitalWrite(LED_GREEN, HIGH); digitalWrite(LED_YELLOW, HIGH); mp3cmd(MP3_RESET, 0, 0, 4096); //delay(3100); word err = mp3query(QUERY_ERROR); if ((err == 0x07) || (err == 0x08)) return false; mp3cmd(MP3_VOLUME, 0, VOLUME_INIT, 256); mp3eq(false); delay(256); mp3response(); delay(256); return true; } //----------------------------------------------------------------------- byte keyPressed() { byte result = 0; bool pressed; unsigned long t = millis(); do { pressed = false; if (!digitalRead(PIN_NEXT)) { bitSet(result, 0); //01 - next pressed = true; } if (!digitalRead(PIN_PREV)) { bitSet(result, 1); //02 - prev pressed = true; } if (!digitalRead(PIN_PLAY)) { result = 0x04; //04 - play / pause pressed = true; } if (!digitalRead(ROT_SW)) { result = 0x08; pressed = true; } } while (pressed); unsigned long t2 = millis(); t = t2 - t; if (t < 32) result = 0; //prilis kratky stisk if (t > 1024) bitSet(result, 7); //dlouhy stisk return result; } //----------------------------------------------------------------------- void setup() { Serial_begin_config(9600, SERIAL_8N1); delay(128); pinMode(LED_GREEN, OUTPUT); pinMode(LED_YELLOW, OUTPUT); pinMode(PIN_NEXT, INPUT_PULLUP); pinMode(PIN_PREV, INPUT_PULLUP); pinMode(PIN_PLAY, INPUT_PULLUP); pinMode(PIN_BUSY, INPUT); pinMode(ROT_CLK, INPUT); pinMode(ROT_DT, INPUT); pinMode(ROT_SW, INPUT_PULLUP); rotPred = digitalRead(ROT_CLK); while (!mp3init()); track = getWord(ADR_TRACK); mp3cmd(MP3_PLAY_TRACK, highByte(track), lowByte(track), 2048); } void loop() { if (inactive > 4) { //asi je pripojen PC-USB, nebo neni vlozena/vadna SD, tak nedelej nic, az do dalsiho zapnuti if ((millis() / BLINK_INTERVAL) != blinkLed) { digitalWrite(LED_YELLOW, HIGH); blinkLed = millis() / BLINK_INTERVAL; if (blinkLed % 2) digitalWrite(LED_GREEN, LOW); else digitalWrite(LED_GREEN, HIGH); } return; } byte k = keyPressed(); // tlacitka switch (k) { case 0x01: if (playingMode) mp3cmd(MP3_NEXT, 0, 0, 512); break; //dalsi case 0x02: if (playingMode) mp3cmd(MP3_PREV, 0, 0, 512); break; //predesla case 0x81: if (playingMode) mp3seek(mp3query(QUERY_TRACK) + 10); break; //o deset dal case 0x82: if (playingMode) mp3seek(mp3query(QUERY_TRACK) - 10); break; //o deset zpet case 0x83: mp3seek(1); break; //na zacatek; case 0x04: ; case 0x84: mp3play(); break;; case 0x08: mp3eq(true); break; case 0x88: eq = 5; mp3eq(true); break; } rotCLK = digitalRead(ROT_CLK); // hlasitost if (rotCLK != rotPred) { if (playingMode) { if (digitalRead(ROT_DT) != rotCLK) mp3cmd(MP3_VOL_INC, 0, 0, 128); else mp3cmd(MP3_VOL_DEC, 0, 0, 128); } rotPred = digitalRead(ROT_CLK); } if ((millis() / LED_INTERVAL) != ledInfo) { if (digitalRead(PIN_BUSY)) { //zastaveno digitalWrite(LED_GREEN, LOW); digitalWrite(LED_YELLOW, HIGH); if (playingMode) { if (inactive > 1) mp3cmd(MP3_NEXT, 0, 0, 512); //ma hrat, tak pusti dalsi stopu inactive++; trackTest = 0; } else inactive = 0; } else { inactive = 0; digitalWrite(LED_GREEN, HIGH); //hraje digitalWrite(LED_YELLOW, LOW); if ((millis() / TRACK_INTERVAL) != trackTest) { //test zmeny stopy int playingTrack = mp3query(QUERY_TRACK); if ((totalTrack < playingTrack) || (totalTrack > 3000)) totalTrack = mp3query(QUERY_TOTAL); if ((playingTrack < 3000) && (playingTrack > 0) && (playingTrack != track)) { //zmena stopy track = playingTrack; setWord(ADR_TRACK, track); digitalWrite(LED_YELLOW, HIGH); delay(256); } trackTest = (millis() / TRACK_INTERVAL); } } ledInfo = (millis() / LED_INTERVAL); } }