Changed from MCP23S17 to MCP23017. Lots of changes.

Doesn't really work because of timing stuff.
This commit is contained in:
Fabian Schlenz 2019-11-10 14:45:33 +01:00
parent cccdc9cedb
commit c313f6eb72
13 changed files with 367 additions and 143 deletions

131
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -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
}

7
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
]
}

32
.vscode/launch.json vendored Normal file
View File

@ -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"
}
]
}

25
README.md Normal file
View File

@ -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!

View File

@ -5,17 +5,19 @@
#include "player.h" #include "player.h"
#include "mqtt_client.h" #include "mqtt_client.h"
#include <MFRC522.h> #include <MFRC522.h>
#include <MCP23S17/MCP23S17.h> #include <Adafruit_MCP23017.h>
class Controller { class Controller {
private: private:
MFRC522* _rfid; MFRC522* _rfid;
MCP* _mcp; Adafruit_MCP23017* _mcp;
SPIMaster* _spi;
MQTTClient* _mqtt_client; MQTTClient* _mqtt_client;
bool _rfid_enabled = true; bool _rfid_enabled = true;
void _check_rfid(); void _check_rfid();
void _check_serial(); void _check_serial();
void _check_buttons(); void _check_buttons();
bool _debounce_button(uint8_t index);
uint32_t _get_rfid_card_uid(); uint32_t _get_rfid_card_uid();
uint32_t _last_rfid_card_uid = 0; uint32_t _last_rfid_card_uid = 0;
uint8_t _no_rfid_card_count = 0; uint8_t _no_rfid_card_count = 0;
@ -30,7 +32,7 @@ private:
unsigned long _last_mqtt_report_at = 0; unsigned long _last_mqtt_report_at = 0;
void _send_mqtt_report(); void _send_mqtt_report();
public: public:
Controller(Player* p, MCP* m); Controller(Player* p, Adafruit_MCP23017* m, SPIMaster* s);
void set_mqtt_client(MQTTClient* m); void set_mqtt_client(MQTTClient* m);
String get_status_json(); String get_status_json();
void loop(); void loop();

View File

@ -1,6 +1,5 @@
#pragma once #pragma once
#include <ESP8266WebServer.h> #include <ESP8266WebServer.h>
#include "spi_master.h"
#include "player.h" #include "player.h"
#include "controller.h" #include "controller.h"
#include <SD.h> #include <SD.h>

View File

@ -4,7 +4,8 @@
#include <SD.h> #include <SD.h>
#include <list> #include <list>
#include <map> #include <map>
#include <MCP23S17/MCP23S17.h> #include <Adafruit_MCP23017.h>
#include "spi_master.h"
#define SCI_MODE 0x00 #define SCI_MODE 0x00
#define SCI_STATUS 0x01 #define SCI_STATUS 0x01
@ -23,11 +24,6 @@
#define SM_CANCEL 0x0008 #define SM_CANCEL 0x0008
#define SS_DO_NOT_JUMP 0x8000 #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 { class Player {
private: private:
enum state { uninitialized, idle, playing, stopping, enum state { uninitialized, idle, playing, stopping,
@ -81,10 +77,11 @@ private:
uint8_t _volume; uint8_t _volume;
uint16_t _stop_delay; uint16_t _stop_delay;
uint32_t _skip_to; uint32_t _skip_to;
MCP* _mcp; Adafruit_MCP23017* _mcp;
SPIMaster* _spi;
unsigned long _stopped_at; unsigned long _stopped_at;
public: public:
Player(MCP* m); Player(Adafruit_MCP23017* m, SPIMaster* s);
void vol_up(); void vol_up();
void vol_down(); void vol_down();
void track_next(); void track_next();

View File

@ -5,31 +5,42 @@
#include "config.h" #include "config.h"
class SPIMaster { class SPIMaster {
private:
Adafruit_MCP23017* _mcp;
public: public:
static void init() { SPIMaster(Adafruit_MCP23017* m) {
SPI.setHwCs(false); _mcp = m;
pinMode(PIN_SD_CS, OUTPUT); PIN_SD_CS_SETUP();
pinMode(PIN_VS1053_XCS, OUTPUT); PIN_VS1053_XCS_SETUP();
pinMode(PIN_VS1053_XDCS, OUTPUT); PIN_VS1053_XDCS_SETUP();
pinMode(PIN_MCP, OUTPUT); PIN_RC522_CS_SETUP();
} disable();
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);
} }
static void printStatus() { void select_sd(bool enabled=true) {
Serial.printf("CS state: SD:%d, VS1053_XCS:%d, VS1053_XDCS:%d, MCP:%d\n", PIN_SD_CS(enabled ? LOW : HIGH);
digitalRead(PIN_SD_CS), delayMicroseconds(MCP_SPI_SETTING_DELAY);
digitalRead(PIN_VS1053_XCS),
digitalRead(PIN_VS1053_XDCS),
digitalRead(PIN_MCP));
} }
static void disable() { void select_vs1053_xcs(bool enabled=true) {
enable(142); 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);
} }
}; };

8
include/tools.h Normal file
View File

@ -0,0 +1,8 @@
#include <Adafruit_MCP23017.h>
#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());
}

