diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..9ea30ec --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,131 @@ +{ + "configurations": [ + { + "name": "!!! WARNING !!! AUTO-GENERATED FILE, PLEASE DO NOT MODIFY IT AND USE https://docs.platformio.org/page/projectconf/section_env_build.html#build-flags" + }, + { + "name": "Mac", + "macFrameworkPath": [], + "includePath": [ + "/Users/fabian/Documents/PlatformIO/Projects/esmp3/include", + "/Users/fabian/Documents/PlatformIO/Projects/esmp3/src", + "/Users/fabian/Documents/PlatformIO/Projects/esmp3/lib/pubsubclient/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266mDNS/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266WebServer/src", + "/Users/fabian/Documents/PlatformIO/Projects/esmp3/.pio/libdeps/esp12e/MFRC522_ID63/src", + "/Users/fabian/Documents/PlatformIO/Projects/esmp3/lib/esp8266FTPServer", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/SD/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/SDFS/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266SdFat/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/SPI", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266WiFi/src", + "/Users/fabian/.platformio/lib/Adafruit MCP23017 Arduino Library_ID334", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/Wire", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/tools/sdk/include", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/tools/sdk/libc/xtensa-lx106-elf/include", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/cores/esp8266", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/tools/sdk/lwip2/include", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/variants/nodemcu", + "/Users/fabian/Documents/PlatformIO/Projects/esmp3/.pio/libdeps/esp12e/MCP23S17", + "/Users/fabian/.platformio/lib/FastLED_ID126", + "/Users/fabian/.platformio/lib/PubSubClient_ID89/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ArduinoOTA", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/DNSServer/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/EEPROM", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266AVRISP/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266HTTPClient/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266HTTPUpdateServer/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266LLMNR", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266NetBIOS", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266SSDP", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266WiFiMesh/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266httpUpdate/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/Ethernet/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/GDBStub/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/Hash/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/SPISlave/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/Servo/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/SoftwareSerial/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/TFT_Touch_Shield_V2", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/Ticker", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/esp8266/src", + "/Users/fabian/.platformio/packages/tool-unity", + "" + ], + "browse": { + "limitSymbolsToIncludedHeaders": true, + "path": [ + "/Users/fabian/Documents/PlatformIO/Projects/esmp3/include", + "/Users/fabian/Documents/PlatformIO/Projects/esmp3/src", + "/Users/fabian/Documents/PlatformIO/Projects/esmp3/lib/pubsubclient/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266mDNS/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266WebServer/src", + "/Users/fabian/Documents/PlatformIO/Projects/esmp3/.pio/libdeps/esp12e/MFRC522_ID63/src", + "/Users/fabian/Documents/PlatformIO/Projects/esmp3/lib/esp8266FTPServer", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/SD/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/SDFS/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266SdFat/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/SPI", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266WiFi/src", + "/Users/fabian/.platformio/lib/Adafruit MCP23017 Arduino Library_ID334", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/Wire", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/tools/sdk/include", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/tools/sdk/libc/xtensa-lx106-elf/include", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/cores/esp8266", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/tools/sdk/lwip2/include", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/variants/nodemcu", + "/Users/fabian/Documents/PlatformIO/Projects/esmp3/.pio/libdeps/esp12e/MCP23S17", + "/Users/fabian/.platformio/lib/FastLED_ID126", + "/Users/fabian/.platformio/lib/PubSubClient_ID89/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ArduinoOTA", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/DNSServer/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/EEPROM", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266AVRISP/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266HTTPClient/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266HTTPUpdateServer/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266LLMNR", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266NetBIOS", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266SSDP", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266WiFiMesh/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266httpUpdate/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/Ethernet/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/GDBStub/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/Hash/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/SPISlave/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/Servo/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/SoftwareSerial/src", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/TFT_Touch_Shield_V2", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/Ticker", + "/Users/fabian/.platformio/packages/framework-arduinoespressif8266/libraries/esp8266/src", + "/Users/fabian/.platformio/packages/tool-unity", + "" + ] + }, + "defines": [ + "PLATFORMIO=40100", + "ESP8266", + "ARDUINO_ARCH_ESP8266", + "ARDUINO_ESP8266_ESP12", + "VERSION=\"0.1-9-g88655b5-dirty\"", + "F_CPU=80000000L", + "__ets__", + "ICACHE_FLASH", + "ARDUINO=10805", + "ARDUINO_BOARD=\"PLATFORMIO_ESP12E\"", + "FLASHMODE_DIO", + "LWIP_OPEN_SRC", + "NONOSDK221=1", + "TCP_MSS=536", + "LWIP_FEATURES=1", + "LWIP_IPV6=0", + "VTABLES_IN_FLASH", + "" + ], + "intelliSenseMode": "clang-x64", + "cStandard": "c99", + "cppStandard": "c++11", + "compilerPath": "\"/Users/fabian/.platformio/packages/toolchain-xtensa/bin/xtensa-lx106-elf-gcc\" -mlongcalls -mtext-section-literals" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..272828b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ] +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..d800219 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,32 @@ +// AUTOMATICALLY GENERATED FILE. PLEASE DO NOT MODIFY IT MANUALLY + +// PIO Unified Debugger +// +// Documentation: https://docs.platformio.org/page/plus/debugging.html +// Configuration: https://docs.platformio.org/page/projectconf/section_env_debug.html + +{ + "version": "0.2.0", + "configurations": [ + { + "type": "platformio-debug", + "request": "launch", + "name": "PIO Debug", + "executable": "/Users/fabian/Documents/PlatformIO/Projects/esmp3/.pio/build/esp12e/firmware.elf", + "toolchainBinDir": "/Users/fabian/.platformio/packages/toolchain-xtensa/bin", + "preLaunchTask": { + "type": "PlatformIO", + "task": "Pre-Debug" + }, + "internalConsoleOptions": "openOnSessionStart" + }, + { + "type": "platformio-debug", + "request": "launch", + "name": "PIO Debug (skip Pre-Debug)", + "executable": "/Users/fabian/Documents/PlatformIO/Projects/esmp3/.pio/build/esp12e/firmware.elf", + "toolchainBinDir": "/Users/fabian/.platformio/packages/toolchain-xtensa/bin", + "internalConsoleOptions": "openOnSessionStart" + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..aa3b598 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# Ports + +| Device | Port | Connected to | +| ------ | ---- | ------------ | +| ESP | D0 | NFC: SDA | +| ESP | D1 | MCP: SCK (12) | +| ESP | D2 | MCP: SDA (13) | +| ESP | D3 | --free-- | +| ESP | D4 | --free-- | +| ESP | D5 | SCK | +| ESP | D6 | MISO | +| ESP | D7 | MOSI | +| ESP | D8 | MP3: XCS | +| MCP | B7 | MP3: XRESET +| MCP | B6 | AMP1: SD +| MCP | B5 | AMP2: SD +| MCP | B4 | MP3: XDCS +| MCP | B3 | MP3: CS +| MCP | B2 | MP3: DREQ +| MCP | A0 | BTN_PREV +| MCP | A1 | BTN_VOL_UP +| MCP | A2 | BTN_VOL_DOWN +| MCP | A3 | BTN_NEXT + +Buttons pull to GND if pushed -> Internal Pull-Up needed! diff --git a/include/config.h b/include/config.h index 071e50e..43181f4 100644 --- a/include/config.h +++ b/include/config.h @@ -20,6 +20,24 @@ #define RX 3 #define TX 1 +// Pins for MCP23017 +#define GPA0 0 +#define GPA1 1 +#define GPA2 2 +#define GPA3 3 +#define GPA4 4 +#define GPA5 5 +#define GPA6 6 +#define GPA7 7 +#define GPB0 8 +#define GPB1 9 +#define GPB2 10 +#define GPB3 11 +#define GPB4 12 +#define GPB5 13 +#define GPB6 14 +#define GPB7 15 + #define SHOW_DEBUG //#define SHOW_TRACE #define FTP_DEBUG @@ -30,21 +48,44 @@ #define VS1053_SLEEP_DELAY 5000 #define MQTT_REPORT_INTERVAL 10000 +#define PIN_SD_CS(x) (_mcp->digitalWrite(GPB3, x)) +#define PIN_SD_CS_SETUP() (_mcp->pinMode(GPB3, OUTPUT)) -#define PIN_SD_CS D4 -#define PIN_VS1053_XCS D8 -#define PIN_VS1053_XRESET 16 -#define PIN_MCP D3 -#define PIN_VS1053_XDCS D1 -#define PIN_VS1053_DREQ D2 -#define PIN_RC522_CS D0 -#define SPEAKER_L 15 -#define SPEAKER_R 14 +#define PIN_VS1053_XCS(x) (digitalWrite(D8, x)) +#define PIN_VS1053_XCS_SETUP() (pinMode(D8, OUTPUT)) -#define PIN_BTN_VOL_UP D4 -#define PIN_BTN_VOL_DOWN D5 -#define PIN_BTN_TRACK_NEXT D6 -#define PIN_BTN_TRACK_PREV D7 +#define PIN_VS1053_XRESET(x) (_mcp->digitalWrite(GPB7, x)) +#define PIN_VS1053_XRESET_SETUP() (_mcp->pinMode(GPB7, OUTPUT)) + +#define PIN_VS1053_XDCS(x) (digitalWrite(D3, x)) +#define PIN_VS1053_XDCS_SETUP() (pinMode(D3, OUTPUT)) + +#define PIN_VS1053_DREQ() (_mcp->digitalRead(GPB2)) +#define PIN_VS1053_DREQ_SETUP() (_mcp->pinMode(GPB2, INPUT)) + +#define PIN_RC522_CS(x) (digitalWrite(D0, x)) +#define PIN_RC522_CS_SETUP() (pinMode(D0, OUTPUT)) + +#define PIN_SPEAKER_L(x) (_mcp->digitalWrite(GPB5, x)) +#define PIN_SPEAKER_L_SETUP() (_mcp->pinMode(GPB5, OUTPUT)) + +#define PIN_SPEAKER_R(x) (_mcp->digitalWrite(GPB6, x)) +#define PIN_SPEAKER_R_SETUP() (_mcp->pinMode(GPB6, OUTPUT)) + +#define BTN_PREV() ( ! _mcp->digitalRead(GPA0)) +#define BTN_PREV_SETUP() {_mcp->pinMode(GPA0, INPUT); _mcp->pullUp(GPA0, HIGH);} + +#define BTN_VOL_UP() ( ! _mcp->digitalRead(GPA1)) +#define BTN_VOL_UP_SETUP() {_mcp->pinMode(GPA1, INPUT); _mcp->pullUp(GPA1, HIGH);} + +#define BTN_VOL_DOWN() ( ! _mcp->digitalRead(GPA2)) +#define BTN_VOL_DOWN_SETUP() {_mcp->pinMode(GPA2, INPUT); _mcp->pullUp(GPA2, HIGH);} + +#define BTN_NEXT() ( ! _mcp->digitalRead(GPA3)) +#define BTN_NEXT_SETUP() {_mcp->pinMode(GPA3, INPUT); _mcp->pullUp(GPA3, HIGH);} + + +#define MCP_I2C_ADDR 7 #define NUM_BUTTONS 4 @@ -54,6 +95,8 @@ #define VOLUME_MAX 255 #define VOLUME_STEP 0x08 +#define MCP_SPI_SETTING_DELAY 1 + #define RFID_SCAN_INTERVAL 100 diff --git a/include/controller.h b/include/controller.h index 1540729..3df0266 100644 --- a/include/controller.h +++ b/include/controller.h @@ -5,17 +5,19 @@ #include "player.h" #include "mqtt_client.h" #include -#include +#include class Controller { private: MFRC522* _rfid; - MCP* _mcp; + Adafruit_MCP23017* _mcp; + SPIMaster* _spi; MQTTClient* _mqtt_client; bool _rfid_enabled = true; void _check_rfid(); void _check_serial(); void _check_buttons(); + bool _debounce_button(uint8_t index); uint32_t _get_rfid_card_uid(); uint32_t _last_rfid_card_uid = 0; uint8_t _no_rfid_card_count = 0; @@ -30,7 +32,7 @@ private: unsigned long _last_mqtt_report_at = 0; void _send_mqtt_report(); public: - Controller(Player* p, MCP* m); + Controller(Player* p, Adafruit_MCP23017* m, SPIMaster* s); void set_mqtt_client(MQTTClient* m); String get_status_json(); void loop(); diff --git a/include/http_server.h b/include/http_server.h index 18945e3..779a3aa 100644 --- a/include/http_server.h +++ b/include/http_server.h @@ -1,6 +1,5 @@ #pragma once #include -#include "spi_master.h" #include "player.h" #include "controller.h" #include diff --git a/include/player.h b/include/player.h index 98d311b..c4fefd0 100644 --- a/include/player.h +++ b/include/player.h @@ -4,7 +4,8 @@ #include #include #include -#include +#include +#include "spi_master.h" #define SCI_MODE 0x00 #define SCI_STATUS 0x01 @@ -23,11 +24,6 @@ #define SM_CANCEL 0x0008 #define SS_DO_NOT_JUMP 0x8000 -#define XRESET PIN_VS1053_XRESET -#define DREQ PIN_VS1053_DREQ -#define XCS PIN_VS1053_XCS -#define XDCS PIN_VS1053_XDCS - class Player { private: enum state { uninitialized, idle, playing, stopping, @@ -81,10 +77,11 @@ private: uint8_t _volume; uint16_t _stop_delay; uint32_t _skip_to; - MCP* _mcp; + Adafruit_MCP23017* _mcp; + SPIMaster* _spi; unsigned long _stopped_at; public: - Player(MCP* m); + Player(Adafruit_MCP23017* m, SPIMaster* s); void vol_up(); void vol_down(); void track_next(); diff --git a/include/spi_master.h b/include/spi_master.h index b31ade4..73c6b46 100644 --- a/include/spi_master.h +++ b/include/spi_master.h @@ -5,31 +5,42 @@ #include "config.h" class SPIMaster { +private: + Adafruit_MCP23017* _mcp; public: - static void init() { - SPI.setHwCs(false); - pinMode(PIN_SD_CS, OUTPUT); - pinMode(PIN_VS1053_XCS, OUTPUT); - pinMode(PIN_VS1053_XDCS, OUTPUT); - pinMode(PIN_MCP, OUTPUT); - } - static void enable(uint8_t pin) { - digitalWrite(PIN_SD_CS, pin==PIN_SD_CS ? LOW : HIGH); - digitalWrite(PIN_VS1053_XCS, pin==PIN_VS1053_XCS ? LOW : HIGH); - digitalWrite(PIN_VS1053_XDCS, pin==PIN_VS1053_XDCS ? LOW : HIGH); - digitalWrite(PIN_MCP, pin==PIN_MCP ? LOW : HIGH); - + SPIMaster(Adafruit_MCP23017* m) { + _mcp = m; + PIN_SD_CS_SETUP(); + PIN_VS1053_XCS_SETUP(); + PIN_VS1053_XDCS_SETUP(); + PIN_RC522_CS_SETUP(); + disable(); } - static void printStatus() { - Serial.printf("CS state: SD:%d, VS1053_XCS:%d, VS1053_XDCS:%d, MCP:%d\n", - digitalRead(PIN_SD_CS), - digitalRead(PIN_VS1053_XCS), - digitalRead(PIN_VS1053_XDCS), - digitalRead(PIN_MCP)); + void select_sd(bool enabled=true) { + PIN_SD_CS(enabled ? LOW : HIGH); + delayMicroseconds(MCP_SPI_SETTING_DELAY); } - static void disable() { - enable(142); + void select_vs1053_xcs(bool enabled=true) { + PIN_VS1053_XCS(enabled ? LOW : HIGH); + delayMicroseconds(MCP_SPI_SETTING_DELAY); + } + + void select_vs1053_xdcs(bool enabled=true) { + PIN_VS1053_XDCS(enabled ? LOW : HIGH); + delayMicroseconds(MCP_SPI_SETTING_DELAY); + } + + void select_rc522(bool enabled=true) { + PIN_RC522_CS(enabled ? LOW : HIGH); + delayMicroseconds(MCP_SPI_SETTING_DELAY); + } + + void disable() { + PIN_SD_CS(HIGH); + PIN_VS1053_XCS(HIGH); + PIN_VS1053_XDCS(HIGH); + PIN_RC522_CS(HIGH); } }; diff --git a/include/tools.h b/include/tools.h new file mode 100644 index 0000000..745ee89 --- /dev/null +++ b/include/tools.h @@ -0,0 +1,8 @@ +#include +#include "config.h" + +void print_mcp_status(Adafruit_MCP23017* mcp) { + DEBUG(" AAAAAAAA BBBBBBBB\n"); + DEBUG(" 76543210 76543210\n"); + DEBUG("State of MCP pins: %08s %08s\n", String(mcp->readGPIO(0), 2).c_str(), String(mcp->readGPIO(1), 2).c_str()); +} \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index ab3a238..c36e1fe 100644 --- a/platformio.ini +++ b/platformio.ini @@ -14,6 +14,7 @@ board = esp12e framework = arduino upload_speed = 512000 build_flags=!./build_version.sh -lib_deps = 63 - https://github.com/n0mjs710/MCP23S17.git +lib_deps = Adafruit MCP23017 Arduino Library upload_port = /dev/cu.wchusbserial1420 +monitor_speed = 74480 +monitor_port = /dev/cu.wchusbserial1420 \ No newline at end of file diff --git a/src/controller.cpp b/src/controller.cpp index eb96839..9d78dee 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -1,24 +1,25 @@ #include "controller.h" #include "spi_master.h" +#include "config.h" -Controller::Controller(Player* p, MCP* m) { +Controller::Controller(Player* p, Adafruit_MCP23017* m, SPIMaster* s) { _player = p; _mcp = m; - _rfid = new MFRC522(PIN_RC522_CS, MFRC522::UNUSED_PIN); + _spi = s; + _rfid = new MFRC522(D0, MFRC522::UNUSED_PIN); - SPIMaster::enable(PIN_MCP); - _mcp->pinMode(1, INPUT); _mcp->pullupMode(1, HIGH); - _mcp->pinMode(2, INPUT); _mcp->pullupMode(2, HIGH); - _mcp->pinMode(3, INPUT); _mcp->pullupMode(3, HIGH); - _mcp->pinMode(4, INPUT); _mcp->pullupMode(4, HIGH); + BTN_NEXT_SETUP(); + BTN_PREV_SETUP(); + BTN_VOL_UP_SETUP(); + BTN_VOL_DOWN_SETUP(); - SPIMaster::enable(PIN_RC522_CS); - DEBUG("Initializing RC522..."); + _spi->select_rc522(); + DEBUG("Initializing RC522...\n"); _rfid->PCD_Init(); #ifdef SHOW_DEBUG _rfid->PCD_DumpVersionToSerial(); #endif - SPIMaster::disable(); + _spi->select_rc522(false); INFO("RC522 initialized.\n"); for (uint8_t i=0; iselect_rc522(); if (!_rfid->PICC_ReadCardSerial()) { if (!_rfid->PICC_IsNewCardPresent()) { return 0; @@ -53,8 +54,8 @@ uint32_t Controller::_get_rfid_card_uid() { return 0; } } + _spi->select_rc522(false); uint32_t uid = _rfid->uid.uidByte[0]<<24 | _rfid->uid.uidByte[1]<<16 | _rfid->uid.uidByte[2]<<8 | _rfid->uid.uidByte[3]; - SPIMaster::disable(); return uid; } @@ -146,46 +147,26 @@ void Controller::_execute_command_help() { } void Controller::_check_buttons() { - SPIMaster::enable(PIN_MCP); - SPI.beginTransaction(SPISettings(250000, MSBFIRST, SPI_MODE0)); - /*if (millis()%100==0) { - Serial.printf("Buttons: %d %d %d %d\n", _mcp->digitalRead(1), _mcp->digitalRead(2), _mcp->digitalRead(3), _mcp->digitalRead(4)); - }*/ - if (_check_button(0)) { + if (BTN_PREV() && _debounce_button(0)) { _player->track_prev(); - } else if (_check_button(1)) { + } else if (BTN_VOL_UP() && _debounce_button(1)) { _player->vol_up(); - } else if (_check_button(2)) { + } else if (BTN_VOL_DOWN() && _debounce_button(2)) { _player->vol_down(); - } else if (_check_button(3)) { + } else if (BTN_NEXT() && _debounce_button(3)) { _player->track_next(); } - SPI.endTransaction(); - SPIMaster::disable(); } -bool Controller::_check_button(uint8_t index) { - if (index >= NUM_BUTTONS) return false; +bool Controller::_debounce_button(uint8_t index) { bool ret = false; - /*uint8_t sum = 0; - while (1) { - sum = 0; - for (int i=0; i<8; i++) { - sum += _mcp->digitalRead(index + 1) == HIGH ? 1 : 0; - } - if (sum==0 || sum==8) break; - } - if (sum == 0) {*/ - if (_mcp->digitalRead(index + 1) == LOW) { - if (_button_last_pressed_at[index] + DEBOUNCE_MILLIS < millis()) { - DEBUG("Button %d pressed.\n", index); - ret = true; - } - _button_last_pressed_at[index] = millis(); + if (_button_last_pressed_at[index] + DEBOUNCE_MILLIS < millis()) { + DEBUG("Button %d pressed.\n", index); + ret = true; } + _button_last_pressed_at[index] = millis(); return ret; } - String Controller::get_status_json() { String response = String("{"); response.concat("\"state\": \""); diff --git a/src/main.cpp b/src/main.cpp index 085d2e8..975a8bb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,8 @@ #include #include #include -#include +#include +#include #include "config.h" #include "controller.h" #include "player.h" @@ -12,7 +13,7 @@ Controller* controller; Player* player; -MCP* mcp; +Adafruit_MCP23017* mcp; HTTPServer* http_server; FtpServer* ftp_server; MQTTClient* mqtt_client; @@ -21,6 +22,8 @@ unsigned long last_mqtt_report = 0; void setup() { delay(500); Serial.begin(74880); + /*Serial.println("Starting..."); + Serial.println("Started."); INFO("Starting.\n"); #ifdef VERSION INFO("ESMP3 version %s\n", VERSION); @@ -28,7 +31,47 @@ void setup() { INFO("ESMP3, version unknown\n"); #endif INFO("Initializing...\n"); - + + DEBUG("Setting up MCP...\n");*/ + Wire.begin(); + Wire.setClock(1700000); + + uint8_t addr = MCP23017_ADDRESS + MCP_I2C_ADDR; + while(true) { + Wire.beginTransmission(addr); + byte status = Wire.endTransmission(); + if (status==0) { + DEBUG("I2C device found."); + break; + } + DEBUG("No I2C device found."); + delay(100); + } + + mcp = new Adafruit_MCP23017(); + mcp->begin(MCP_I2C_ADDR); + INFO("MCP initialized.\n"); + + DEBUG("Setting up SPI...\n"); + SPI.begin(); + SPI.setHwCs(false); + SPIMaster* spi = new SPIMaster(mcp); + INFO("SPI initialized.\n"); + + DEBUG("Setting up SD card...\n"); + spi->select_sd(); + if (SD.begin(42)) { + INFO("SD card initialized.\n"); + } else { + ERROR("Could not initialize SD card.\n"); + } + spi->select_sd(false); + + DEBUG("Initializing Player and Controller...\n"); + player = new Player(mcp, spi); + controller = new Controller(player, mcp, spi); + INFO("Player and controller initialized.\n"); + DEBUG("Connecting to wifi \"%s\"...\n", WIFI_SSID); WiFi.mode(WIFI_AP_STA); WiFi.begin(WIFI_SSID, WIFI_PASS); @@ -42,30 +85,7 @@ void setup() { mqtt_client = new MQTTClient(); MDNS.begin("esmp3"); - - - DEBUG("Setting up SPI...\n"); - SPI.begin(); - SPIMaster::init(); - INFO("SPI initialized.\n"); - - DEBUG("Setting up MCP...\n"); - SPIMaster::enable(PIN_MCP); - mcp = new MCP(0, PIN_MCP); - INFO("MCP initialized."); - - DEBUG("Setting up SD card...\n"); - SPIMaster::enable(PIN_SD_CS); - if (SD.begin(PIN_SD_CS)) { - INFO("SD card initialized.\n"); - } else { - ERROR("Could not initialize SD card.\n"); - } - - DEBUG("Initializing Player and Controller...\n"); - player = new Player(mcp); - controller = new Controller(player, mcp, mqtt_client); - INFO("Player and controller initialized.\n"); + controller->set_mqtt_client(mqtt_client); DEBUG("Setting up WiFi and web server...\n"); http_server = new HTTPServer(player, controller); diff --git a/src/player.cpp b/src/player.cpp index 827466f..9f8840d 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -2,50 +2,50 @@ #include "player.h" #include "spi_master.h" +#include "tools.h" //Player::_spi_settings -Player::Player(MCP* m) { - SPIMaster::enable(PIN_MCP); +Player::Player(Adafruit_MCP23017* m, SPIMaster* s) { _mcp = m; - _mcp->pinMode(XRESET, OUTPUT); - _mcp->digitalWrite(XRESET, HIGH); - _mcp->pinMode(SPEAKER_L, OUTPUT); - _mcp->pinMode(SPEAKER_R, OUTPUT); + _spi = s; + PIN_VS1053_XRESET_SETUP(); + PIN_VS1053_XRESET(HIGH); + PIN_SPEAKER_L_SETUP(); + PIN_SPEAKER_R_SETUP(); _speaker_off(); - SPIMaster::disable(); - pinMode(DREQ, INPUT); + _spi->disable(); + PIN_VS1053_DREQ_SETUP(); _init(); } void Player::_reset() { - SPIMaster::enable(PIN_MCP); - _mcp->digitalWrite(XRESET, LOW); + PIN_VS1053_XRESET(LOW); delay(100); - _mcp->digitalWrite(XRESET, HIGH); - SPIMaster::disable(); + PIN_VS1053_XRESET(HIGH); delay(100); _state = uninitialized; _spi_settings = &_spi_settings_slow; // After reset, communication has to be slow } void Player::_init() { - SPIMaster::disable(); DEBUG("Resetting VS1053...\n"); _reset(); uint16_t result = _read_control_register(SCI_MODE); DEBUG("SCI_MODE: 0x%04X\n", result); if (result != 0x4800) { - ERROR("SCI_MODE was 0x%04X, expected was 0x4800.\n", result); - return; + ERROR("SCI_MODE was 0x%04X, expected was 0x4800. Rebooting.\n", result); + delay(500); + ESP.restart(); } result = _read_control_register(SCI_STATUS); DEBUG("SCI_STATUS: 0x%04X\n", result); if (result != 0x0040 && result != 0x0048) { - ERROR("SCI_STATUS was 0x%04X, expected was 0x0040 or 0x0048.\n", result); - return; + ERROR("SCI_STATUS was 0x%04X, expected was 0x0040 or 0x0048. Rebooting.\n", result); + delay(500); + ESP.restart(); } result = _read_control_register(SCI_CLOCKF); DEBUG("SCI_CLOCKF: 0x%04X\n", result); @@ -61,8 +61,9 @@ void Player::_init() { result = _read_control_register(SCI_CLOCKF); DEBUG("SCI_CLOCKF: 0x%04X\n", result); if (result != 0x6000) { - ERROR("Error: SCI_CLOCKF was 0x%04X, expected was 0x6000.\n", result); - return; + ERROR("Error: SCI_CLOCKF was 0x%04X, expected was 0x6000. Rebooting.\n", result); + delay(500); + ESP.restart(); } set_volume(VOLUME_DEFAULT); @@ -70,29 +71,26 @@ void Player::_init() { INFO("VS1053 initialization completed.\n"); INFO("Checking system sounds...\n"); - SPIMaster::enable(PIN_SD_CS); + _spi->select_sd(); _check_system_sound("no_prev_song.mp3"); _check_system_sound("no_next_song.mp3"); _check_system_sound("volume_max.mp3"); _check_system_sound("volume_min.mp3"); + _spi->select_sd(false); _state = idle; } void Player::_speaker_off() { DEBUG("Speaker off\n"); - SPIMaster::enable(PIN_MCP); - _mcp->digitalWrite(SPEAKER_R, LOW); - _mcp->digitalWrite(SPEAKER_L, LOW); - SPIMaster::disable(); + PIN_SPEAKER_L(LOW); + PIN_SPEAKER_R(LOW); } void Player::_speaker_on() { DEBUG("Speaker on\n"); - SPIMaster::enable(PIN_MCP); - _mcp->digitalWrite(SPEAKER_R, HIGH); - _mcp->digitalWrite(SPEAKER_L, HIGH); - SPIMaster::disable(); + PIN_SPEAKER_L(HIGH); + PIN_SPEAKER_R(HIGH); } void Player::_sleep() { @@ -128,12 +126,12 @@ void Player::_check_system_sound(String filename) { } inline void Player::_wait() { - while(!digitalRead(DREQ)); + while(!PIN_VS1053_DREQ()); } uint16_t Player::_read_control_register(uint8_t address) { _wait(); - SPIMaster::enable(XCS); + _spi->select_vs1053_xcs(); SPI.beginTransaction(*_spi_settings); SPI.transfer(CMD_READ); SPI.transfer(address); @@ -142,7 +140,7 @@ uint16_t Player::_read_control_register(uint8_t address) { uint8_t b2 = SPI.transfer(0xFF); _wait(); SPI.endTransaction(); - SPIMaster::disable(); + _spi->select_vs1053_xcs(false); return (b1 << 8) | b2; } @@ -151,7 +149,7 @@ void Player::_write_control_register(uint8_t address, uint16_t value) { uint8_t b1 = value >> 8; uint8_t b2 = value & 0xFF; _wait(); - SPIMaster::enable(XCS); + _spi->select_vs1053_xcs(); SPI.beginTransaction(*_spi_settings); SPI.transfer(CMD_WRITE); SPI.transfer(address); @@ -159,17 +157,17 @@ void Player::_write_control_register(uint8_t address, uint16_t value) { SPI.transfer(b2); _wait(); SPI.endTransaction(); - SPIMaster::disable(); + _spi->select_vs1053_xcs(false); } void Player::_write_data(uint8_t* buffer) { - SPIMaster::enable(XDCS); + _spi->select_vs1053_xdcs(); SPI.beginTransaction(*_spi_settings); for (uint i=0; iselect_vs1053_xdcs(false); } uint16_t Player::_read_wram(uint16_t address) { @@ -264,7 +262,7 @@ bool Player::is_playing() { } std::list Player::ls(String path, bool withFiles, bool withDirs, bool withHidden) { - SPIMaster::enable(PIN_SD_CS); + _spi->select_sd(); std::list result; if (!SD.exists(path)) return result; File dir = SD.open(path); @@ -277,11 +275,13 @@ std::list Player::ls(String path, bool withFiles, bool withDirs, bool wi if (entry.isDirectory()) filename.concat("/"); result.push_back(filename); } + _spi->select_sd(false); result.sort(); return result; } String Player::_find_album_dir(String id) { + _spi->select_sd(); if (id.endsWith("/")) id = id.substring(0, id.length() - 1); String id_with_divider = id + " - "; File root = SD.open("/"); @@ -295,10 +295,12 @@ String Player::_find_album_dir(String id) { entry.close(); } root.close(); + _spi->select_sd(false); return result; } std::list Player::_files_in_dir(String path) { + _spi->select_sd(); DEBUG("Examining folder %s...\n", path.c_str()); if (!path.startsWith("/")) path = String("/") + path; if (!path.endsWith("/")) path.concat("/"); @@ -323,6 +325,7 @@ std::list Player::_files_in_dir(String path) { entry.close(); } dir.close(); + _spi->select_sd(false); result.sort(); return result; @@ -393,8 +396,13 @@ void Player::play_system_sound(String filename) { void Player::_play_file(String file, uint32_t file_offset) { INFO("play_file('%s', %d)\n", file.c_str(), file_offset); + _spi->select_sd(); _file = SD.open(file); - if (!_file) return; + _spi->select_sd(false); + if (!_file) { + DEBUG("Could not open file %s", file.c_str()); + return; + } DEBUG("Resetting SCI_DECODE_TIME...\n"); _write_control_register(SCI_DECODE_TIME, 0); @@ -438,13 +446,14 @@ uint32_t Player::_id3_tag_offset(File f) { } void Player::_flush(uint count, int8_t byte) { - SPIMaster::enable(XDCS); + _spi->select_vs1053_xdcs(); SPI.beginTransaction(*_spi_settings); for(uint i=0; iselect_vs1053_xdcs(false); } void Player::_finish_playing() { @@ -498,10 +507,11 @@ void Player::_finish_stopping(bool turn_speaker_off) { } void Player::_refill() { - SPIMaster::enable(PIN_SD_CS); + _spi->select_sd(); _refills++; if (_refills % 1000 == 0) DEBUG("."); uint8_t result = _file.read(_buffer, sizeof(_buffer)); + _spi->select_sd(false); if (result == 0) { // File is over. DEBUG("EOF reached.\n"); @@ -550,7 +560,7 @@ bool Player::_refill_needed() { } bool Player::loop() { - if (digitalRead(DREQ) && _refill_needed()) { + if (PIN_VS1053_DREQ() && _refill_needed()) { _refill(); return true; }