View File

@ -14,6 +14,7 @@ board = esp12e
framework = arduino framework = arduino
upload_speed = 512000 upload_speed = 512000
build_flags=!./build_version.sh build_flags=!./build_version.sh
lib_deps = 63 lib_deps = Adafruit MCP23017 Arduino Library
https://github.com/n0mjs710/MCP23S17.git
upload_port = /dev/cu.wchusbserial1420 upload_port = /dev/cu.wchusbserial1420
monitor_speed = 74480
monitor_port = /dev/cu.wchusbserial1420

View File

@ -1,24 +1,25 @@
#include "controller.h" #include "controller.h"
#include "spi_master.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; _player = p;
_mcp = m; _mcp = m;
_rfid = new MFRC522(PIN_RC522_CS, MFRC522::UNUSED_PIN); _spi = s;
_rfid = new MFRC522(D0, MFRC522::UNUSED_PIN);
SPIMaster::enable(PIN_MCP); BTN_NEXT_SETUP();
_mcp->pinMode(1, INPUT); _mcp->pullupMode(1, HIGH); BTN_PREV_SETUP();
_mcp->pinMode(2, INPUT); _mcp->pullupMode(2, HIGH); BTN_VOL_UP_SETUP();
_mcp->pinMode(3, INPUT); _mcp->pullupMode(3, HIGH); BTN_VOL_DOWN_SETUP();
_mcp->pinMode(4, INPUT); _mcp->pullupMode(4, HIGH);
SPIMaster::enable(PIN_RC522_CS); _spi->select_rc522();
DEBUG("Initializing RC522..."); DEBUG("Initializing RC522...\n");
_rfid->PCD_Init(); _rfid->PCD_Init();
#ifdef SHOW_DEBUG #ifdef SHOW_DEBUG
_rfid->PCD_DumpVersionToSerial(); _rfid->PCD_DumpVersionToSerial();
#endif #endif
SPIMaster::disable(); _spi->select_rc522(false);
INFO("RC522 initialized.\n"); INFO("RC522 initialized.\n");
for (uint8_t i=0; i<NUM_BUTTONS; i++) _button_last_pressed_at[i]=0; for (uint8_t i=0; i<NUM_BUTTONS; i++) _button_last_pressed_at[i]=0;
@ -44,7 +45,7 @@ void Controller::loop() {
} }
uint32_t Controller::_get_rfid_card_uid() { uint32_t Controller::_get_rfid_card_uid() {
SPIMaster::enable(PIN_RC522_CS); _spi->select_rc522();
if (!_rfid->PICC_ReadCardSerial()) { if (!_rfid->PICC_ReadCardSerial()) {
if (!_rfid->PICC_IsNewCardPresent()) { if (!_rfid->PICC_IsNewCardPresent()) {
return 0; return 0;
@ -53,8 +54,8 @@ uint32_t Controller::_get_rfid_card_uid() {
return 0; 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]; 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; return uid;
} }
@ -146,46 +147,26 @@ void Controller::_execute_command_help() {
} }
void Controller::_check_buttons() { void Controller::_check_buttons() {
SPIMaster::enable(PIN_MCP); if (BTN_PREV() && _debounce_button(0)) {
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)) {
_player->track_prev(); _player->track_prev();
} else if (_check_button(1)) { } else if (BTN_VOL_UP() && _debounce_button(1)) {
_player->vol_up(); _player->vol_up();
} else if (_check_button(2)) { } else if (BTN_VOL_DOWN() && _debounce_button(2)) {
_player->vol_down(); _player->vol_down();
} else if (_check_button(3)) { } else if (BTN_NEXT() && _debounce_button(3)) {
_player->track_next(); _player->track_next();
} }
SPI.endTransaction();
SPIMaster::disable();
} }
bool Controller::_check_button(uint8_t index) { bool Controller::_debounce_button(uint8_t index) {
if (index >= NUM_BUTTONS) return false;
bool ret = false; bool ret = false;
/*uint8_t sum = 0; if (_button_last_pressed_at[index] + DEBOUNCE_MILLIS < millis()) {
while (1) { DEBUG("Button %d pressed.\n", index);
sum = 0; ret = true;
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();
} }
_button_last_pressed_at[index] = millis();
return ret; return ret;
} }
String Controller::get_status_json() { String Controller::get_status_json() {
String response = String("{"); String response = String("{");
response.concat("\"state\": \""); response.concat("\"state\": \"");

View File

@ -1,7 +1,8 @@
#include <Arduino.h> #include <Arduino.h>
#include <SPI.h> #include <SPI.h>
#include <SD.h> #include <SD.h>
#include <MCP23S17/MCP23S17.h> #include <Wire.h>
#include <Adafruit_MCP23017.h>
#include "config.h" #include "config.h"
#include "controller.h" #include "controller.h"
#include "player.h" #include "player.h"
@ -12,7 +13,7 @@
Controller* controller; Controller* controller;
Player* player; Player* player;
MCP* mcp; Adafruit_MCP23017* mcp;
HTTPServer* http_server; HTTPServer* http_server;
FtpServer* ftp_server; FtpServer* ftp_server;
MQTTClient* mqtt_client; MQTTClient* mqtt_client;
@ -21,6 +22,8 @@ unsigned long last_mqtt_report = 0;
void setup() { void setup() {
delay(500); delay(500);
Serial.begin(74880); Serial.begin(74880);
/*Serial.println("Starting...");
Serial.println("Started.");
INFO("Starting.\n"); INFO("Starting.\n");
#ifdef VERSION #ifdef VERSION
INFO("ESMP3 version %s\n", VERSION); INFO("ESMP3 version %s\n", VERSION);
@ -28,7 +31,47 @@ void setup() {
INFO("ESMP3, version unknown\n"); INFO("ESMP3, version unknown\n");
#endif #endif
INFO("Initializing...\n"); 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); DEBUG("Connecting to wifi \"%s\"...\n", WIFI_SSID);
WiFi.mode(WIFI_AP_STA); WiFi.mode(WIFI_AP_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS); WiFi.begin(WIFI_SSID, WIFI_PASS);
@ -42,30 +85,7 @@ void setup() {
mqtt_client = new MQTTClient(); mqtt_client = new MQTTClient();
MDNS.begin("esmp3"); MDNS.begin("esmp3");
controller->set_mqtt_client(mqtt_client);
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");
DEBUG("Setting up WiFi and web server...\n"); DEBUG("Setting up WiFi and web server...\n");
http_server = new HTTPServer(player, controller); http_server = new HTTPServer(player, controller);

View File

@ -2,50 +2,50 @@
#include "player.h" #include "player.h"
#include "spi_master.h" #include "spi_master.h"
#include "tools.h"
//Player::_spi_settings //Player::_spi_settings
Player::Player(MCP* m) { Player::Player(Adafruit_MCP23017* m, SPIMaster* s) {
SPIMaster::enable(PIN_MCP);
_mcp = m; _mcp = m;
_mcp->pinMode(XRESET, OUTPUT); _spi = s;
_mcp->digitalWrite(XRESET, HIGH); PIN_VS1053_XRESET_SETUP();
_mcp->pinMode(SPEAKER_L, OUTPUT); PIN_VS1053_XRESET(HIGH);
_mcp->pinMode(SPEAKER_R, OUTPUT); PIN_SPEAKER_L_SETUP();
PIN_SPEAKER_R_SETUP();
_speaker_off(); _speaker_off();
SPIMaster::disable(); _spi->disable();
pinMode(DREQ, INPUT); PIN_VS1053_DREQ_SETUP();
_init(); _init();
} }
void Player::_reset() { void Player::_reset() {
SPIMaster::enable(PIN_MCP); PIN_VS1053_XRESET(LOW);
_mcp->digitalWrite(XRESET, LOW);
delay(100); delay(100);
_mcp->digitalWrite(XRESET, HIGH); PIN_VS1053_XRESET(HIGH);
SPIMaster::disable();
delay(100); delay(100);
_state = uninitialized; _state = uninitialized;
_spi_settings = &_spi_settings_slow; // After reset, communication has to be slow _spi_settings = &_spi_settings_slow; // After reset, communication has to be slow
} }
void Player::_init() { void Player::_init() {
SPIMaster::disable();
DEBUG("Resetting VS1053...\n"); DEBUG("Resetting VS1053...\n");
_reset(); _reset();
uint16_t result = _read_control_register(SCI_MODE); uint16_t result = _read_control_register(SCI_MODE);
DEBUG("SCI_MODE: 0x%04X\n", result); DEBUG("SCI_MODE: 0x%04X\n", result);
if (result != 0x4800) { if (result != 0x4800) {
ERROR("SCI_MODE was 0x%04X, expected was 0x4800.\n", result); ERROR("SCI_MODE was 0x%04X, expected was 0x4800. Rebooting.\n", result);
return; delay(500);
ESP.restart();
} }
result = _read_control_register(SCI_STATUS); result = _read_control_register(SCI_STATUS);
DEBUG("SCI_STATUS: 0x%04X\n", result); DEBUG("SCI_STATUS: 0x%04X\n", result);
if (result != 0x0040 && result != 0x0048) { if (result != 0x0040 && result != 0x0048) {
ERROR("SCI_STATUS was 0x%04X, expected was 0x0040 or 0x0048.\n", result); ERROR("SCI_STATUS was 0x%04X, expected was 0x0040 or 0x0048. Rebooting.\n", result);
return; delay(500);
ESP.restart();
} }
result = _read_control_register(SCI_CLOCKF); result = _read_control_register(SCI_CLOCKF);
DEBUG("SCI_CLOCKF: 0x%04X\n", result); DEBUG("SCI_CLOCKF: 0x%04X\n", result);
@ -61,8 +61,9 @@ void Player::_init() {
result = _read_control_register(SCI_CLOCKF); result = _read_control_register(SCI_CLOCKF);
DEBUG("SCI_CLOCKF: 0x%04X\n", result); DEBUG("SCI_CLOCKF: 0x%04X\n", result);
if (result != 0x6000) { if (result != 0x6000) {
ERROR("Error: SCI_CLOCKF was 0x%04X, expected was 0x6000.\n", result); ERROR("Error: SCI_CLOCKF was 0x%04X, expected was 0x6000. Rebooting.\n", result);
return; delay(500);
ESP.restart();
} }
set_volume(VOLUME_DEFAULT); set_volume(VOLUME_DEFAULT);
@ -70,29 +71,26 @@ void Player::_init() {
INFO("VS1053 initialization completed.\n"); INFO("VS1053 initialization completed.\n");
INFO("Checking system sounds...\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_prev_song.mp3");
_check_system_sound("no_next_song.mp3"); _check_system_sound("no_next_song.mp3");
_check_system_sound("volume_max.mp3"); _check_system_sound("volume_max.mp3");
_check_system_sound("volume_min.mp3"); _check_system_sound("volume_min.mp3");
_spi->select_sd(false);
_state = idle; _state = idle;
} }
void Player::_speaker_off() { void Player::_speaker_off() {
DEBUG("Speaker off\n"); DEBUG("Speaker off\n");
SPIMaster::enable(PIN_MCP); PIN_SPEAKER_L(LOW);
_mcp->digitalWrite(SPEAKER_R, LOW); PIN_SPEAKER_R(LOW);
_mcp->digitalWrite(SPEAKER_L, LOW);
SPIMaster::disable();
} }
void Player::_speaker_on() { void Player::_speaker_on() {
DEBUG("Speaker on\n"); DEBUG("Speaker on\n");
SPIMaster::enable(PIN_MCP); PIN_SPEAKER_L(HIGH);
_mcp->digitalWrite(SPEAKER_R, HIGH); PIN_SPEAKER_R(HIGH);
_mcp->digitalWrite(SPEAKER_L, HIGH);
SPIMaster::disable();
} }
void Player::_sleep() { void Player::_sleep() {
@ -128,12 +126,12 @@ void Player::_check_system_sound(String filename) {
} }
inline void Player::_wait() { inline void Player::_wait() {
while(!digitalRead(DREQ)); while(!PIN_VS1053_DREQ());
} }
uint16_t Player::_read_control_register(uint8_t address) { uint16_t Player::_read_control_register(uint8_t address) {
_wait(); _wait();
SPIMaster::enable(XCS); _spi->select_vs1053_xcs();
SPI.beginTransaction(*_spi_settings); SPI.beginTransaction(*_spi_settings);
SPI.transfer(CMD_READ); SPI.transfer(CMD_READ);
SPI.transfer(address); SPI.transfer(address);
@ -142,7 +140,7 @@ uint16_t Player::_read_control_register(uint8_t address) {
uint8_t b2 = SPI.transfer(0xFF); uint8_t b2 = SPI.transfer(0xFF);
_wait(); _wait();
SPI.endTransaction(); SPI.endTransaction();
SPIMaster::disable(); _spi->select_vs1053_xcs(false);
return (b1 << 8) | b2; 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 b1 = value >> 8;
uint8_t b2 = value & 0xFF; uint8_t b2 = value & 0xFF;
_wait(); _wait();
SPIMaster::enable(XCS); _spi->select_vs1053_xcs();
SPI.beginTransaction(*_spi_settings); SPI.beginTransaction(*_spi_settings);
SPI.transfer(CMD_WRITE); SPI.transfer(CMD_WRITE);
SPI.transfer(address); SPI.transfer(address);
@ -159,17 +157,17 @@ void Player::_write_control_register(uint8_t address, uint16_t value) {
SPI.transfer(b2); SPI.transfer(b2);
_wait(); _wait();
SPI.endTransaction(); SPI.endTransaction();
SPIMaster::disable(); _spi->select_vs1053_xcs(false);
} }
void Player::_write_data(uint8_t* buffer) { void Player::_write_data(uint8_t* buffer) {
SPIMaster::enable(XDCS); _spi->select_vs1053_xdcs();
SPI.beginTransaction(*_spi_settings); SPI.beginTransaction(*_spi_settings);
for (uint i=0; i<sizeof(_buffer); i++) { for (uint i=0; i<sizeof(_buffer); i++) {
SPI.transfer(_buffer[i]); SPI.transfer(_buffer[i]);
} }
SPI.endTransaction(); SPI.endTransaction();
SPIMaster::disable(); _spi->select_vs1053_xdcs(false);
} }
uint16_t Player::_read_wram(uint16_t address) { uint16_t Player::_read_wram(uint16_t address) {
@ -264,7 +262,7 @@ bool Player::is_playing() {
} }
std::list<String> Player::ls(String path, bool withFiles, bool withDirs, bool withHidden) { std::list<String> Player::ls(String path, bool withFiles, bool withDirs, bool withHidden) {
SPIMaster::enable(PIN_SD_CS); _spi->select_sd();
std::list<String> result; std::list<String> result;
if (!SD.exists(path)) return result; if (!SD.exists(path)) return result;
File dir = SD.open(path); File dir = SD.open(path);
@ -277,11 +275,13 @@ std::list<String> Player::ls(String path, bool withFiles, bool withDirs, bool wi
if (entry.isDirectory()) filename.concat("/"); if (entry.isDirectory()) filename.concat("/");
result.push_back(filename); result.push_back(filename);
} }
_spi->select_sd(false);
result.sort(); result.sort();
return result; return result;
} }
String Player::_find_album_dir(String id) { String Player::_find_album_dir(String id) {
_spi->select_sd();
if (id.endsWith("/")) id = id.substring(0, id.length() - 1); if (id.endsWith("/")) id = id.substring(0, id.length() - 1);
String id_with_divider = id + " - "; String id_with_divider = id + " - ";
File root = SD.open("/"); File root = SD.open("/");
@ -295,10 +295,12 @@ String Player::_find_album_dir(String id) {
entry.close(); entry.close();
} }
root.close(); root.close();
_spi->select_sd(false);
return result; return result;
} }
std::list<String> Player::_files_in_dir(String path) { std::list<String> Player::_files_in_dir(String path) {
_spi->select_sd();
DEBUG("Examining folder %s...\n", path.c_str()); DEBUG("Examining folder %s...\n", path.c_str());
if (!path.startsWith("/")) path = String("/") + path; if (!path.startsWith("/")) path = String("/") + path;
if (!path.endsWith("/")) path.concat("/"); if (!path.endsWith("/")) path.concat("/");
@ -323,6 +325,7 @@ std::list<String> Player::_files_in_dir(String path) {
entry.close(); entry.close();
} }
dir.close(); dir.close();
_spi->select_sd(false);
result.sort(); result.sort();
return result; return result;
@ -393,8 +396,13 @@ void Player::play_system_sound(String filename) {
void Player::_play_file(String file, uint32_t file_offset) { void Player::_play_file(String file, uint32_t file_offset) {
INFO("play_file('%s', %d)\n", file.c_str(), file_offset); INFO("play_file('%s', %d)\n", file.c_str(), file_offset);
_spi->select_sd();
_file = SD.open(file); _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"); DEBUG("Resetting SCI_DECODE_TIME...\n");
_write_control_register(SCI_DECODE_TIME, 0); _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) { void Player::_flush(uint count, int8_t byte) {
SPIMaster::enable(XDCS); _spi->select_vs1053_xdcs();
SPI.beginTransaction(*_spi_settings); SPI.beginTransaction(*_spi_settings);
for(uint i=0; i<count; i++) { for(uint i=0; i<count; i++) {
_wait(); _wait();
SPI.transfer(byte); SPI.transfer(byte);
} }
SPI.endTransaction(); SPI.endTransaction();
_spi->select_vs1053_xdcs(false);
} }
void Player::_finish_playing() { void Player::_finish_playing() {
@ -498,10 +507,11 @@ void Player::_finish_stopping(bool turn_speaker_off) {
} }
void Player::_refill() { void Player::_refill() {
SPIMaster::enable(PIN_SD_CS); _spi->select_sd();
_refills++; _refills++;
if (_refills % 1000 == 0) DEBUG("."); if (_refills % 1000 == 0) DEBUG(".");
uint8_t result = _file.read(_buffer, sizeof(_buffer)); uint8_t result = _file.read(_buffer, sizeof(_buffer));
_spi->select_sd(false);
if (result == 0) { if (result == 0) {
// File is over. // File is over.
DEBUG("EOF reached.\n"); DEBUG("EOF reached.\n");
@ -550,7 +560,7 @@ bool Player::_refill_needed() {
} }
bool Player::loop() { bool Player::loop() {
if (digitalRead(DREQ) && _refill_needed()) { if (PIN_VS1053_DREQ() && _refill_needed()) {
_refill(); _refill();
return true; return true;
} }