Dump some existing projects based on Spejsiot

master
informatic 2018-06-28 15:37:32 +02:00
parent cd4b46f090
commit a242d95c9d
27 changed files with 10004 additions and 0 deletions

1
display/Makefile Symbolic link
View File

@ -0,0 +1 @@
../Makefile

116
display/app/application.cpp Normal file
View File

@ -0,0 +1,116 @@
#include <SpejsNode.h>
SpejsNode node("control-panel");
DriverPWM pwm;
#define SLAVES_COUNT 1
class SlaveEndpoint {
public:
String topic;
int ledPin;
int btnPin;
bool state = false;
uint32_t lastTrigger = 0;
bool lastButton = false;
Timer breatheTimer;
void init() {
if (ledPin != -1)
pinMode(ledPin, OUTPUT);
if (btnPin != -1)
pinMode(btnPin, INPUT_PULLUP);
//breatheTimer.initializeMs(20, TimerDelegate(&SlaveEndpoint::breatheHandler, this)).start();
}
void stateUpdate(bool newState) {
state = newState;
digitalWrite(ledPin, !state);
}
void breatheHandler() {
//pwm.analogWrite(ledPin, (millis()/10) % 50 + 20);
}
SlaveEndpoint(String _topic, int _ledPin = -1, int _btnPin = -1) :
topic(_topic), ledPin(_ledPin), btnPin(_btnPin) {}
};
SlaveEndpoint slaves[] = {
{"iot/b4a90f/relay/on", 2, 0}, // Exhaust
};
class StatusEndpoint : public Endpoint {
public:
Timer sampleTimer;
Timer idleTimer;
StatusEndpoint() : Endpoint("status") { }
void bind(String _name, SpejsNode* _parent) {
Endpoint::bind(_name, _parent);
idleTimer.initializeMs(100, TimerDelegate(&StatusEndpoint::idleHandler, this)).start();
//pwm.initialize();
for(int i = 0; i < SLAVES_COUNT; i++) {
slaves[i].init();
}
}
void idleHandler() {
for(int i = 0; i < SLAVES_COUNT; i++) {
slaves[i].stateUpdate(!slaves[i].state);
}
}
void onConnected() {
idleTimer.stop();
Serial.println("status: connected");
for(int i = 0; i < SLAVES_COUNT; i++) {
Serial.println(i);
parent->mqtt.subscribe(slaves[i].topic);
slaves[i].init();
}
sampleTimer.initializeMs(50, TimerDelegate(&StatusEndpoint::sampleButtons, this)).start();
}
void onMessage(String topic, String payload) {
Serial.println("status: got message");
Serial.printf("%s: %s\r\n", topic.c_str(), payload.c_str());
for(int i = 0; i < SLAVES_COUNT; i++) {
if (topic.equals(slaves[i].topic)) {
slaves[i].stateUpdate(payload.equals("true"));
}
}
}
void sampleButtons() {
for(int i = 0; i < SLAVES_COUNT; i++) {
bool s = digitalRead(slaves[i].btnPin);
if(s != slaves[i].lastButton) {
slaves[i].lastButton = s;
if (!s) {
Serial.println("INTERRUPT");
parent->mqtt.publish(slaves[i].topic + "/set", slaves[i].state ? "false" : "true", true);
}
}
}
}
};
void init() {
node.init();
node.registerEndpoint("status", new StatusEndpoint());
//node.registerEndpoint("relay", new OutputEndpoint(5));
//node.registerEndpoint("dht", new DHTEndpoint(D4, 5000));
}

6920
display/mounting.slvs Normal file

File diff suppressed because it is too large Load Diff

1
ledcontroller/Makefile Symbolic link
View File

@ -0,0 +1 @@
../Makefile

2
ledcontroller/README.md Normal file
View File

@ -0,0 +1,2 @@
This module borrows some code from [esp8266ws2812i2s](https://github.com/cnlohr/esp8266ws2812i2s) project, which is licensed
under [MIT](https://github.com/cnlohr/esp82xx/blob/6053b2f478a2ecae867bef3f98fb265cf4a69a98/LICENSE)

View File

@ -0,0 +1,106 @@
#include <user_config.h>
#include <SmingCore/SmingCore.h>
#include <algorithm>
#include <SpejsNode.h>
extern "C" {
#include "ws2812_i2s.h"
}
#define LEDS_CNT 150
enum LEDMode {
IDLE,
OFF,
WHITE,
STROBE,
BRIGHT,
TEST,
};
class LEDEndpoint : public Endpoint {
private:
struct __attribute__((packed)) {
uint8_t g;
uint8_t r;
uint8_t b;
} leds[LEDS_CNT];
enum LEDMode currentMode = LEDMode::IDLE;
Timer animationTimer;
void animate() {
/*if (i % 50 == 0)
WDT.alive();*/
static int frameCounter = 0;
frameCounter++;
for(int i = 0; i < LEDS_CNT; i++) {
switch(currentMode) {
case LEDMode::IDLE:
leds[i].r = std::max(sin(i * 2*PI/LEDS_CNT - millis() / 1000.0)/2 * 255, 0.0);
leds[i].g = std::max(sin(i * 2*PI/LEDS_CNT + millis() / 500.0)/2 * 255, 0.0);
leds[i].b = std::max(sin(i * 2*PI/LEDS_CNT + millis() / 420.0)/2 * 255, 0.0);
break;
case LEDMode::TEST:
leds[i].r = std::min(std::max((sin(i * 2*PI/LEDS_CNT - millis() / 1000.0)/2 + 0.2) * 255, 0.0), 255.0);
leds[i].g = std::min(std::max((sin(i * 2*PI/LEDS_CNT + millis() / 500.0)/2 + 0.2) * 255, 0.0), 255.0);
leds[i].b = std::min(std::max((sin(i * 2*PI/LEDS_CNT + millis() / 420.0)/2 + 0.2) * 255, 0.0), 255.0);
break;
case LEDMode::BRIGHT:
leds[i].r = std::min(std::max((sin(i * 2*PI/LEDS_CNT - millis() / 1000.0)/4 + 0.5) * 255, 0.0), 255.0);
leds[i].g = std::min(std::max((sin(i * 2*PI/LEDS_CNT + millis() / 500.0)/4 + 0.5) * 255, 0.0), 255.0);
leds[i].b = std::min(std::max((sin(i * 2*PI/LEDS_CNT + millis() / 420.0)/4 + 0.5) * 255, 0.0), 255.0);
break;
case LEDMode::OFF:
leds[i].r = leds[i].g = leds[i].b = 0;
break;
case LEDMode::WHITE:
leds[i].r = leds[i].g = leds[i].b = 255;
break;
case LEDMode::STROBE:
leds[i].r = leds[i].g = leds[i].b = (frameCounter % 2) ? 255 : 0;
break;
}
}
ws2812_push((uint8_t*) leds, sizeof(leds));
}
public:
LEDEndpoint() : Endpoint("leds", {
{"mode", "enum", true, "idle,off,white,strobe,bright,test", "Current LED mode"},
}) {
animationTimer.initializeMs(50, TimerDelegate(&LEDEndpoint::animate, this)).start();
ws2812_init();
}
EndpointResult onValue(String property, String value) {
if (property != "mode") {
return 400;
}
if (value == "idle") currentMode = LEDMode::IDLE;
else if (value == "off") currentMode = LEDMode::OFF;
else if (value == "white") currentMode = LEDMode::WHITE;
else if (value == "strobe") currentMode = LEDMode::STROBE;
else if (value == "bright") currentMode = LEDMode::BRIGHT;
else if (value == "test") currentMode = LEDMode::TEST;
else {
return 400;
}
notify("mode", value);
return 200;
}
};
SpejsNode node("ledcontroller");
void init()
{
node.init();
node.registerEndpoint("leds", new LEDEndpoint());
}

View File

@ -0,0 +1,173 @@
/*
* Copyright (c) Espressif System 2010 - 2012
*
*/
#ifndef _PIN_MUX_H_
#define _PIN_MUX_H_
//Register Bits{{
#define BIT31 0x80000000
#define BIT30 0x40000000
#define BIT29 0x20000000
#define BIT28 0x10000000
#define BIT27 0x08000000
#define BIT26 0x04000000
#define BIT25 0x02000000
#define BIT24 0x01000000
#define BIT23 0x00800000
#define BIT22 0x00400000
#define BIT21 0x00200000
#define BIT20 0x00100000
#define BIT19 0x00080000
#define BIT18 0x00040000
#define BIT17 0x00020000
#define BIT16 0x00010000
#define BIT15 0x00008000
#define BIT14 0x00004000
#define BIT13 0x00002000
#define BIT12 0x00001000
#define BIT11 0x00000800
#define BIT10 0x00000400
#define BIT9 0x00000200
#define BIT8 0x00000100
#define BIT7 0x00000080
#define BIT6 0x00000040
#define BIT5 0x00000020
#define BIT4 0x00000010
#define BIT3 0x00000008
#define BIT2 0x00000004
#define BIT1 0x00000002
#define BIT0 0x00000001
//}}
#define PERIPHS_IO_MUX 0x60000800
#define PERIPHS_IO_MUX_FUNC 0x13
#define PERIPHS_IO_MUX_FUNC_S 4
#define PERIPHS_IO_MUX_PULLUP BIT7
#define PERIPHS_IO_MUX_PULLDWN BIT6
#define PERIPHS_IO_MUX_SLEEP_PULLUP BIT3
#define PERIPHS_IO_MUX_SLEEP_PULLDWN BIT2
#define PERIPHS_IO_MUX_SLEEP_OE BIT1
#define PERIPHS_IO_MUX_OE BIT0
#define PERIPHS_IO_MUX_CONF_U (PERIPHS_IO_MUX + 0x00)
#define SPI0_CLK_EQU_SYS_CLK BIT8
#define SPI1_CLK_EQU_SYS_CLK BIT9
#define PERIPHS_IO_MUX_MTDI_U (PERIPHS_IO_MUX + 0x04)
#define FUNC_MTDI 0
#define FUNC_I2SI_DATA 1
#define FUNC_HSPIQ_MISO 2
#define FUNC_GPIO12 3
#define FUNC_UART0_DTR 4
#define PERIPHS_IO_MUX_MTCK_U (PERIPHS_IO_MUX + 0x08)
#define FUNC_MTCK 0
#define FUNC_I2SI_BCK 1
#define FUNC_HSPID_MOSI 2
#define FUNC_GPIO13 3
#define FUNC_UART0_CTS 4
#define PERIPHS_IO_MUX_MTMS_U (PERIPHS_IO_MUX + 0x0C)
#define FUNC_MTMS 0
#define FUNC_I2SI_WS 1
#define FUNC_HSPI_CLK 2
#define FUNC_GPIO14 3
#define FUNC_UART0_DSR 4
#define PERIPHS_IO_MUX_MTDO_U (PERIPHS_IO_MUX + 0x10)
#define FUNC_MTDO 0
#define FUNC_I2SO_BCK 1
#define FUNC_HSPI_CS0 2
#define FUNC_GPIO15 3
#define FUNC_U0RTS 4
#define FUNC_UART0_RTS 4
#define PERIPHS_IO_MUX_U0RXD_U (PERIPHS_IO_MUX + 0x14)
#define FUNC_U0RXD 0
#define FUNC_I2SO_DATA 1
#define FUNC_GPIO3 3
#define FUNC_CLK_XTAL_BK 4
#define PERIPHS_IO_MUX_U0TXD_U (PERIPHS_IO_MUX + 0x18)
#define FUNC_U0TXD 0
#define FUNC_SPICS1 1
#define FUNC_GPIO1 3
#define FUNC_CLK_RTC_BK 4
#define PERIPHS_IO_MUX_SD_CLK_U (PERIPHS_IO_MUX + 0x1c)
#define FUNC_SDCLK 0
#define FUNC_SPICLK 1
#define FUNC_GPIO6 3
#define UART1_CTS 4
#define PERIPHS_IO_MUX_SD_DATA0_U (PERIPHS_IO_MUX + 0x20)
#define FUNC_SDDATA0 0
#define FUNC_SPIQ_MISO 1
#define FUNC_GPIO7 3
#define FUNC_U1TXD 4
#define FUNC_UART1_TXD 4
#define PERIPHS_IO_MUX_SD_DATA1_U (PERIPHS_IO_MUX + 0x24)
#define FUNC_SDDATA1 0
#define FUNC_SPID_MOSI 1
#define FUNC_GPIO8 3
#define FUNC_U1RXD 4
#define FUNC_UART1_RXD 4
#define PERIPHS_IO_MUX_SD_DATA2_U (PERIPHS_IO_MUX + 0x28)
#define FUNC_SDDATA2 0
#define FUNC_SPIHD 1
#define FUNC_GPIO9 3
#define UFNC_HSPIHD 4
#define PERIPHS_IO_MUX_SD_DATA3_U (PERIPHS_IO_MUX + 0x2c)
#define FUNC_SDDATA3 0
#define FUNC_SPIWP 1
#define FUNC_GPIO10 3
#define FUNC_HSPIWP 4
#define PERIPHS_IO_MUX_SD_CMD_U (PERIPHS_IO_MUX + 0x30)
#define FUNC_SDCMD 0
#define FUNC_SPICS0 1
#define FUNC_GPIO11 3
#define U1RTS 4
#define UART1_RTS 4
#define PERIPHS_IO_MUX_GPIO0_U (PERIPHS_IO_MUX + 0x34)
#define FUNC_GPIO0 0
#define FUNC_SPICS2 1
#define FUNC_CLK_OUT 4
#define PERIPHS_IO_MUX_GPIO2_U (PERIPHS_IO_MUX + 0x38)
#define FUNC_GPIO2 0
#define FUNC_I2SO_WS 1
#define FUNC_U1TXD_BK 2
#define FUNC_UART1_TXD_BK 2
#define FUNC_U0TXD_BK 4
#define FUNC_UART0_TXD_BK 4
#define PERIPHS_IO_MUX_GPIO4_U (PERIPHS_IO_MUX + 0x3C)
#define FUNC_GPIO4 0
#define FUNC_CLK_XTAL 1
#define PERIPHS_IO_MUX_GPIO5_U (PERIPHS_IO_MUX + 0x40)
#define FUNC_GPIO5 0
#define FUNC_CLK_RTC 1
#define PIN_PULLUP_DIS(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME, PERIPHS_IO_MUX_PULLUP)
#define PIN_PULLUP_EN(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME, PERIPHS_IO_MUX_PULLUP)
//XXX THIS LOOKS WRONG.
#undef PIN_FUNC_SELECT
#define PIN_FUNC_SELECT(PIN_NAME, FUNC) do { \
CLEAR_PERI_REG_MASK(PIN_NAME, (PERIPHS_IO_MUX_FUNC<<PERIPHS_IO_MUX_FUNC_S)); \
SET_PERI_REG_MASK(PIN_NAME, (((FUNC&BIT2)<<2)|(FUNC&0x3))<<PERIPHS_IO_MUX_FUNC_S); \
} while (0)
#endif //_PIN_MUX_H_

View File

@ -0,0 +1,281 @@
//Generated at 2012-10-23 19:55:03
/*
* Copyright (c) 2010 - 2011 Espressif System
*
*/
#ifndef SLC_REGISTER_H_
#define SLC_REGISTER_H_
#define REG_SLC_BASE 0x60000B00
//version value:32'h091700
#define SLC_CONF0 (REG_SLC_BASE + 0x0)
#ifndef ESP_MAC_5
#define SLC_MODE 0x00000003
#define SLC_MODE_S 12
#endif
#define SLC_DATA_BURST_EN (BIT(9))
#define SLC_DSCR_BURST_EN (BIT(8))
#define SLC_RX_NO_RESTART_CLR (BIT(7))
#define SLC_RX_AUTO_WRBACK (BIT(6))
#define SLC_RX_LOOP_TEST (BIT(5))
#define SLC_TX_LOOP_TEST (BIT(4))
#define SLC_AHBM_RST (BIT(3))
#define SLC_AHBM_FIFO_RST (BIT(2))
#define SLC_RXLINK_RST (BIT(1))
#define SLC_TXLINK_RST (BIT(0))
#define SLC_INT_RAW (REG_SLC_BASE + 0x4)
#define SLC_TX_DSCR_EMPTY_INT_RAW (BIT(21))
#define SLC_RX_DSCR_ERR_INT_RAW (BIT(20))
#define SLC_TX_DSCR_ERR_INT_RAW (BIT(19))
#define SLC_TOHOST_INT_RAW (BIT(18))
#define SLC_RX_EOF_INT_RAW (BIT(17))
#define SLC_RX_DONE_INT_RAW (BIT(16))
#define SLC_TX_EOF_INT_RAW (BIT(15))
#define SLC_TX_DONE_INT_RAW (BIT(14))
#define SLC_TOKEN1_1TO0_INT_RAW (BIT(13))
#define SLC_TOKEN0_1TO0_INT_RAW (BIT(12))
#define SLC_TX_OVF_INT_RAW (BIT(11))
#define SLC_RX_UDF_INT_RAW (BIT(10))
#define SLC_TX_START_INT_RAW (BIT(9))
#define SLC_RX_START_INT_RAW (BIT(8))
#define SLC_FRHOST_BIT7_INT_RAW (BIT(7))
#define SLC_FRHOST_BIT6_INT_RAW (BIT(6))
#define SLC_FRHOST_BIT5_INT_RAW (BIT(5))
#define SLC_FRHOST_BIT4_INT_RAW (BIT(4))
#define SLC_FRHOST_BIT3_INT_RAW (BIT(3))
#define SLC_FRHOST_BIT2_INT_RAW (BIT(2))
#define SLC_FRHOST_BIT1_INT_RAW (BIT(1))
#define SLC_FRHOST_BIT0_INT_RAW (BIT(0))
#define SLC_INT_STATUS (REG_SLC_BASE + 0x8)
#define SLC_TX_DSCR_EMPTY_INT_ST (BIT(21))
#define SLC_RX_DSCR_ERR_INT_ST (BIT(20))
#define SLC_TX_DSCR_ERR_INT_ST (BIT(19))
#define SLC_TOHOST_INT_ST (BIT(18))
#define SLC_RX_EOF_INT_ST (BIT(17))
#define SLC_RX_DONE_INT_ST (BIT(16))
#define SLC_TX_EOF_INT_ST (BIT(15))
#define SLC_TX_DONE_INT_ST (BIT(14))
#define SLC_TOKEN1_1TO0_INT_ST (BIT(13))
#define SLC_TOKEN0_1TO0_INT_ST (BIT(12))
#define SLC_TX_OVF_INT_ST (BIT(11))
#define SLC_RX_UDF_INT_ST (BIT(10))
#define SLC_TX_START_INT_ST (BIT(9))
#define SLC_RX_START_INT_ST (BIT(8))
#define SLC_FRHOST_BIT7_INT_ST (BIT(7))
#define SLC_FRHOST_BIT6_INT_ST (BIT(6))
#define SLC_FRHOST_BIT5_INT_ST (BIT(5))
#define SLC_FRHOST_BIT4_INT_ST (BIT(4))
#define SLC_FRHOST_BIT3_INT_ST (BIT(3))
#define SLC_FRHOST_BIT2_INT_ST (BIT(2))
#define SLC_FRHOST_BIT1_INT_ST (BIT(1))
#define SLC_FRHOST_BIT0_INT_ST (BIT(0))
#define SLC_INT_ENA (REG_SLC_BASE + 0xC)
#define SLC_TX_DSCR_EMPTY_INT_ENA (BIT(21))
#define SLC_RX_DSCR_ERR_INT_ENA (BIT(20))
#define SLC_TX_DSCR_ERR_INT_ENA (BIT(19))
#define SLC_TOHOST_INT_ENA (BIT(18))
#define SLC_RX_EOF_INT_ENA (BIT(17))
#define SLC_RX_DONE_INT_ENA (BIT(16))
#define SLC_TX_EOF_INT_ENA (BIT(15))
#define SLC_TX_DONE_INT_ENA (BIT(14))
#define SLC_TOKEN1_1TO0_INT_ENA (BIT(13))
#define SLC_TOKEN0_1TO0_INT_ENA (BIT(12))
#define SLC_TX_OVF_INT_ENA (BIT(11))
#define SLC_RX_UDF_INT_ENA (BIT(10))
#define SLC_TX_START_INT_ENA (BIT(9))
#define SLC_RX_START_INT_ENA (BIT(8))
#define SLC_FRHOST_BIT7_INT_ENA (BIT(7))
#define SLC_FRHOST_BIT6_INT_ENA (BIT(6))
#define SLC_FRHOST_BIT5_INT_ENA (BIT(5))
#define SLC_FRHOST_BIT4_INT_ENA (BIT(4))
#define SLC_FRHOST_BIT3_INT_ENA (BIT(3))
#define SLC_FRHOST_BIT2_INT_ENA (BIT(2))
#define SLC_FRHOST_BIT1_INT_ENA (BIT(1))
#define SLC_FRHOST_BIT0_INT_ENA (BIT(0))
#define SLC_FRHOST_BIT_INT_ENA_ALL 0xff
#define SLC_INT_CLR (REG_SLC_BASE + 0x10)
#define SLC_TX_DSCR_EMPTY_INT_CLR (BIT(21))
#define SLC_RX_DSCR_ERR_INT_CLR (BIT(20))
#define SLC_TX_DSCR_ERR_INT_CLR (BIT(19))
#define SLC_TOHOST_INT_CLR (BIT(18))
#define SLC_RX_EOF_INT_CLR (BIT(17))
#define SLC_RX_DONE_INT_CLR (BIT(16))
#define SLC_TX_EOF_INT_CLR (BIT(15))
#define SLC_TX_DONE_INT_CLR (BIT(14))
#define SLC_TOKEN1_1TO0_INT_CLR (BIT(13))
#define SLC_TOKEN0_1TO0_INT_CLR (BIT(12))
#define SLC_TX_OVF_INT_CLR (BIT(11))
#define SLC_RX_UDF_INT_CLR (BIT(10))
#define SLC_TX_START_INT_CLR (BIT(9))
#define SLC_RX_START_INT_CLR (BIT(8))
#define SLC_FRHOST_BIT7_INT_CLR (BIT(7))
#define SLC_FRHOST_BIT6_INT_CLR (BIT(6))
#define SLC_FRHOST_BIT5_INT_CLR (BIT(5))
#define SLC_FRHOST_BIT4_INT_CLR (BIT(4))
#define SLC_FRHOST_BIT3_INT_CLR (BIT(3))
#define SLC_FRHOST_BIT2_INT_CLR (BIT(2))
#define SLC_FRHOST_BIT1_INT_CLR (BIT(1))
#define SLC_FRHOST_BIT0_INT_CLR (BIT(0))
#define SLC_RX_STATUS (REG_SLC_BASE + 0x14)
#define SLC_RX_EMPTY (BIT(1))
#define SLC_RX_FULL (BIT(0))
#define SLC_RX_FIFO_PUSH (REG_SLC_BASE + 0x18)
#define SLC_RXFIFO_PUSH (BIT(16))
#define SLC_RXFIFO_WDATA 0x000001FF
#define SLC_RXFIFO_WDATA_S 0
#define SLC_TX_STATUS (REG_SLC_BASE + 0x1C)
#define SLC_TX_EMPTY (BIT(1))
#define SLC_TX_FULL (BIT(0))
#define SLC_TX_FIFO_POP (REG_SLC_BASE + 0x20)
#define SLC_TXFIFO_POP (BIT(16))
#define SLC_TXFIFO_RDATA 0x000007FF
#define SLC_TXFIFO_RDATA_S 0
#define SLC_RX_LINK (REG_SLC_BASE + 0x24)
#define SLC_RXLINK_PARK (BIT(31))
#define SLC_RXLINK_RESTART (BIT(30))
#define SLC_RXLINK_START (BIT(29))
#define SLC_RXLINK_STOP (BIT(28))
#define SLC_RXLINK_DESCADDR_MASK 0x000FFFFF
#define SLC_RXLINK_ADDR_S 0
#define SLC_TX_LINK (REG_SLC_BASE + 0x28)
#define SLC_TXLINK_PARK (BIT(31))
#define SLC_TXLINK_RESTART (BIT(30))
#define SLC_TXLINK_START (BIT(29))
#define SLC_TXLINK_STOP (BIT(28))
#define SLC_TXLINK_DESCADDR_MASK 0x000FFFFF
#define SLC_TXLINK_ADDR_S 0
#define SLC_INTVEC_TOHOST (REG_SLC_BASE + 0x2C)
#define SLC_TOHOST_INTVEC 0x000000FF
#define SLC_TOHOST_INTVEC_S 0
#define SLC_TOKEN0 (REG_SLC_BASE + 0x30)
#define SLC_TOKEN0_MASK 0x00000FFF
#define SLC_TOKEN0_S 16
#define SLC_TOKEN0_LOCAL_INC_MORE (BIT(14))
#define SLC_TOKEN0_LOCAL_INC (BIT(13))
#define SLC_TOKEN0_LOCAL_WR (BIT(12))
#define SLC_TOKEN0_LOCAL_WDATA_MASK 0x00000FFF
#define SLC_TOKEN0_LOCAL_WDATA_S 0
#define SLC_TOKEN1 (REG_SLC_BASE + 0x34)
#define SLC_TOKEN1_MASK 0x00000FFF
#define SLC_TOKEN1_S 16
#define SLC_TOKEN1_LOCAL_INC_MORE (BIT(14))
#define SLC_TOKEN1_LOCAL_INC (BIT(13))
#define SLC_TOKEN1_LOCAL_WR (BIT(12))
#define SLC_TOKEN1_LOCAL_WDATA 0x00000FFF
#define SLC_TOKEN1_LOCAL_WDATA_S 0
#define SLC_CONF1 (REG_SLC_BASE + 0x38)
#define SLC_STATE0 (REG_SLC_BASE + 0x3C)
#define SLC_STATE1 (REG_SLC_BASE + 0x40)
#define SLC_BRIDGE_CONF (REG_SLC_BASE + 0x44)
#ifndef ESP_MAC_5
#define SLC_TX_PUSH_IDLE_NUM 0x0000FFFF
#define SLC_TX_PUSH_IDLE_NUM_S 16
#define SLC_TX_DUMMY_MODE (BIT(12))
#endif
#define SLC_FIFO_MAP_ENA 0x0000000F
#define SLC_FIFO_MAP_ENA_S 8
#define SLC_TXEOF_ENA 0x0000003F
#define SLC_TXEOF_ENA_S 0
#define SLC_RX_EOF_DES_ADDR (REG_SLC_BASE + 0x48)
#define SLC_TX_EOF_DES_ADDR (REG_SLC_BASE + 0x4C)
#define SLC_FROM_HOST_LAST_DESC SLC_TX_EOF_DES_ADDR
#define SLC_TO_HOST_LAST_DESC SLC_RX_EOF_DES_ADDR
#define SLC_RX_EOF_BFR_DES_ADDR (REG_SLC_BASE + 0x50)
#define SLC_AHB_TEST (REG_SLC_BASE + 0x54)
#define SLC_AHB_TESTADDR 0x00000003
#define SLC_AHB_TESTADDR_S 4
#define SLC_AHB_TESTMODE 0x00000007
#define SLC_AHB_TESTMODE_S 0
#define SLC_SDIO_ST (REG_SLC_BASE + 0x58)
#define SLC_BUS_ST 0x00000007
#define SLC_BUS_ST_S 12
#define SLC_SDIO_WAKEUP (BIT(8))
#define SLC_FUNC_ST 0x0000000F
#define SLC_FUNC_ST_S 4
#define SLC_CMD_ST 0x00000007
#define SLC_CMD_ST_S 0
#define SLC_RX_DSCR_CONF (REG_SLC_BASE + 0x5C)
#ifdef ESP_MAC_5
#define SLC_INFOR_NO_REPLACE (BIT(9))
#define SLC_TOKEN_NO_REPLACE (BIT(8))
#define SLC_POP_IDLE_CNT 0x000000FF
#else
#define SLC_RX_FILL_EN (BIT(20))
#define SLC_RX_EOF_MODE (BIT(19))
#define SLC_RX_FILL_MODE (BIT(18))
#define SLC_INFOR_NO_REPLACE (BIT(17))
#define SLC_TOKEN_NO_REPLACE (BIT(16))
#define SLC_POP_IDLE_CNT 0x0000FFFF
#endif
#define SLC_POP_IDLE_CNT_S 0
#define SLC_TXLINK_DSCR (REG_SLC_BASE + 0x60)
#define SLC_TXLINK_DSCR_BF0 (REG_SLC_BASE + 0x64)
#define SLC_TXLINK_DSCR_BF1 (REG_SLC_BASE + 0x68)
#define SLC_RXLINK_DSCR (REG_SLC_BASE + 0x6C)
#define SLC_RXLINK_DSCR_BF0 (REG_SLC_BASE + 0x70)
#define SLC_RXLINK_DSCR_BF1 (REG_SLC_BASE + 0x74)
#define SLC_DATE (REG_SLC_BASE + 0x78)
#define SLC_ID (REG_SLC_BASE + 0x7C)
#define SLC_HOST_CONF_W0 (REG_SLC_BASE + 0x80 + 0x14)
#define SLC_HOST_CONF_W1 (REG_SLC_BASE + 0x80 + 0x18)
#define SLC_HOST_CONF_W2 (REG_SLC_BASE + 0x80 + 0x20)
#define SLC_HOST_CONF_W3 (REG_SLC_BASE + 0x80 + 0x24)
#define SLC_HOST_CONF_W4 (REG_SLC_BASE + 0x80 + 0x28)
#define SLC_HOST_INTR_ST (REG_SLC_BASE + 0x80 + 0x1c)
#define SLC_HOST_INTR_CLR (REG_SLC_BASE + 0x80 + 0x30)
#define SLC_HOST_INTR_SOF_BIT (BIT(12))
#define SLC_HOST_INTR_ENA (REG_SLC_BASE + 0x80 + 0x34)
#define SLC_RX_NEW_PACKET_INT_ENA (BIT23)
#define SLC_HOST_TOHOST_BIT0_INT_ENA (BIT0)
#define SLC_HOST_CONF_W5 (REG_SLC_BASE + 0x80 + 0x3C)
#define SLC_HOST_INTR_RAW (REG_SLC_BASE + 0x80 + 0x8)
#define SLC_HOST_INTR_ENA_BIT (BIT(23))
//[15:12]: 0x3ff9xxxx -- 0b01 from_host
// 0x3ffaxxxx -- 0b10 general
// 0x3ffbxxxx -- 0b11 to_host
#define SLC_DATA_ADDR_CLEAR_MASK (~(0xf<<12))
#define SLC_FROM_HOST_ADDR_MASK (0x1<<12)
#define SLC_TO_HOST_ADDR_MASK (0x3<<12)
#define SLC_SET_FROM_HOST_ADDR_MASK(v) do { \
(v) &= SLC_DATA_ADDR_CLEAR_MASK; \
(v) |= SLC_FROM_HOST_ADDR_MASK; \
} while(0);
#define SLC_SET_TO_HOST_ADDR_MASK(v) do { \
(v) &= SLC_DATA_ADDR_CLEAR_MASK; \
(v) |= SLC_TO_HOST_ADDR_MASK; \
} while(0);
#define SLC_TX_DESC_DEBUG_REG 0x3ff0002c //[15:0] set to 0xcccc
#endif // SLC_REGISTER_H_INCLUDED

View File

@ -0,0 +1,542 @@
/******************************************************************************
* Copyright 2013-2015 Espressif Systems
* 2015 <>< Charles Lohr
*
* FileName: i2s_freertos.c
*
* Description: I2S output routines for a FreeRTOS system. Uses DMA and a queue
* to abstract away the nitty-gritty details.
*
* Modification history:
* 2015/06/01, v1.0 File created.
* 2015/07/23, Switch to making it a WS2812 output device.
*******************************************************************************
Notes:
This is pretty badly hacked together from the MP3 example.
I spent some time trying to strip it down to avoid a lot of the TX_ stuff.
That seems to work.
Major suggestions that I couldn't figure out:
* Use interrupts to disable DMA, so it isn't running nonstop.
* Use interrupts to flag when new data can be sent.
When I try using interrupts, it seems to work for a bit but things fall apart
rather quickly and the engine just refuses to send anymore until reboot.
The way it works right now is to keep the DMA running forever and just update
the data in the buffer so it continues sending the frame.
Extra copyright info:
Actually not much of this file is Copyright Espressif, comparativly little
mostly just the stuff to make the I2S bus go.
*******************************************************************************/
#include "eagle_soc.h"
#include "slc_register.h"
// #include "esp82xxutil.h"
#include <c_types.h>
#include "ws2812_i2s.h"
//#include "user_interface.h"
#include "pin_mux_register.h"
//Creates an I2S SR of 93,750 Hz, or 3 MHz Bitclock (.333us/sample)
// 1600000000L/(div*bestbck)
//It is likely you could speed this up a little.
#ifdef WS2812_THREE_SAMPLE
#define WS_I2S_BCK 21 //Seems to work as low as 18, but is shakey at 1.
#define WS_I2S_DIV 3
#elif defined( WS2812_FOUR_SAMPLE ) || defined(SK6812)
#define WS_I2S_BCK 16 //Seems to work as low as 13, shoddy at 12.
#define WS_I2S_DIV 3
#else
#error You need to either define WS2812_THREE_SAMPLE, WS2812_FOUR_SAMPLE or SK6812
#endif
#ifndef i2c_bbpll
#define i2c_bbpll 0x67
#define i2c_bbpll_en_audio_clock_out 4
#define i2c_bbpll_en_audio_clock_out_msb 7
#define i2c_bbpll_en_audio_clock_out_lsb 7
#define i2c_bbpll_hostid 4
#define i2c_writeReg_Mask(block, host_id, reg_add, Msb, Lsb, indata) rom_i2c_writeReg_Mask(block, host_id, reg_add, Msb, Lsb, indata)
#define i2c_readReg_Mask(block, host_id, reg_add, Msb, Lsb) rom_i2c_readReg_Mask(block, host_id, reg_add, Msb, Lsb)
#define i2c_writeReg_Mask_def(block, reg_add, indata) \
i2c_writeReg_Mask(block, block##_hostid, reg_add, reg_add##_msb, reg_add##_lsb, indata)
#define i2c_readReg_Mask_def(block, reg_add) \
i2c_readReg_Mask(block, block##_hostid, reg_add, reg_add##_msb, reg_add##_lsb)
#endif
#ifndef ETS_SLC_INUM
#define ETS_SLC_INUM 1
#endif
//From i2s_reg.h
#define DR_REG_I2S_BASE (0x60000e00)
#define I2STXFIFO (DR_REG_I2S_BASE + 0x0000)
#define I2SRXFIFO (DR_REG_I2S_BASE + 0x0004)
#define I2SCONF (DR_REG_I2S_BASE + 0x0008)
#define I2S_BCK_DIV_NUM 0x0000003F
#define I2S_BCK_DIV_NUM_S 22
#define I2S_CLKM_DIV_NUM 0x0000003F
#define I2S_CLKM_DIV_NUM_S 16
#define I2S_BITS_MOD 0x0000000F
#define I2S_BITS_MOD_S 12
#define I2S_RECE_MSB_SHIFT (BIT(11))
#define I2S_TRANS_MSB_SHIFT (BIT(10))
#define I2S_I2S_RX_START (BIT(9))
#define I2S_I2S_TX_START (BIT(8))
#define I2S_MSB_RIGHT (BIT(7))
#define I2S_RIGHT_FIRST (BIT(6))
#define I2S_RECE_SLAVE_MOD (BIT(5))
#define I2S_TRANS_SLAVE_MOD (BIT(4))
#define I2S_I2S_RX_FIFO_RESET (BIT(3))
#define I2S_I2S_TX_FIFO_RESET (BIT(2))
#define I2S_I2S_RX_RESET (BIT(1))
#define I2S_I2S_TX_RESET (BIT(0))
#define I2S_I2S_RESET_MASK 0xf
#define I2SINT_RAW (DR_REG_I2S_BASE + 0x000c)
#define I2S_I2S_TX_REMPTY_INT_RAW (BIT(5))
#define I2S_I2S_TX_WFULL_INT_RAW (BIT(4))
#define I2S_I2S_RX_REMPTY_INT_RAW (BIT(3))
#define I2S_I2S_RX_WFULL_INT_RAW (BIT(2))
#define I2S_I2S_TX_PUT_DATA_INT_RAW (BIT(1))
#define I2S_I2S_RX_TAKE_DATA_INT_RAW (BIT(0))
#define I2SINT_ST (DR_REG_I2S_BASE + 0x0010)
#define I2S_I2S_TX_REMPTY_INT_ST (BIT(5))
#define I2S_I2S_TX_WFULL_INT_ST (BIT(4))
#define I2S_I2S_RX_REMPTY_INT_ST (BIT(3))
#define I2S_I2S_RX_WFULL_INT_ST (BIT(2))
#define I2S_I2S_TX_PUT_DATA_INT_ST (BIT(1))
#define I2S_I2S_RX_TAKE_DATA_INT_ST (BIT(0))
#define I2SINT_ENA (DR_REG_I2S_BASE + 0x0014)
#define I2S_I2S_TX_REMPTY_INT_ENA (BIT(5))
#define I2S_I2S_TX_WFULL_INT_ENA (BIT(4))
#define I2S_I2S_RX_REMPTY_INT_ENA (BIT(3))
#define I2S_I2S_RX_WFULL_INT_ENA (BIT(2))
#define I2S_I2S_TX_PUT_DATA_INT_ENA (BIT(1))
#define I2S_I2S_RX_TAKE_DATA_INT_ENA (BIT(0))
#define I2SINT_CLR (DR_REG_I2S_BASE + 0x0018)
#define I2S_I2S_TX_REMPTY_INT_CLR (BIT(5))
#define I2S_I2S_TX_WFULL_INT_CLR (BIT(4))
#define I2S_I2S_RX_REMPTY_INT_CLR (BIT(3))
#define I2S_I2S_RX_WFULL_INT_CLR (BIT(2))
#define I2S_I2S_PUT_DATA_INT_CLR (BIT(1))
#define I2S_I2S_TAKE_DATA_INT_CLR (BIT(0))
#define I2STIMING (DR_REG_I2S_BASE + 0x001c)
#define I2S_TRANS_BCK_IN_INV (BIT(22))
#define I2S_RECE_DSYNC_SW (BIT(21))
#define I2S_TRANS_DSYNC_SW (BIT(20))
#define I2S_RECE_BCK_OUT_DELAY 0x00000003
#define I2S_RECE_BCK_OUT_DELAY_S 18
#define I2S_RECE_WS_OUT_DELAY 0x00000003
#define I2S_RECE_WS_OUT_DELAY_S 16
#define I2S_TRANS_SD_OUT_DELAY 0x00000003
#define I2S_TRANS_SD_OUT_DELAY_S 14
#define I2S_TRANS_WS_OUT_DELAY 0x00000003
#define I2S_TRANS_WS_OUT_DELAY_S 12
#define I2S_TRANS_BCK_OUT_DELAY 0x00000003
#define I2S_TRANS_BCK_OUT_DELAY_S 10
#define I2S_RECE_SD_IN_DELAY 0x00000003
#define I2S_RECE_SD_IN_DELAY_S 8
#define I2S_RECE_WS_IN_DELAY 0x00000003
#define I2S_RECE_WS_IN_DELAY_S 6
#define I2S_RECE_BCK_IN_DELAY 0x00000003
#define I2S_RECE_BCK_IN_DELAY_S 4
#define I2S_TRANS_WS_IN_DELAY 0x00000003
#define I2S_TRANS_WS_IN_DELAY_S 2
#define I2S_TRANS_BCK_IN_DELAY 0x00000003
#define I2S_TRANS_BCK_IN_DELAY_S 0
#define I2S_FIFO_CONF (DR_REG_I2S_BASE + 0x0020)
#define I2S_I2S_RX_FIFO_MOD 0x00000007
#define I2S_I2S_RX_FIFO_MOD_S 16
#define I2S_I2S_TX_FIFO_MOD 0x00000007
#define I2S_I2S_TX_FIFO_MOD_S 13
#define I2S_I2S_DSCR_EN (BIT(12))
#define I2S_I2S_TX_DATA_NUM 0x0000003F
#define I2S_I2S_TX_DATA_NUM_S 6
#define I2S_I2S_RX_DATA_NUM 0x0000003F
#define I2S_I2S_RX_DATA_NUM_S 0
#define I2SRXEOF_NUM (DR_REG_I2S_BASE + 0x0024)
#define I2S_I2S_RX_EOF_NUM 0xFFFFFFFF
#define I2S_I2S_RX_EOF_NUM_S 0
#define I2SCONF_SIGLE_DATA (DR_REG_I2S_BASE + 0x0028)
#define I2S_I2S_SIGLE_DATA 0xFFFFFFFF
#define I2S_I2S_SIGLE_DATA_S 0
#define I2SCONF_CHAN (DR_REG_I2S_BASE + 0x002c)
#define I2S_RX_CHAN_MOD 0x00000003
#define I2S_RX_CHAN_MOD_S 3
#define I2S_TX_CHAN_MOD 0x00000007
#define I2S_TX_CHAN_MOD_S 0
//From sdio_slv.h
struct sdio_queue
{
uint32 blocksize:12;
uint32 datalen:12;
uint32 unused:5;
uint32 sub_sof:1;
uint32 eof:1;
uint32 owner:1;
uint32 buf_ptr;
uint32 next_link_ptr;
};
struct sdio_slave_status_element
{
uint32 wr_busy:1;
uint32 rd_empty :1;
uint32 comm_cnt :3;
uint32 intr_no :3;
uint32 rx_length:16;
uint32 res:8;
};
union sdio_slave_status
{
struct sdio_slave_status_element elm_value;
uint32 word_value;
};
#define RX_AVAILIBLE 2
#define TX_AVAILIBLE 1
#define INIT_STAGE 0
#define SDIO_QUEUE_LEN 8
#define MOSI 0
#define MISO 1
#define SDIO_DATA_ERROR 6
#define SLC_INTEREST_EVENT (SLC_TX_EOF_INT_ENA | SLC_RX_EOF_INT_ENA | SLC_RX_UDF_INT_ENA | SLC_TX_DSCR_ERR_INT_ENA)
#define TRIG_TOHOST_INT() SET_PERI_REG_MASK(SLC_INTVEC_TOHOST , BIT0);\
CLEAR_PERI_REG_MASK(SLC_INTVEC_TOHOST , BIT0)
///Rest of program...
//Pointer to the I2S DMA buffer data
//static unsigned int i2sBuf[I2SDMABUFCNT][I2SDMABUFLEN];
//I2S DMA buffer descriptors
//static struct sdio_queue i2sBufDesc[I2SDMABUFCNT];
static struct sdio_queue i2sBufDescOut;
static struct sdio_queue i2sBufDescZeroes;
static unsigned int i2sZeroes[32];
static unsigned int i2sBlock[WS_BLOCKSIZE/4];
//Queue which contains empty DMA buffers
//DMA underrun counter
#ifdef USE_2812_INTERRUPTS
volatile uint8_t ws2812_dma_complete;
//This routine is called as soon as the DMA routine has something to tell us. All we
//handle here is the RX_EOF_INT status, which indicate the DMA has sent a buffer whose
//descriptor has the 'EOF' field set to 1.
LOCAL void slc_isr(void) {
//clear all intr flags
// WRITE_PERI_REG(SLC_INT_CLR, 0xffffffff);//slc_intr_status);
// ws2812_dma_complete = 1;
//This is a little wacky. This function actually gets called twice.
//Once for the initial transfer, but by the time we tell it to stop
//The other zero transfer's already begun.
// SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_STOP);
}
#endif
//Initialize I2S subsystem for DMA circular buffer use
void ICACHE_FLASH_ATTR ws2812_init()
{
int x, y;
//Reset DMA
SET_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST);//|SLC_TXLINK_RST);
CLEAR_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST);//|SLC_TXLINK_RST);
//Clear DMA int flags
SET_PERI_REG_MASK(SLC_INT_CLR, 0xffffffff);
CLEAR_PERI_REG_MASK(SLC_INT_CLR, 0xffffffff);
//Enable and configure DMA
CLEAR_PERI_REG_MASK(SLC_CONF0, (SLC_MODE<<SLC_MODE_S));
SET_PERI_REG_MASK(SLC_CONF0,(1<<SLC_MODE_S));
SET_PERI_REG_MASK(SLC_RX_DSCR_CONF,SLC_INFOR_NO_REPLACE|SLC_TOKEN_NO_REPLACE);
CLEAR_PERI_REG_MASK(SLC_RX_DSCR_CONF, SLC_RX_FILL_EN|SLC_RX_EOF_MODE | SLC_RX_FILL_MODE);
i2sBufDescOut.owner = 1;
i2sBufDescOut.eof = 1;
i2sBufDescOut.sub_sof = 0;
i2sBufDescOut.datalen = WS_BLOCKSIZE; //Size (in bytes)
i2sBufDescOut.blocksize = WS_BLOCKSIZE; //Size (in bytes)
i2sBufDescOut.buf_ptr=(uint32_t)&i2sBlock[0];
i2sBufDescOut.unused=0;
i2sBufDescOut.next_link_ptr=(uint32_t)&i2sBufDescZeroes; //At the end, just redirect the DMA to the zero buffer.
i2sBufDescZeroes.owner = 1;
i2sBufDescZeroes.eof = 1;
i2sBufDescZeroes.sub_sof = 0;
i2sBufDescZeroes.datalen = 32;
i2sBufDescZeroes.blocksize = 32;
i2sBufDescZeroes.buf_ptr=(uint32_t)&i2sZeroes[0];
i2sBufDescZeroes.unused=0;
i2sBufDescZeroes.next_link_ptr=(uint32_t)&i2sBufDescOut;
for( x = 0; x < 32; x++ )
{
i2sZeroes[x] = 0x00;
}
for( x = 0; x < WS_BLOCKSIZE/4; x++ )
{
i2sBlock[x] = 0x00000000;//(x == 0 || x == 999)?0xaa:0x00;
/* uint16_t * tt = (uint16_t*)&i2sBlock[x];
(*(tt+0)) = 0xA0F0;
(*(tt+1)) = 0xC0E0;*/
}
// CLEAR_PERI_REG_MASK(SLC_TX_LINK,SLC_TXLINK_DESCADDR_MASK);
// SET_PERI_REG_MASK(SLC_TX_LINK, ((uint32)&i2sBufDescZeroes) & SLC_TXLINK_DESCADDR_MASK); //any random desc is OK, we don't use TX but it needs something valid
CLEAR_PERI_REG_MASK(SLC_RX_LINK,SLC_RXLINK_DESCADDR_MASK);
SET_PERI_REG_MASK(SLC_RX_LINK, ((uint32)&i2sBufDescOut) & SLC_RXLINK_DESCADDR_MASK);
#ifdef USE_2812_INTERRUPTS
//Attach the DMA interrupt
ets_isr_attach(ETS_SLC_INUM, slc_isr);
//Enable DMA operation intr
WRITE_PERI_REG(SLC_INT_ENA, SLC_RX_EOF_INT_ENA);
//clear any interrupt flags that are set
WRITE_PERI_REG(SLC_INT_CLR, 0xffffffff);
///enable DMA intr in cpu
ets_isr_unmask(1<<ETS_SLC_INUM);
#endif
//Start transmission
// SET_PERI_REG_MASK(SLC_TX_LINK, SLC_TXLINK_START);
SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_START);
//----
//Init pins to i2s functions
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_I2SO_DATA);
// PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_I2SO_WS);
// PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_I2SO_BCK);
//Enable clock to i2s subsystem
i2c_writeReg_Mask_def(i2c_bbpll, i2c_bbpll_en_audio_clock_out, 1);
//Reset I2S subsystem
CLEAR_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK);
SET_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK);
CLEAR_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK);
//Select 16bits per channel (FIFO_MOD=0), no DMA access (FIFO only)
CLEAR_PERI_REG_MASK(I2S_FIFO_CONF, I2S_I2S_DSCR_EN|(I2S_I2S_RX_FIFO_MOD<<I2S_I2S_RX_FIFO_MOD_S)|(I2S_I2S_TX_FIFO_MOD<<I2S_I2S_TX_FIFO_MOD_S));
//Enable DMA in i2s subsystem
SET_PERI_REG_MASK(I2S_FIFO_CONF, I2S_I2S_DSCR_EN);
//tx/rx binaureal
// CLEAR_PERI_REG_MASK(I2SCONF_CHAN, (I2S_TX_CHAN_MOD<<I2S_TX_CHAN_MOD_S)|(I2S_RX_CHAN_MOD<<I2S_RX_CHAN_MOD_S));
#ifdef USE_2812_INTERRUPTS
//Clear int
SET_PERI_REG_MASK(I2SINT_CLR,
I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR);
CLEAR_PERI_REG_MASK(I2SINT_CLR,
I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR);
#endif
//trans master&rece slave,MSB shift,right_first,msb right
CLEAR_PERI_REG_MASK(I2SCONF, I2S_TRANS_SLAVE_MOD|
(I2S_BITS_MOD<<I2S_BITS_MOD_S)|
(I2S_BCK_DIV_NUM <<I2S_BCK_DIV_NUM_S)|
(I2S_CLKM_DIV_NUM<<I2S_CLKM_DIV_NUM_S));
SET_PERI_REG_MASK(I2SCONF, I2S_RIGHT_FIRST|I2S_MSB_RIGHT|I2S_RECE_SLAVE_MOD|
I2S_RECE_MSB_SHIFT|I2S_TRANS_MSB_SHIFT|
(((WS_I2S_BCK)&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)|
(((WS_I2S_DIV)&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S));
//No idea if ints are needed...
//clear int
SET_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR);
CLEAR_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR);
//enable int
SET_PERI_REG_MASK(I2SINT_ENA, I2S_I2S_RX_REMPTY_INT_ENA|I2S_I2S_RX_TAKE_DATA_INT_ENA);
//Start transmission
SET_PERI_REG_MASK(I2SCONF,I2S_I2S_TX_START);
}
//All functions below this line are Public Domain 2015 Charles Lohr.
//this code may be used by anyone in any way without restriction or limitation.
#ifdef WS2812_THREE_SAMPLE
static const uint16_t bitpatterns[16] = {
0b100100100100, 0b100100100110, 0b100100110100, 0b100100110110,
0b100110100100, 0b100110100110, 0b100110110100, 0b100110110110,
0b110100100100, 0b110100100110, 0b110100110100, 0b110100110110,
0b110110100100, 0b110110100110, 0b110110110100, 0b110110110110,
};
#elif defined(WS2812_FOUR_SAMPLE)
//Tricky, send out WS2812 bits with coded pulses, one nibble, then the other.
static const uint16_t bitpatterns[16] = {
0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110,
0b1000111010001000, 0b1000111010001110, 0b1000111011101000, 0b1000111011101110,
0b1110100010001000, 0b1110100010001110, 0b1110100011101000, 0b1110100011101110,
0b1110111010001000, 0b1110111010001110, 0b1110111011101000, 0b1110111011101110,
};
#elif defined(SK6812)
// SK6812 has different timing for '1' bits, which requires 4bit samples
static const uint16_t bitpatterns[16] = {
0b1000100010001000, 0b1000100010001100, 0b1000100011001000, 0b1000100011001100,
0b1000110010001000, 0b1000110010001100, 0b1000110011001000, 0b1000110011001100,
0b1100100010001000, 0b1100100010001100, 0b1100100011001000, 0b1100100011001100,
0b1100110010001000, 0b1100110010001100, 0b1100110011001000, 0b1100110011001100,
};
#endif
void ICACHE_FLASH_ATTR ws2812_push( uint8_t * buffer, uint16_t buffersize )
{
uint16_t place;
// while( !ws2812_dma_complete );
#ifdef WS2812_THREE_SAMPLE
uint8_t * bufferpl = (uint8_t*)&i2sBlock[0];
// buffersize += 3;
// if( buffersize * 4 + 1 > WS_BLOCKSIZE ) return;
int pl = 0;
int quit = 0;
//Once for each led.
for( place = 0; !quit; place++ )
{
uint8_t b;
b = buffer[pl++]; uint16_t c1a = bitpatterns[(b&0x0f)]; uint16_t c1b = bitpatterns[(b>>4)];
b = buffer[pl++]; uint16_t c2a = bitpatterns[(b&0x0f)]; uint16_t c2b = bitpatterns[(b>>4)];
b = buffer[pl++]; uint16_t c3a = bitpatterns[(b&0x0f)]; uint16_t c3b = bitpatterns[(b>>4)];
b = buffer[pl++]; uint16_t c4a = bitpatterns[(b&0x0f)]; uint16_t c4b = bitpatterns[(b>>4)];
if( pl >= buffersize )
{
quit = 1;
if( pl-1 >= buffersize ) c4a = c4b = 0;
if( pl-2 >= buffersize ) c3a = c3b = 0;
if( pl-3 >= buffersize ) c2a = c2b = 0;
if( pl-4 >= buffersize ) c1a = c1b = 0;
}
//Order of bits on wire: Reverse from how they appear here.
#define STEP1(x) (c##x##b >> 4 )
#define STEP2(x) ((c##x##b << 4 ) | ( c##x##a>>8 ))
#define STEP3(x) (c##x##a & 0xff )
*(bufferpl++) = STEP1(2);
*(bufferpl++) = STEP3(1);
*(bufferpl++) = STEP2(1);
*(bufferpl++) = STEP1(1);
*(bufferpl++) = STEP2(3);
*(bufferpl++) = STEP1(3);
*(bufferpl++) = STEP3(2);
*(bufferpl++) = STEP2(2);
*(bufferpl++) = STEP3(4);
*(bufferpl++) = STEP2(4);
*(bufferpl++) = STEP1(4);
*(bufferpl++) = STEP3(3);
}
while( bufferpl < &((uint8_t*)i2sBlock)[WS_BLOCKSIZE] ) *(bufferpl++) = 0;
#elif defined(WS2812_FOUR_SAMPLE) || defined(SK6812)
uint16_t * bufferpl = (uint16_t*)&i2sBlock[0];
if( buffersize * 4 > WS_BLOCKSIZE ) return;
for( place = 0; place < buffersize; place++ )
{
uint8_t btosend = buffer[place];
*(bufferpl++) = bitpatterns[(btosend&0x0f)];
*(bufferpl++) = bitpatterns[(btosend>>4)&0x0f];
}
#endif
#ifdef USE_2812_INTERRUPTS
uint16_t leftover = buffersize & 0x1f;
if( leftover ) leftover = 32 - leftover;
for( place = 0; place < leftover; place++ )
{
*(bufferpl++) = 0;
*(bufferpl++) = 0;
}
buffersize += leftover;
uint16_t sizeout_words = buffersize * 2;
i2sBufDescOut.owner = 1;
i2sBufDescOut.eof = 1;
i2sBufDescOut.sub_sof = 0;
i2sBufDescOut.datalen = sizeout_words*2; //Size (in bytes)
i2sBufDescOut.blocksize = sizeout_words*2; //Size (in bytes)
i2sBufDescOut.buf_ptr = (uint32_t)&i2sBlock[0];
i2sBufDescOut.unused = 0;
i2sBufDescOut.next_link_ptr=(uint32_t)&i2sBufDescZeroes; //At the end, just redirect the DMA to the zero buffer.
SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_STOP);
CLEAR_PERI_REG_MASK(SLC_RX_LINK,SLC_RXLINK_DESCADDR_MASK);
SET_PERI_REG_MASK(SLC_RX_LINK, ((uint32)&i2sBufDescOut) & SLC_RXLINK_DESCADDR_MASK);
SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_START);
#endif
}

View File

@ -0,0 +1,36 @@
//Copyright 2015 <>< Charles Lohr, See LICENSE file.
//WS2812 sender that abuses the I2S interface on the WS2812.
#ifndef _WS2812I2S_TEST
#define _WS2812I2S_TEST
//Stuff that should be for the header:
#include <c_types.h>
//Parameters for the I2S DMA behaviour
//#define I2SDMABUFCNT (2) //Number of buffers in the I2S circular buffer
//#define I2SDMABUFLEN (32*2) //Length of one buffer, in 32-bit words.
//NOTE: Blocksize MUST be divisible by 4. Cannot exceed 4092
//Each LED takes up 12 block bytes in WS2812_FOUR_SAMPLE
//Or 9 block bytes in WS2812_THREE_SAMPLE
#define WS_BLOCKSIZE 4000
//You can either have 3 or 4 samples per bit for WS2812s.
//3 sample can't go quite as fast as 4.
//3 sample uses more processing when updating than 4.
//4 takes up more RAM per LED than 3.
//3 has slightly more restrictve timing requirements.
//4 has more DMA load when running.
#define WS2812_THREE_SAMPLE
//#define WS2812_FOUR_SAMPLE
// timing for SK6812 LEDs, always uses 4bit samples
//#define SK6812
void ICACHE_FLASH_ATTR ws2812_init();
void ICACHE_FLASH_ATTR ws2812_push( uint8_t * buffer, uint16_t buffersize ); //Buffersize = Nr LEDs * 3
#endif

1
mopidy-control/Makefile Symbolic link
View File

@ -0,0 +1 @@
../Makefile

37
mopidy-control/README.md Normal file
View File

@ -0,0 +1,37 @@
This module required customized [mopidy-mqtt
extension](https://github.com/Informatic/mopidy-mqtt).
This module borrows some code from [esp8266ws2812i2s](https://github.com/cnlohr/esp8266ws2812i2s) project, which is licensed
under [MIT](https://github.com/cnlohr/esp82xx/blob/6053b2f478a2ecae867bef3f98fb265cf4a69a98/LICENSE)
This module borrows some code from
[ClickEncoder](https://github.com/0xPIT/encoder/blob/master/LICENSING.txt)
project.
// -----------------------------------------------------------------------------
//
// Copyright (c) 2010-2014, karl@pitrich.com
// Copyright by authors stated in the source code files
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// -----------------------------------------------------------------------------

View File

@ -0,0 +1,219 @@
// ----------------------------------------------------------------------------
// Rotary Encoder Driver with Acceleration
// Supports Click, DoubleClick, Long Click
//
// (c) 2010 karl@pitrich.com
// (c) 2014 karl@pitrich.com
//
// Timer-based rotary encoder logic by Peter Dannegger
// http://www.mikrocontroller.net/articles/Drehgeber
// ----------------------------------------------------------------------------
#include "ClickEncoder.h"
#include <SmingCore/SmingCore.h>
// ----------------------------------------------------------------------------
// Button configuration (values for 1ms timer service calls)
//
#define ENC_BUTTONINTERVAL 10 // check button every x milliseconds, also debouce time
#define ENC_DOUBLECLICKTIME 400 // second click within 600ms
#define ENC_HOLDTIME 1000 // report held button after 1.2s
// ----------------------------------------------------------------------------
// Acceleration configuration (for 1000Hz calls to ::service())
//
#define ENC_ACCEL_TOP 3072 // max. acceleration: *12 (val >> 8)
#define ENC_ACCEL_INC 25
#define ENC_ACCEL_DEC 2
// ----------------------------------------------------------------------------
#if ENC_DECODER != ENC_NORMAL
# ifdef ENC_HALFSTEP
// decoding table for hardware with flaky notch (half resolution)
const int8_t ClickEncoder::table[16] __attribute__((__progmem__)) = {
0, 0, -1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, -1, 0, 0
};
# else
// decoding table for normal hardware
const int8_t ClickEncoder::table[16] __attribute__((__progmem__)) = {
0, 1, -1, 0, -1, 0, 0, 1, 1, 0, 0, -1, 0, -1, 1, 0
};
# endif
#endif
// ----------------------------------------------------------------------------
ClickEncoder::ClickEncoder(uint8_t A, uint8_t B, uint8_t BTN, uint8_t stepsPerNotch, bool active)
: doubleClickEnabled(true), accelerationEnabled(true),
delta(0), last(0), acceleration(0),
button(Open), steps(stepsPerNotch),
pinA(A), pinB(B), pinBTN(BTN), pinsActive(active)
{
uint8_t configType = (pinsActive == false) ? INPUT_PULLUP : INPUT;
pinMode(pinA, configType);
pinMode(pinB, configType);
pinMode(pinBTN, configType);
if (digitalRead(pinA) == pinsActive) {
last = 3;
}
if (digitalRead(pinB) == pinsActive) {
last ^=1;
}
}
// ----------------------------------------------------------------------------
// call this every 1 millisecond via timer ISR
//
void ClickEncoder::service(void)
{
bool moved = false;
unsigned long now = millis();
if (accelerationEnabled) { // decelerate every tick
acceleration -= ENC_ACCEL_DEC;
if (acceleration & 0x8000) { // handle overflow of MSB is set
acceleration = 0;
}
}
#if ENC_DECODER == ENC_FLAKY
last = (last << 2) & 0x0F;
if (digitalRead(pinA) == pinsActive) {
last |= 2;
}
if (digitalRead(pinB) == pinsActive) {
last |= 1;
}
uint8_t tbl = pgm_read_byte(&table[last]);
if (tbl) {
delta += tbl;
moved = true;
}
#elif ENC_DECODER == ENC_NORMAL
int8_t curr = 0;
if (digitalRead(pinA) == pinsActive) {
curr = 3;
}
if (digitalRead(pinB) == pinsActive) {
curr ^= 1;
}
int8_t diff = last - curr;
if (diff & 1) { // bit 0 = step
last = curr;
delta += (diff & 2) - 1; // bit 1 = direction (+/-)
moved = true;
}
#else
# error "Error: define ENC_DECODER to ENC_NORMAL or ENC_FLAKY"
#endif
if (accelerationEnabled && moved) {
// increment accelerator if encoder has been moved
if (acceleration <= (ENC_ACCEL_TOP - ENC_ACCEL_INC)) {
acceleration += ENC_ACCEL_INC;
}
}
// handle button
//
#ifndef WITHOUT_BUTTON
static uint16_t keyDownTicks = 0;
static uint8_t doubleClickTicks = 0;
static unsigned long lastButtonCheck = 0;
if (pinBTN > 0 // check button only, if a pin has been provided
&& (now - lastButtonCheck) >= ENC_BUTTONINTERVAL) // checking button is sufficient every 10-30ms
{
lastButtonCheck = now;
if (digitalRead(pinBTN) == pinsActive) { // key is down
keyDownTicks++;
if (keyDownTicks > (ENC_HOLDTIME / ENC_BUTTONINTERVAL)) {
button = Held;
}
}
if (digitalRead(pinBTN) == !pinsActive) { // key is now up
if (keyDownTicks /*> ENC_BUTTONINTERVAL*/) {
if (button == Held) {
button = Released;
doubleClickTicks = 0;
}
else {
#define ENC_SINGLECLICKONLY 1
if (doubleClickTicks > ENC_SINGLECLICKONLY) { // prevent trigger in single click mode
if (doubleClickTicks < (ENC_DOUBLECLICKTIME / ENC_BUTTONINTERVAL)) {
button = DoubleClicked;
doubleClickTicks = 0;
}
}
else {
doubleClickTicks = (doubleClickEnabled) ? (ENC_DOUBLECLICKTIME / ENC_BUTTONINTERVAL) : ENC_SINGLECLICKONLY;
}
}
}
keyDownTicks = 0;
}
if (doubleClickTicks > 0) {
doubleClickTicks--;
if (--doubleClickTicks == 0) {
button = Clicked;
}
}
}
#endif // WITHOUT_BUTTON
}
// ----------------------------------------------------------------------------
int16_t ClickEncoder::getValue(void)
{
int16_t val;
val = delta;
if (steps == 2) delta = val & 1;
else if (steps == 4) delta = val & 3;
else delta = 0; // default to 1 step per notch
if (steps == 4) val >>= 2;
if (steps == 2) val >>= 1;
int16_t r = 0;
int16_t accel = ((accelerationEnabled) ? (acceleration >> 8) : 0);
if (val < 0) {
r -= 1 + accel;
}
else if (val > 0) {
r += 1 + accel;
}
return r;
}
// ----------------------------------------------------------------------------
#ifndef WITHOUT_BUTTON
ClickEncoder::Button ClickEncoder::getButton(void)
{
ClickEncoder::Button ret = button;
if (button != ClickEncoder::Held) {
button = ClickEncoder::Open; // reset
}
return ret;
}
#endif

View File

@ -0,0 +1,114 @@
// ----------------------------------------------------------------------------
// Rotary Encoder Driver with Acceleration
// Supports Click, DoubleClick, Long Click
//
// (c) 2010 karl@pitrich.com
// (c) 2014 karl@pitrich.com
//
// Timer-based rotary encoder logic by Peter Dannegger
// http://www.mikrocontroller.net/articles/Drehgeber
// ----------------------------------------------------------------------------
#ifndef __have__ClickEncoder_h__
#define __have__ClickEncoder_h__
// ----------------------------------------------------------------------------
#include <stdint.h>
// ----------------------------------------------------------------------------
#define ENC_NORMAL (1 << 1) // use Peter Danneger's decoder
#define ENC_FLAKY (1 << 2) // use Table-based decoder
// ----------------------------------------------------------------------------
#ifndef ENC_DECODER
# define ENC_DECODER ENC_NORMAL
#endif
#if ENC_DECODER == ENC_FLAKY
# ifndef ENC_HALFSTEP
# define ENC_HALFSTEP 1 // use table for half step per default
# endif
#endif
// ----------------------------------------------------------------------------
class ClickEncoder
{
public:
typedef enum Button_e {
Open = 0,
Closed,
Pressed,
Held,
Released,
Clicked,
DoubleClicked
} Button;
public:
ClickEncoder(uint8_t A, uint8_t B, uint8_t BTN = -1,
uint8_t stepsPerNotch = 1, bool active = false);
void service(void);
int16_t getValue(void);
#ifndef WITHOUT_BUTTON
public:
Button getButton(void);
#endif
#ifndef WITHOUT_BUTTON
public:
void setDoubleClickEnabled(const bool &d)
{
doubleClickEnabled = d;
}
const bool getDoubleClickEnabled()
{
return doubleClickEnabled;
}
#endif
public:
void setAccelerationEnabled(const bool &a)
{
accelerationEnabled = a;
if (accelerationEnabled == false) {
acceleration = 0;
}
}
const bool getAccelerationEnabled()
{
return accelerationEnabled;
}
private:
const uint8_t pinA;
const uint8_t pinB;
const uint8_t pinBTN;
const bool pinsActive;
volatile int16_t delta;
volatile int16_t last;
uint8_t steps;
volatile uint16_t acceleration;
#if ENC_DECODER != ENC_NORMAL
static const int8_t table[16];
#endif
#ifndef WITHOUT_BUTTON
volatile Button button;
bool doubleClickEnabled;
bool accelerationEnabled;
#endif
};
// ----------------------------------------------------------------------------
#endif // __have__ClickEncoder_h__

View File

@ -0,0 +1,154 @@
#include <user_config.h>
#include <SmingCore/SmingCore.h>
#include <algorithm>
#include <SpejsNode.h>
#define ENCA 14
#define ENCB 13
#define ENC_DECODER (1 << 2)
#include <ClickEncoder.h>
extern "C" {
#include "ws2812_i2s.h"
}
const int LEDS_CNT = 16;
const int CENTER_OFFSET = 11;
const int MAX_VAL = 100;
const int LED_MIN = 0;
const int LED_MAX = 16;
class EncoderEndpoint : public Endpoint {
private:
ClickEncoder encoder; //(ENCA, ENCB, 4, 4);
struct __attribute__((packed)) {
uint8_t g;
uint8_t r;
uint8_t b;
} leds[LEDS_CNT];
Timer animationTimer;
Timer delayedValueTimer;
Timer encTimer;
int delayedValue = 0;
int value = 0;
bool playing = false;
long long lastInteraction;
void publish(String key, String value) {
if (parent->mqtt.getConnectionState() == eTCS_Connected) {
parent->mqtt.publish(
String(TOPIC_PREFIX "mopidy/status/") +
key + String("/set"), value);
}
}
void animate() {
int oldval = value;
value += encoder.getValue() * 3;
value = constrain(value, 0, MAX_VAL);
if (value != oldval) {
lastInteraction = millis();
publish("volume", String(map(value, 0, MAX_VAL, 0, 100)));
//parent->mqtt.publish(TOPIC_PREFIX "mopidy/status/volume/set", String(map(value, 0, MAX_VAL, 0, 100)));
Serial.println(value);
}
int button = encoder.getButton();
if(button != 0) {
Serial.print("button: ");
Serial.println(button);
if (button == 5) {
publish("playing", playing ? "false" : "true");
}
}
for(int i = 0; i < LEDS_CNT; i++) {
WDT.alive();
int v = constrain(map(value, MAX_VAL * (LEDS_CNT-i-1) / LEDS_CNT, MAX_VAL * (LEDS_CNT-i) / LEDS_CNT, LED_MIN, LED_MAX), LED_MIN, LED_MAX);
int led_i = (i + CENTER_OFFSET) % LEDS_CNT;
if(playing) {
leds[led_i].g = v;
leds[led_i].r = 0;
leds[led_i].b = 0;
} else {
leds[led_i].g = 0;
leds[led_i].r = v;
leds[led_i].b = 0;
}
}
ws2812_push((uint8_t*) leds, sizeof(leds));
}
public:
EncoderEndpoint() : Endpoint("analog"), encoder(ENCA, ENCB, 4, 4) { }
void updateDelayedValue() {
Serial.println("delayed value xD");
value = delayedValue;
}
void bind(String _name, SpejsNode* _parent) {
Endpoint::bind(_name, _parent);
delayedValueTimer.initializeMs(1500, TimerDelegate(&EncoderEndpoint::updateDelayedValue, this));
animationTimer.initializeMs(30, TimerDelegate(&EncoderEndpoint::animate, this)).start();
ws2812_init();
pinMode(12, OUTPUT);
digitalWrite(12, LOW);
pinMode(2, OUTPUT);
digitalWrite(2, LOW);
encoder.setAccelerationEnabled(false);
encTimer.initializeMs(1, TimerDelegate(&ClickEncoder::service, &encoder)).start();
}
EndpointResult onValue(String property, String rvalue) {
Serial.print(property);
Serial.print(" = ");
Serial.println(value);
value = rvalue.toInt(); // map(rvalue.toInt(), 0, 100, 0, MAX_VAL);
return 200;
}
void onConnected() {
parent->mqtt.subscribe(TOPIC_PREFIX "mopidy/#");
}
void onMessage(String topic, String payload) {
Endpoint::onMessage(topic, payload);
Serial.println("status: got message");
Serial.printf("%s: %s\r\n", topic.c_str(), payload.c_str());
if (topic == TOPIC_PREFIX "mopidy/status/volume") {
delayedValue = payload.toInt(); //map(payload.toInt(), 0, 100, 0, MAX_VAL);
if(millis() - lastInteraction > 3000) {
updateDelayedValue();
} else {
delayedValueTimer.stop();
delayedValueTimer.start(false);
}
} else if (topic == TOPIC_PREFIX "mopidy/status/playing") {
playing = payload == "true";
}
}
};
SpejsNode node("encoder");
void init()
{
node.init();
node.registerEndpoint("encoder", new EncoderEndpoint());
}

View File

@ -0,0 +1,173 @@
/*
* Copyright (c) Espressif System 2010 - 2012
*
*/
#ifndef _PIN_MUX_H_
#define _PIN_MUX_H_
//Register Bits{{
#define BIT31 0x80000000
#define BIT30 0x40000000
#define BIT29 0x20000000
#define BIT28 0x10000000
#define BIT27 0x08000000
#define BIT26 0x04000000
#define BIT25 0x02000000
#define BIT24 0x01000000
#define BIT23 0x00800000
#define BIT22 0x00400000
#define BIT21 0x00200000
#define BIT20 0x00100000
#define BIT19 0x00080000
#define BIT18 0x00040000
#define BIT17 0x00020000
#define BIT16 0x00010000
#define BIT15 0x00008000
#define BIT14 0x00004000
#define BIT13 0x00002000
#define BIT12 0x00001000
#define BIT11 0x00000800
#define BIT10 0x00000400
#define BIT9 0x00000200
#define BIT8 0x00000100
#define BIT7 0x00000080
#define BIT6 0x00000040
#define BIT5 0x00000020
#define BIT4 0x00000010
#define BIT3 0x00000008
#define BIT2 0x00000004
#define BIT1 0x00000002
#define BIT0 0x00000001
//}}
#define PERIPHS_IO_MUX 0x60000800
#define PERIPHS_IO_MUX_FUNC 0x13
#define PERIPHS_IO_MUX_FUNC_S 4
#define PERIPHS_IO_MUX_PULLUP BIT7
#define PERIPHS_IO_MUX_PULLDWN BIT6
#define PERIPHS_IO_MUX_SLEEP_PULLUP BIT3
#define PERIPHS_IO_MUX_SLEEP_PULLDWN BIT2
#define PERIPHS_IO_MUX_SLEEP_OE BIT1
#define PERIPHS_IO_MUX_OE BIT0
#define PERIPHS_IO_MUX_CONF_U (PERIPHS_IO_MUX + 0x00)
#define SPI0_CLK_EQU_SYS_CLK BIT8
#define SPI1_CLK_EQU_SYS_CLK BIT9
#define PERIPHS_IO_MUX_MTDI_U (PERIPHS_IO_MUX + 0x04)
#define FUNC_MTDI 0
#define FUNC_I2SI_DATA 1
#define FUNC_HSPIQ_MISO 2
#define FUNC_GPIO12 3
#define FUNC_UART0_DTR 4
#define PERIPHS_IO_MUX_MTCK_U (PERIPHS_IO_MUX + 0x08)
#define FUNC_MTCK 0
#define FUNC_I2SI_BCK 1
#define FUNC_HSPID_MOSI 2
#define FUNC_GPIO13 3
#define FUNC_UART0_CTS 4
#define PERIPHS_IO_MUX_MTMS_U (PERIPHS_IO_MUX + 0x0C)
#define FUNC_MTMS 0
#define FUNC_I2SI_WS 1
#define FUNC_HSPI_CLK 2
#define FUNC_GPIO14 3
#define FUNC_UART0_DSR 4
#define PERIPHS_IO_MUX_MTDO_U (PERIPHS_IO_MUX + 0x10)
#define FUNC_MTDO 0
#define FUNC_I2SO_BCK 1
#define FUNC_HSPI_CS0 2
#define FUNC_GPIO15 3
#define FUNC_U0RTS 4
#define FUNC_UART0_RTS 4
#define PERIPHS_IO_MUX_U0RXD_U (PERIPHS_IO_MUX + 0x14)
#define FUNC_U0RXD 0
#define FUNC_I2SO_DATA 1
#define FUNC_GPIO3 3
#define FUNC_CLK_XTAL_BK 4
#define PERIPHS_IO_MUX_U0TXD_U (PERIPHS_IO_MUX + 0x18)
#define FUNC_U0TXD 0
#define FUNC_SPICS1 1
#define FUNC_GPIO1 3
#define FUNC_CLK_RTC_BK 4
#define PERIPHS_IO_MUX_SD_CLK_U (PERIPHS_IO_MUX + 0x1c)
#define FUNC_SDCLK 0
#define FUNC_SPICLK 1
#define FUNC_GPIO6 3
#define UART1_CTS 4
#define PERIPHS_IO_MUX_SD_DATA0_U (PERIPHS_IO_MUX + 0x20)
#define FUNC_SDDATA0 0
#define FUNC_SPIQ_MISO 1
#define FUNC_GPIO7 3
#define FUNC_U1TXD 4
#define FUNC_UART1_TXD 4
#define PERIPHS_IO_MUX_SD_DATA1_U (PERIPHS_IO_MUX + 0x24)
#define FUNC_SDDATA1 0
#define FUNC_SPID_MOSI 1
#define FUNC_GPIO8 3
#define FUNC_U1RXD 4
#define FUNC_UART1_RXD 4
#define PERIPHS_IO_MUX_SD_DATA2_U (PERIPHS_IO_MUX + 0x28)
#define FUNC_SDDATA2 0
#define FUNC_SPIHD 1
#define FUNC_GPIO9 3
#define UFNC_HSPIHD 4
#define PERIPHS_IO_MUX_SD_DATA3_U (PERIPHS_IO_MUX + 0x2c)
#define FUNC_SDDATA3 0
#define FUNC_SPIWP 1
#define FUNC_GPIO10 3
#define FUNC_HSPIWP 4
#define PERIPHS_IO_MUX_SD_CMD_U (PERIPHS_IO_MUX + 0x30)
#define FUNC_SDCMD 0
#define FUNC_SPICS0 1
#define FUNC_GPIO11 3
#define U1RTS 4
#define UART1_RTS 4
#define PERIPHS_IO_MUX_GPIO0_U (PERIPHS_IO_MUX + 0x34)
#define FUNC_GPIO0 0
#define FUNC_SPICS2 1
#define FUNC_CLK_OUT 4
#define PERIPHS_IO_MUX_GPIO2_U (PERIPHS_IO_MUX + 0x38)
#define FUNC_GPIO2 0
#define FUNC_I2SO_WS 1
#define FUNC_U1TXD_BK 2
#define FUNC_UART1_TXD_BK 2
#define FUNC_U0TXD_BK 4
#define FUNC_UART0_TXD_BK 4
#define PERIPHS_IO_MUX_GPIO4_U (PERIPHS_IO_MUX + 0x3C)
#define FUNC_GPIO4 0
#define FUNC_CLK_XTAL 1
#define PERIPHS_IO_MUX_GPIO5_U (PERIPHS_IO_MUX + 0x40)
#define FUNC_GPIO5 0
#define FUNC_CLK_RTC 1
#define PIN_PULLUP_DIS(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME, PERIPHS_IO_MUX_PULLUP)
#define PIN_PULLUP_EN(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME, PERIPHS_IO_MUX_PULLUP)
//XXX THIS LOOKS WRONG.
#undef PIN_FUNC_SELECT
#define PIN_FUNC_SELECT(PIN_NAME, FUNC) do { \
CLEAR_PERI_REG_MASK(PIN_NAME, (PERIPHS_IO_MUX_FUNC<<PERIPHS_IO_MUX_FUNC_S)); \
SET_PERI_REG_MASK(PIN_NAME, (((FUNC&BIT2)<<2)|(FUNC&0x3))<<PERIPHS_IO_MUX_FUNC_S); \
} while (0)
#endif //_PIN_MUX_H_

View File

@ -0,0 +1,281 @@
//Generated at 2012-10-23 19:55:03
/*
* Copyright (c) 2010 - 2011 Espressif System
*
*/
#ifndef SLC_REGISTER_H_
#define SLC_REGISTER_H_
#define REG_SLC_BASE 0x60000B00
//version value:32'h091700
#define SLC_CONF0 (REG_SLC_BASE + 0x0)
#ifndef ESP_MAC_5
#define SLC_MODE 0x00000003
#define SLC_MODE_S 12
#endif
#define SLC_DATA_BURST_EN (BIT(9))
#define SLC_DSCR_BURST_EN (BIT(8))
#define SLC_RX_NO_RESTART_CLR (BIT(7))
#define SLC_RX_AUTO_WRBACK (BIT(6))
#define SLC_RX_LOOP_TEST (BIT(5))
#define SLC_TX_LOOP_TEST (BIT(4))
#define SLC_AHBM_RST (BIT(3))
#define SLC_AHBM_FIFO_RST (BIT(2))
#define SLC_RXLINK_RST (BIT(1))
#define SLC_TXLINK_RST (BIT(0))
#define SLC_INT_RAW (REG_SLC_BASE + 0x4)
#define SLC_TX_DSCR_EMPTY_INT_RAW (BIT(21))
#define SLC_RX_DSCR_ERR_INT_RAW (BIT(20))
#define SLC_TX_DSCR_ERR_INT_RAW (BIT(19))
#define SLC_TOHOST_INT_RAW (BIT(18))
#define SLC_RX_EOF_INT_RAW (BIT(17))
#define SLC_RX_DONE_INT_RAW (BIT(16))
#define SLC_TX_EOF_INT_RAW (BIT(15))
#define SLC_TX_DONE_INT_RAW (BIT(14))
#define SLC_TOKEN1_1TO0_INT_RAW (BIT(13))
#define SLC_TOKEN0_1TO0_INT_RAW (BIT(12))
#define SLC_TX_OVF_INT_RAW (BIT(11))
#define SLC_RX_UDF_INT_RAW (BIT(10))
#define SLC_TX_START_INT_RAW (BIT(9))
#define SLC_RX_START_INT_RAW (BIT(8))
#define SLC_FRHOST_BIT7_INT_RAW (BIT(7))
#define SLC_FRHOST_BIT6_INT_RAW (BIT(6))
#define SLC_FRHOST_BIT5_INT_RAW (BIT(5))
#define SLC_FRHOST_BIT4_INT_RAW (BIT(4))
#define SLC_FRHOST_BIT3_INT_RAW (BIT(3))
#define SLC_FRHOST_BIT2_INT_RAW (BIT(2))
#define SLC_FRHOST_BIT1_INT_RAW (BIT(1))
#define SLC_FRHOST_BIT0_INT_RAW (BIT(0))
#define SLC_INT_STATUS (REG_SLC_BASE + 0x8)
#define SLC_TX_DSCR_EMPTY_INT_ST (BIT(21))
#define SLC_RX_DSCR_ERR_INT_ST (BIT(20))
#define SLC_TX_DSCR_ERR_INT_ST (BIT(19))
#define SLC_TOHOST_INT_ST (BIT(18))
#define SLC_RX_EOF_INT_ST (BIT(17))
#define SLC_RX_DONE_INT_ST (BIT(16))
#define SLC_TX_EOF_INT_ST (BIT(15))
#define SLC_TX_DONE_INT_ST (BIT(14))
#define SLC_TOKEN1_1TO0_INT_ST (BIT(13))
#define SLC_TOKEN0_1TO0_INT_ST (BIT(12))
#define SLC_TX_OVF_INT_ST (BIT(11))
#define SLC_RX_UDF_INT_ST (BIT(10))
#define SLC_TX_START_INT_ST (BIT(9))
#define SLC_RX_START_INT_ST (BIT(8))
#define SLC_FRHOST_BIT7_INT_ST (BIT(7))
#define SLC_FRHOST_BIT6_INT_ST (BIT(6))
#define SLC_FRHOST_BIT5_INT_ST (BIT(5))
#define SLC_FRHOST_BIT4_INT_ST (BIT(4))
#define SLC_FRHOST_BIT3_INT_ST (BIT(3))
#define SLC_FRHOST_BIT2_INT_ST (BIT(2))
#define SLC_FRHOST_BIT1_INT_ST (BIT(1))
#define SLC_FRHOST_BIT0_INT_ST (BIT(0))
#define SLC_INT_ENA (REG_SLC_BASE + 0xC)
#define SLC_TX_DSCR_EMPTY_INT_ENA (BIT(21))
#define SLC_RX_DSCR_ERR_INT_ENA (BIT(20))
#define SLC_TX_DSCR_ERR_INT_ENA (BIT(19))
#define SLC_TOHOST_INT_ENA (BIT(18))
#define SLC_RX_EOF_INT_ENA (BIT(17))
#define SLC_RX_DONE_INT_ENA (BIT(16))
#define SLC_TX_EOF_INT_ENA (BIT(15))
#define SLC_TX_DONE_INT_ENA (BIT(14))
#define SLC_TOKEN1_1TO0_INT_ENA (BIT(13))
#define SLC_TOKEN0_1TO0_INT_ENA (BIT(12))
#define SLC_TX_OVF_INT_ENA (BIT(11))
#define SLC_RX_UDF_INT_ENA (BIT(10))
#define SLC_TX_START_INT_ENA (BIT(9))
#define SLC_RX_START_INT_ENA (BIT(8))
#define SLC_FRHOST_BIT7_INT_ENA (BIT(7))
#define SLC_FRHOST_BIT6_INT_ENA (BIT(6))
#define SLC_FRHOST_BIT5_INT_ENA (BIT(5))
#define SLC_FRHOST_BIT4_INT_ENA (BIT(4))
#define SLC_FRHOST_BIT3_INT_ENA (BIT(3))
#define SLC_FRHOST_BIT2_INT_ENA (BIT(2))
#define SLC_FRHOST_BIT1_INT_ENA (BIT(1))
#define SLC_FRHOST_BIT0_INT_ENA (BIT(0))
#define SLC_FRHOST_BIT_INT_ENA_ALL 0xff
#define SLC_INT_CLR (REG_SLC_BASE + 0x10)
#define SLC_TX_DSCR_EMPTY_INT_CLR (BIT(21))
#define SLC_RX_DSCR_ERR_INT_CLR (BIT(20))
#define SLC_TX_DSCR_ERR_INT_CLR (BIT(19))
#define SLC_TOHOST_INT_CLR (BIT(18))
#define SLC_RX_EOF_INT_CLR (BIT(17))
#define SLC_RX_DONE_INT_CLR (BIT(16))
#define SLC_TX_EOF_INT_CLR (BIT(15))
#define SLC_TX_DONE_INT_CLR (BIT(14))
#define SLC_TOKEN1_1TO0_INT_CLR (BIT(13))
#define SLC_TOKEN0_1TO0_INT_CLR (BIT(12))
#define SLC_TX_OVF_INT_CLR (BIT(11))
#define SLC_RX_UDF_INT_CLR (BIT(10))
#define SLC_TX_START_INT_CLR (BIT(9))
#define SLC_RX_START_INT_CLR (BIT(8))
#define SLC_FRHOST_BIT7_INT_CLR (BIT(7))
#define SLC_FRHOST_BIT6_INT_CLR (BIT(6))
#define SLC_FRHOST_BIT5_INT_CLR (BIT(5))
#define SLC_FRHOST_BIT4_INT_CLR (BIT(4))
#define SLC_FRHOST_BIT3_INT_CLR (BIT(3))
#define SLC_FRHOST_BIT2_INT_CLR (BIT(2))
#define SLC_FRHOST_BIT1_INT_CLR (BIT(1))
#define SLC_FRHOST_BIT0_INT_CLR (BIT(0))
#define SLC_RX_STATUS (REG_SLC_BASE + 0x14)
#define SLC_RX_EMPTY (BIT(1))
#define SLC_RX_FULL (BIT(0))
#define SLC_RX_FIFO_PUSH (REG_SLC_BASE + 0x18)
#define SLC_RXFIFO_PUSH (BIT(16))
#define SLC_RXFIFO_WDATA 0x000001FF
#define SLC_RXFIFO_WDATA_S 0
#define SLC_TX_STATUS (REG_SLC_BASE + 0x1C)
#define SLC_TX_EMPTY (BIT(1))
#define SLC_TX_FULL (BIT(0))
#define SLC_TX_FIFO_POP (REG_SLC_BASE + 0x20)
#define SLC_TXFIFO_POP (BIT(16))
#define SLC_TXFIFO_RDATA 0x000007FF
#define SLC_TXFIFO_RDATA_S 0
#define SLC_RX_LINK (REG_SLC_BASE + 0x24)
#define SLC_RXLINK_PARK (BIT(31))
#define SLC_RXLINK_RESTART (BIT(30))
#define SLC_RXLINK_START (BIT(29))
#define SLC_RXLINK_STOP (BIT(28))
#define SLC_RXLINK_DESCADDR_MASK 0x000FFFFF
#define SLC_RXLINK_ADDR_S 0
#define SLC_TX_LINK (REG_SLC_BASE + 0x28)
#define SLC_TXLINK_PARK (BIT(31))
#define SLC_TXLINK_RESTART (BIT(30))
#define SLC_TXLINK_START (BIT(29))
#define SLC_TXLINK_STOP (BIT(28))
#define SLC_TXLINK_DESCADDR_MASK 0x000FFFFF
#define SLC_TXLINK_ADDR_S 0
#define SLC_INTVEC_TOHOST (REG_SLC_BASE + 0x2C)
#define SLC_TOHOST_INTVEC 0x000000FF
#define SLC_TOHOST_INTVEC_S 0
#define SLC_TOKEN0 (REG_SLC_BASE + 0x30)
#define SLC_TOKEN0_MASK 0x00000FFF
#define SLC_TOKEN0_S 16
#define SLC_TOKEN0_LOCAL_INC_MORE (BIT(14))
#define SLC_TOKEN0_LOCAL_INC (BIT(13))
#define SLC_TOKEN0_LOCAL_WR (BIT(12))
#define SLC_TOKEN0_LOCAL_WDATA_MASK 0x00000FFF
#define SLC_TOKEN0_LOCAL_WDATA_S 0
#define SLC_TOKEN1 (REG_SLC_BASE + 0x34)
#define SLC_TOKEN1_MASK 0x00000FFF
#define SLC_TOKEN1_S 16
#define SLC_TOKEN1_LOCAL_INC_MORE (BIT(14))
#define SLC_TOKEN1_LOCAL_INC (BIT(13))
#define SLC_TOKEN1_LOCAL_WR (BIT(12))
#define SLC_TOKEN1_LOCAL_WDATA 0x00000FFF
#define SLC_TOKEN1_LOCAL_WDATA_S 0
#define SLC_CONF1 (REG_SLC_BASE + 0x38)
#define SLC_STATE0 (REG_SLC_BASE + 0x3C)
#define SLC_STATE1 (REG_SLC_BASE + 0x40)
#define SLC_BRIDGE_CONF (REG_SLC_BASE + 0x44)
#ifndef ESP_MAC_5
#define SLC_TX_PUSH_IDLE_NUM 0x0000FFFF
#define SLC_TX_PUSH_IDLE_NUM_S 16
#define SLC_TX_DUMMY_MODE (BIT(12))
#endif
#define SLC_FIFO_MAP_ENA 0x0000000F
#define SLC_FIFO_MAP_ENA_S 8
#define SLC_TXEOF_ENA 0x0000003F
#define SLC_TXEOF_ENA_S 0
#define SLC_RX_EOF_DES_ADDR (REG_SLC_BASE + 0x48)
#define SLC_TX_EOF_DES_ADDR (REG_SLC_BASE + 0x4C)
#define SLC_FROM_HOST_LAST_DESC SLC_TX_EOF_DES_ADDR
#define SLC_TO_HOST_LAST_DESC SLC_RX_EOF_DES_ADDR
#define SLC_RX_EOF_BFR_DES_ADDR (REG_SLC_BASE + 0x50)
#define SLC_AHB_TEST (REG_SLC_BASE + 0x54)
#define SLC_AHB_TESTADDR 0x00000003
#define SLC_AHB_TESTADDR_S 4
#define SLC_AHB_TESTMODE 0x00000007
#define SLC_AHB_TESTMODE_S 0
#define SLC_SDIO_ST (REG_SLC_BASE + 0x58)
#define SLC_BUS_ST 0x00000007
#define SLC_BUS_ST_S 12
#define SLC_SDIO_WAKEUP (BIT(8))
#define SLC_FUNC_ST 0x0000000F
#define SLC_FUNC_ST_S 4
#define SLC_CMD_ST 0x00000007
#define SLC_CMD_ST_S 0
#define SLC_RX_DSCR_CONF (REG_SLC_BASE + 0x5C)
#ifdef ESP_MAC_5
#define SLC_INFOR_NO_REPLACE (BIT(9))
#define SLC_TOKEN_NO_REPLACE (BIT(8))
#define SLC_POP_IDLE_CNT 0x000000FF
#else
#define SLC_RX_FILL_EN (BIT(20))
#define SLC_RX_EOF_MODE (BIT(19))
#define SLC_RX_FILL_MODE (BIT(18))
#define SLC_INFOR_NO_REPLACE (BIT(17))
#define SLC_TOKEN_NO_REPLACE (BIT(16))
#define SLC_POP_IDLE_CNT 0x0000FFFF
#endif
#define SLC_POP_IDLE_CNT_S 0
#define SLC_TXLINK_DSCR (REG_SLC_BASE + 0x60)
#define SLC_TXLINK_DSCR_BF0 (REG_SLC_BASE + 0x64)
#define SLC_TXLINK_DSCR_BF1 (REG_SLC_BASE + 0x68)
#define SLC_RXLINK_DSCR (REG_SLC_BASE + 0x6C)
#define SLC_RXLINK_DSCR_BF0 (REG_SLC_BASE + 0x70)
#define SLC_RXLINK_DSCR_BF1 (REG_SLC_BASE + 0x74)
#define SLC_DATE (REG_SLC_BASE + 0x78)
#define SLC_ID (REG_SLC_BASE + 0x7C)
#define SLC_HOST_CONF_W0 (REG_SLC_BASE + 0x80 + 0x14)
#define SLC_HOST_CONF_W1 (REG_SLC_BASE + 0x80 + 0x18)
#define SLC_HOST_CONF_W2 (REG_SLC_BASE + 0x80 + 0x20)
#define SLC_HOST_CONF_W3 (REG_SLC_BASE + 0x80 + 0x24)
#define SLC_HOST_CONF_W4 (REG_SLC_BASE + 0x80 + 0x28)
#define SLC_HOST_INTR_ST (REG_SLC_BASE + 0x80 + 0x1c)
#define SLC_HOST_INTR_CLR (REG_SLC_BASE + 0x80 + 0x30)
#define SLC_HOST_INTR_SOF_BIT (BIT(12))
#define SLC_HOST_INTR_ENA (REG_SLC_BASE + 0x80 + 0x34)
#define SLC_RX_NEW_PACKET_INT_ENA (BIT23)
#define SLC_HOST_TOHOST_BIT0_INT_ENA (BIT0)
#define SLC_HOST_CONF_W5 (REG_SLC_BASE + 0x80 + 0x3C)
#define SLC_HOST_INTR_RAW (REG_SLC_BASE + 0x80 + 0x8)
#define SLC_HOST_INTR_ENA_BIT (BIT(23))
//[15:12]: 0x3ff9xxxx -- 0b01 from_host
// 0x3ffaxxxx -- 0b10 general
// 0x3ffbxxxx -- 0b11 to_host
#define SLC_DATA_ADDR_CLEAR_MASK (~(0xf<<12))
#define SLC_FROM_HOST_ADDR_MASK (0x1<<12)
#define SLC_TO_HOST_ADDR_MASK (0x3<<12)
#define SLC_SET_FROM_HOST_ADDR_MASK(v) do { \
(v) &= SLC_DATA_ADDR_CLEAR_MASK; \
(v) |= SLC_FROM_HOST_ADDR_MASK; \
} while(0);
#define SLC_SET_TO_HOST_ADDR_MASK(v) do { \
(v) &= SLC_DATA_ADDR_CLEAR_MASK; \
(v) |= SLC_TO_HOST_ADDR_MASK; \
} while(0);
#define SLC_TX_DESC_DEBUG_REG 0x3ff0002c //[15:0] set to 0xcccc
#endif // SLC_REGISTER_H_INCLUDED

View File

@ -0,0 +1,542 @@
/******************************************************************************
* Copyright 2013-2015 Espressif Systems
* 2015 <>< Charles Lohr
*
* FileName: i2s_freertos.c
*
* Description: I2S output routines for a FreeRTOS system. Uses DMA and a queue
* to abstract away the nitty-gritty details.
*
* Modification history:
* 2015/06/01, v1.0 File created.
* 2015/07/23, Switch to making it a WS2812 output device.
*******************************************************************************
Notes:
This is pretty badly hacked together from the MP3 example.
I spent some time trying to strip it down to avoid a lot of the TX_ stuff.
That seems to work.
Major suggestions that I couldn't figure out:
* Use interrupts to disable DMA, so it isn't running nonstop.
* Use interrupts to flag when new data can be sent.
When I try using interrupts, it seems to work for a bit but things fall apart
rather quickly and the engine just refuses to send anymore until reboot.
The way it works right now is to keep the DMA running forever and just update
the data in the buffer so it continues sending the frame.
Extra copyright info:
Actually not much of this file is Copyright Espressif, comparativly little
mostly just the stuff to make the I2S bus go.
*******************************************************************************/
#include "eagle_soc.h"
#include "slc_register.h"
// #include "esp82xxutil.h"
#include <c_types.h>
#include "ws2812_i2s.h"
//#include "user_interface.h"
#include "pin_mux_register.h"
//Creates an I2S SR of 93,750 Hz, or 3 MHz Bitclock (.333us/sample)
// 1600000000L/(div*bestbck)
//It is likely you could speed this up a little.
#ifdef WS2812_THREE_SAMPLE
#define WS_I2S_BCK 21 //Seems to work as low as 18, but is shakey at 1.
#define WS_I2S_DIV 3
#elif defined( WS2812_FOUR_SAMPLE ) || defined(SK6812)
#define WS_I2S_BCK 16 //Seems to work as low as 13, shoddy at 12.
#define WS_I2S_DIV 3
#else
#error You need to either define WS2812_THREE_SAMPLE, WS2812_FOUR_SAMPLE or SK6812
#endif
#ifndef i2c_bbpll
#define i2c_bbpll 0x67
#define i2c_bbpll_en_audio_clock_out 4
#define i2c_bbpll_en_audio_clock_out_msb 7
#define i2c_bbpll_en_audio_clock_out_lsb 7
#define i2c_bbpll_hostid 4
#define i2c_writeReg_Mask(block, host_id, reg_add, Msb, Lsb, indata) rom_i2c_writeReg_Mask(block, host_id, reg_add, Msb, Lsb, indata)
#define i2c_readReg_Mask(block, host_id, reg_add, Msb, Lsb) rom_i2c_readReg_Mask(block, host_id, reg_add, Msb, Lsb)
#define i2c_writeReg_Mask_def(block, reg_add, indata) \
i2c_writeReg_Mask(block, block##_hostid, reg_add, reg_add##_msb, reg_add##_lsb, indata)
#define i2c_readReg_Mask_def(block, reg_add) \
i2c_readReg_Mask(block, block##_hostid, reg_add, reg_add##_msb, reg_add##_lsb)
#endif
#ifndef ETS_SLC_INUM
#define ETS_SLC_INUM 1
#endif
//From i2s_reg.h
#define DR_REG_I2S_BASE (0x60000e00)
#define I2STXFIFO (DR_REG_I2S_BASE + 0x0000)
#define I2SRXFIFO (DR_REG_I2S_BASE + 0x0004)
#define I2SCONF (DR_REG_I2S_BASE + 0x0008)
#define I2S_BCK_DIV_NUM 0x0000003F
#define I2S_BCK_DIV_NUM_S 22
#define I2S_CLKM_DIV_NUM 0x0000003F
#define I2S_CLKM_DIV_NUM_S 16
#define I2S_BITS_MOD 0x0000000F
#define I2S_BITS_MOD_S 12
#define I2S_RECE_MSB_SHIFT (BIT(11))
#define I2S_TRANS_MSB_SHIFT (BIT(10))
#define I2S_I2S_RX_START (BIT(9))
#define I2S_I2S_TX_START (BIT(8))
#define I2S_MSB_RIGHT (BIT(7))
#define I2S_RIGHT_FIRST (BIT(6))
#define I2S_RECE_SLAVE_MOD (BIT(5))
#define I2S_TRANS_SLAVE_MOD (BIT(4))
#define I2S_I2S_RX_FIFO_RESET (BIT(3))
#define I2S_I2S_TX_FIFO_RESET (BIT(2))
#define I2S_I2S_RX_RESET (BIT(1))
#define I2S_I2S_TX_RESET (BIT(0))
#define I2S_I2S_RESET_MASK 0xf
#define I2SINT_RAW (DR_REG_I2S_BASE + 0x000c)
#define I2S_I2S_TX_REMPTY_INT_RAW (BIT(5))
#define I2S_I2S_TX_WFULL_INT_RAW (BIT(4))
#define I2S_I2S_RX_REMPTY_INT_RAW (BIT(3))
#define I2S_I2S_RX_WFULL_INT_RAW (BIT(2))
#define I2S_I2S_TX_PUT_DATA_INT_RAW (BIT(1))
#define I2S_I2S_RX_TAKE_DATA_INT_RAW (BIT(0))
#define I2SINT_ST (DR_REG_I2S_BASE + 0x0010)
#define I2S_I2S_TX_REMPTY_INT_ST (BIT(5))
#define I2S_I2S_TX_WFULL_INT_ST (BIT(4))
#define I2S_I2S_RX_REMPTY_INT_ST (BIT(3))
#define I2S_I2S_RX_WFULL_INT_ST (BIT(2))
#define I2S_I2S_TX_PUT_DATA_INT_ST (BIT(1))
#define I2S_I2S_RX_TAKE_DATA_INT_ST (BIT(0))
#define I2SINT_ENA (DR_REG_I2S_BASE + 0x0014)
#define I2S_I2S_TX_REMPTY_INT_ENA (BIT(5))
#define I2S_I2S_TX_WFULL_INT_ENA (BIT(4))
#define I2S_I2S_RX_REMPTY_INT_ENA (BIT(3))
#define I2S_I2S_RX_WFULL_INT_ENA (BIT(2))
#define I2S_I2S_TX_PUT_DATA_INT_ENA (BIT(1))
#define I2S_I2S_RX_TAKE_DATA_INT_ENA (BIT(0))
#define I2SINT_CLR (DR_REG_I2S_BASE + 0x0018)
#define I2S_I2S_TX_REMPTY_INT_CLR (BIT(5))
#define I2S_I2S_TX_WFULL_INT_CLR (BIT(4))
#define I2S_I2S_RX_REMPTY_INT_CLR (BIT(3))
#define I2S_I2S_RX_WFULL_INT_CLR (BIT(2))
#define I2S_I2S_PUT_DATA_INT_CLR (BIT(1))
#define I2S_I2S_TAKE_DATA_INT_CLR (BIT(0))
#define I2STIMING (DR_REG_I2S_BASE + 0x001c)
#define I2S_TRANS_BCK_IN_INV (BIT(22))
#define I2S_RECE_DSYNC_SW (BIT(21))
#define I2S_TRANS_DSYNC_SW (BIT(20))
#define I2S_RECE_BCK_OUT_DELAY 0x00000003
#define I2S_RECE_BCK_OUT_DELAY_S 18
#define I2S_RECE_WS_OUT_DELAY 0x00000003
#define I2S_RECE_WS_OUT_DELAY_S 16
#define I2S_TRANS_SD_OUT_DELAY 0x00000003
#define I2S_TRANS_SD_OUT_DELAY_S 14
#define I2S_TRANS_WS_OUT_DELAY 0x00000003
#define I2S_TRANS_WS_OUT_DELAY_S 12
#define I2S_TRANS_BCK_OUT_DELAY 0x00000003
#define I2S_TRANS_BCK_OUT_DELAY_S 10
#define I2S_RECE_SD_IN_DELAY 0x00000003
#define I2S_RECE_SD_IN_DELAY_S 8
#define I2S_RECE_WS_IN_DELAY 0x00000003
#define I2S_RECE_WS_IN_DELAY_S 6
#define I2S_RECE_BCK_IN_DELAY 0x00000003
#define I2S_RECE_BCK_IN_DELAY_S 4
#define I2S_TRANS_WS_IN_DELAY 0x00000003
#define I2S_TRANS_WS_IN_DELAY_S 2
#define I2S_TRANS_BCK_IN_DELAY 0x00000003
#define I2S_TRANS_BCK_IN_DELAY_S 0
#define I2S_FIFO_CONF (DR_REG_I2S_BASE + 0x0020)
#define I2S_I2S_RX_FIFO_MOD 0x00000007
#define I2S_I2S_RX_FIFO_MOD_S 16
#define I2S_I2S_TX_FIFO_MOD 0x00000007
#define I2S_I2S_TX_FIFO_MOD_S 13
#define I2S_I2S_DSCR_EN (BIT(12))
#define I2S_I2S_TX_DATA_NUM 0x0000003F
#define I2S_I2S_TX_DATA_NUM_S 6
#define I2S_I2S_RX_DATA_NUM 0x0000003F
#define I2S_I2S_RX_DATA_NUM_S 0
#define I2SRXEOF_NUM (DR_REG_I2S_BASE + 0x0024)
#define I2S_I2S_RX_EOF_NUM 0xFFFFFFFF
#define I2S_I2S_RX_EOF_NUM_S 0
#define I2SCONF_SIGLE_DATA (DR_REG_I2S_BASE + 0x0028)
#define I2S_I2S_SIGLE_DATA 0xFFFFFFFF
#define I2S_I2S_SIGLE_DATA_S 0
#define I2SCONF_CHAN (DR_REG_I2S_BASE + 0x002c)
#define I2S_RX_CHAN_MOD 0x00000003
#define I2S_RX_CHAN_MOD_S 3
#define I2S_TX_CHAN_MOD 0x00000007
#define I2S_TX_CHAN_MOD_S 0
//From sdio_slv.h
struct sdio_queue
{
uint32 blocksize:12;
uint32 datalen:12;
uint32 unused:5;
uint32 sub_sof:1;
uint32 eof:1;
uint32 owner:1;
uint32 buf_ptr;
uint32 next_link_ptr;
};
struct sdio_slave_status_element
{
uint32 wr_busy:1;
uint32 rd_empty :1;
uint32 comm_cnt :3;
uint32 intr_no :3;
uint32 rx_length:16;
uint32 res:8;
};
union sdio_slave_status
{
struct sdio_slave_status_element elm_value;
uint32 word_value;
};
#define RX_AVAILIBLE 2
#define TX_AVAILIBLE 1
#define INIT_STAGE 0
#define SDIO_QUEUE_LEN 8
#define MOSI 0
#define MISO 1
#define SDIO_DATA_ERROR 6
#define SLC_INTEREST_EVENT (SLC_TX_EOF_INT_ENA | SLC_RX_EOF_INT_ENA | SLC_RX_UDF_INT_ENA | SLC_TX_DSCR_ERR_INT_ENA)
#define TRIG_TOHOST_INT() SET_PERI_REG_MASK(SLC_INTVEC_TOHOST , BIT0);\
CLEAR_PERI_REG_MASK(SLC_INTVEC_TOHOST , BIT0)
///Rest of program...
//Pointer to the I2S DMA buffer data
//static unsigned int i2sBuf[I2SDMABUFCNT][I2SDMABUFLEN];
//I2S DMA buffer descriptors
//static struct sdio_queue i2sBufDesc[I2SDMABUFCNT];
static struct sdio_queue i2sBufDescOut;
static struct sdio_queue i2sBufDescZeroes;
static unsigned int i2sZeroes[32];
static unsigned int i2sBlock[WS_BLOCKSIZE/4];
//Queue which contains empty DMA buffers
//DMA underrun counter
#ifdef USE_2812_INTERRUPTS
volatile uint8_t ws2812_dma_complete;
//This routine is called as soon as the DMA routine has something to tell us. All we
//handle here is the RX_EOF_INT status, which indicate the DMA has sent a buffer whose
//descriptor has the 'EOF' field set to 1.
LOCAL void slc_isr(void) {
//clear all intr flags
// WRITE_PERI_REG(SLC_INT_CLR, 0xffffffff);//slc_intr_status);
// ws2812_dma_complete = 1;
//This is a little wacky. This function actually gets called twice.
//Once for the initial transfer, but by the time we tell it to stop
//The other zero transfer's already begun.
// SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_STOP);
}
#endif
//Initialize I2S subsystem for DMA circular buffer use
void ICACHE_FLASH_ATTR ws2812_init()
{
int x, y;
//Reset DMA
SET_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST);//|SLC_TXLINK_RST);
CLEAR_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST);//|SLC_TXLINK_RST);
//Clear DMA int flags
SET_PERI_REG_MASK(SLC_INT_CLR, 0xffffffff);
CLEAR_PERI_REG_MASK(SLC_INT_CLR, 0xffffffff);
//Enable and configure DMA
CLEAR_PERI_REG_MASK(SLC_CONF0, (SLC_MODE<<SLC_MODE_S));
SET_PERI_REG_MASK(SLC_CONF0,(1<<SLC_MODE_S));
SET_PERI_REG_MASK(SLC_RX_DSCR_CONF,SLC_INFOR_NO_REPLACE|SLC_TOKEN_NO_REPLACE);
CLEAR_PERI_REG_MASK(SLC_RX_DSCR_CONF, SLC_RX_FILL_EN|SLC_RX_EOF_MODE | SLC_RX_FILL_MODE);
i2sBufDescOut.owner = 1;
i2sBufDescOut.eof = 1;
i2sBufDescOut.sub_sof = 0;
i2sBufDescOut.datalen = WS_BLOCKSIZE; //Size (in bytes)
i2sBufDescOut.blocksize = WS_BLOCKSIZE; //Size (in bytes)
i2sBufDescOut.buf_ptr=(uint32_t)&i2sBlock[0];
i2sBufDescOut.unused=0;
i2sBufDescOut.next_link_ptr=(uint32_t)&i2sBufDescZeroes; //At the end, just redirect the DMA to the zero buffer.
i2sBufDescZeroes.owner = 1;
i2sBufDescZeroes.eof = 1;
i2sBufDescZeroes.sub_sof = 0;
i2sBufDescZeroes.datalen = 32;
i2sBufDescZeroes.blocksize = 32;
i2sBufDescZeroes.buf_ptr=(uint32_t)&i2sZeroes[0];
i2sBufDescZeroes.unused=0;
i2sBufDescZeroes.next_link_ptr=(uint32_t)&i2sBufDescOut;
for( x = 0; x < 32; x++ )
{
i2sZeroes[x] = 0x00;
}
for( x = 0; x < WS_BLOCKSIZE/4; x++ )
{
i2sBlock[x] = 0x00000000;//(x == 0 || x == 999)?0xaa:0x00;
/* uint16_t * tt = (uint16_t*)&i2sBlock[x];
(*(tt+0)) = 0xA0F0;
(*(tt+1)) = 0xC0E0;*/
}
// CLEAR_PERI_REG_MASK(SLC_TX_LINK,SLC_TXLINK_DESCADDR_MASK);
// SET_PERI_REG_MASK(SLC_TX_LINK, ((uint32)&i2sBufDescZeroes) & SLC_TXLINK_DESCADDR_MASK); //any random desc is OK, we don't use TX but it needs something valid
CLEAR_PERI_REG_MASK(SLC_RX_LINK,SLC_RXLINK_DESCADDR_MASK);
SET_PERI_REG_MASK(SLC_RX_LINK, ((uint32)&i2sBufDescOut) & SLC_RXLINK_DESCADDR_MASK);
#ifdef USE_2812_INTERRUPTS
//Attach the DMA interrupt
ets_isr_attach(ETS_SLC_INUM, slc_isr);
//Enable DMA operation intr
WRITE_PERI_REG(SLC_INT_ENA, SLC_RX_EOF_INT_ENA);
//clear any interrupt flags that are set
WRITE_PERI_REG(SLC_INT_CLR, 0xffffffff);
///enable DMA intr in cpu
ets_isr_unmask(1<<ETS_SLC_INUM);
#endif
//Start transmission
// SET_PERI_REG_MASK(SLC_TX_LINK, SLC_TXLINK_START);
SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_START);
//----
//Init pins to i2s functions
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_I2SO_DATA);
// PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_I2SO_WS);
// PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_I2SO_BCK);
//Enable clock to i2s subsystem
i2c_writeReg_Mask_def(i2c_bbpll, i2c_bbpll_en_audio_clock_out, 1);
//Reset I2S subsystem
CLEAR_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK);
SET_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK);
CLEAR_PERI_REG_MASK(I2SCONF,I2S_I2S_RESET_MASK);
//Select 16bits per channel (FIFO_MOD=0), no DMA access (FIFO only)
CLEAR_PERI_REG_MASK(I2S_FIFO_CONF, I2S_I2S_DSCR_EN|(I2S_I2S_RX_FIFO_MOD<<I2S_I2S_RX_FIFO_MOD_S)|(I2S_I2S_TX_FIFO_MOD<<I2S_I2S_TX_FIFO_MOD_S));
//Enable DMA in i2s subsystem
SET_PERI_REG_MASK(I2S_FIFO_CONF, I2S_I2S_DSCR_EN);
//tx/rx binaureal
// CLEAR_PERI_REG_MASK(I2SCONF_CHAN, (I2S_TX_CHAN_MOD<<I2S_TX_CHAN_MOD_S)|(I2S_RX_CHAN_MOD<<I2S_RX_CHAN_MOD_S));
#ifdef USE_2812_INTERRUPTS
//Clear int
SET_PERI_REG_MASK(I2SINT_CLR,
I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR);
CLEAR_PERI_REG_MASK(I2SINT_CLR,
I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR);
#endif
//trans master&rece slave,MSB shift,right_first,msb right
CLEAR_PERI_REG_MASK(I2SCONF, I2S_TRANS_SLAVE_MOD|
(I2S_BITS_MOD<<I2S_BITS_MOD_S)|
(I2S_BCK_DIV_NUM <<I2S_BCK_DIV_NUM_S)|
(I2S_CLKM_DIV_NUM<<I2S_CLKM_DIV_NUM_S));
SET_PERI_REG_MASK(I2SCONF, I2S_RIGHT_FIRST|I2S_MSB_RIGHT|I2S_RECE_SLAVE_MOD|
I2S_RECE_MSB_SHIFT|I2S_TRANS_MSB_SHIFT|
(((WS_I2S_BCK)&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)|
(((WS_I2S_DIV)&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S));
//No idea if ints are needed...
//clear int
SET_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR);
CLEAR_PERI_REG_MASK(I2SINT_CLR, I2S_I2S_RX_WFULL_INT_CLR|I2S_I2S_PUT_DATA_INT_CLR|I2S_I2S_TAKE_DATA_INT_CLR);
//enable int
SET_PERI_REG_MASK(I2SINT_ENA, I2S_I2S_RX_REMPTY_INT_ENA|I2S_I2S_RX_TAKE_DATA_INT_ENA);
//Start transmission
SET_PERI_REG_MASK(I2SCONF,I2S_I2S_TX_START);
}
//All functions below this line are Public Domain 2015 Charles Lohr.
//this code may be used by anyone in any way without restriction or limitation.
#ifdef WS2812_THREE_SAMPLE
static const uint16_t bitpatterns[16] = {
0b100100100100, 0b100100100110, 0b100100110100, 0b100100110110,
0b100110100100, 0b100110100110, 0b100110110100, 0b100110110110,
0b110100100100, 0b110100100110, 0b110100110100, 0b110100110110,
0b110110100100, 0b110110100110, 0b110110110100, 0b110110110110,
};
#elif defined(WS2812_FOUR_SAMPLE)
//Tricky, send out WS2812 bits with coded pulses, one nibble, then the other.
static const uint16_t bitpatterns[16] = {
0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110,
0b1000111010001000, 0b1000111010001110, 0b1000111011101000, 0b1000111011101110,
0b1110100010001000, 0b1110100010001110, 0b1110100011101000, 0b1110100011101110,
0b1110111010001000, 0b1110111010001110, 0b1110111011101000, 0b1110111011101110,
};
#elif defined(SK6812)
// SK6812 has different timing for '1' bits, which requires 4bit samples
static const uint16_t bitpatterns[16] = {
0b1000100010001000, 0b1000100010001100, 0b1000100011001000, 0b1000100011001100,
0b1000110010001000, 0b1000110010001100, 0b1000110011001000, 0b1000110011001100,
0b1100100010001000, 0b1100100010001100, 0b1100100011001000, 0b1100100011001100,
0b1100110010001000, 0b1100110010001100, 0b1100110011001000, 0b1100110011001100,
};
#endif
void ICACHE_FLASH_ATTR ws2812_push( uint8_t * buffer, uint16_t buffersize )
{
uint16_t place;
// while( !ws2812_dma_complete );
#ifdef WS2812_THREE_SAMPLE
uint8_t * bufferpl = (uint8_t*)&i2sBlock[0];
// buffersize += 3;
// if( buffersize * 4 + 1 > WS_BLOCKSIZE ) return;
int pl = 0;
int quit = 0;
//Once for each led.
for( place = 0; !quit; place++ )
{
uint8_t b;
b = buffer[pl++]; uint16_t c1a = bitpatterns[(b&0x0f)]; uint16_t c1b = bitpatterns[(b>>4)];
b = buffer[pl++]; uint16_t c2a = bitpatterns[(b&0x0f)]; uint16_t c2b = bitpatterns[(b>>4)];
b = buffer[pl++]; uint16_t c3a = bitpatterns[(b&0x0f)]; uint16_t c3b = bitpatterns[(b>>4)];
b = buffer[pl++]; uint16_t c4a = bitpatterns[(b&0x0f)]; uint16_t c4b = bitpatterns[(b>>4)];
if( pl >= buffersize )
{
quit = 1;
if( pl-1 >= buffersize ) c4a = c4b = 0;
if( pl-2 >= buffersize ) c3a = c3b = 0;
if( pl-3 >= buffersize ) c2a = c2b = 0;
if( pl-4 >= buffersize ) c1a = c1b = 0;
}
//Order of bits on wire: Reverse from how they appear here.
#define STEP1(x) (c##x##b >> 4 )
#define STEP2(x) ((c##x##b << 4 ) | ( c##x##a>>8 ))
#define STEP3(x) (c##x##a & 0xff )
*(bufferpl++) = STEP1(2);
*(bufferpl++) = STEP3(1);
*(bufferpl++) = STEP2(1);
*(bufferpl++) = STEP1(1);
*(bufferpl++) = STEP2(3);
*(bufferpl++) = STEP1(3);
*(bufferpl++) = STEP3(2);
*(bufferpl++) = STEP2(2);
*(bufferpl++) = STEP3(4);
*(bufferpl++) = STEP2(4);
*(bufferpl++) = STEP1(4);
*(bufferpl++) = STEP3(3);
}
while( bufferpl < &((uint8_t*)i2sBlock)[WS_BLOCKSIZE] ) *(bufferpl++) = 0;
#elif defined(WS2812_FOUR_SAMPLE) || defined(SK6812)
uint16_t * bufferpl = (uint16_t*)&i2sBlock[0];
if( buffersize * 4 > WS_BLOCKSIZE ) return;
for( place = 0; place < buffersize; place++ )
{
uint8_t btosend = buffer[place];
*(bufferpl++) = bitpatterns[(btosend&0x0f)];
*(bufferpl++) = bitpatterns[(btosend>>4)&0x0f];
}
#endif
#ifdef USE_2812_INTERRUPTS
uint16_t leftover = buffersize & 0x1f;
if( leftover ) leftover = 32 - leftover;
for( place = 0; place < leftover; place++ )
{
*(bufferpl++) = 0;
*(bufferpl++) = 0;
}
buffersize += leftover;
uint16_t sizeout_words = buffersize * 2;
i2sBufDescOut.owner = 1;
i2sBufDescOut.eof = 1;
i2sBufDescOut.sub_sof = 0;
i2sBufDescOut.datalen = sizeout_words*2; //Size (in bytes)
i2sBufDescOut.blocksize = sizeout_words*2; //Size (in bytes)
i2sBufDescOut.buf_ptr = (uint32_t)&i2sBlock[0];
i2sBufDescOut.unused = 0;
i2sBufDescOut.next_link_ptr=(uint32_t)&i2sBufDescZeroes; //At the end, just redirect the DMA to the zero buffer.
SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_STOP);
CLEAR_PERI_REG_MASK(SLC_RX_LINK,SLC_RXLINK_DESCADDR_MASK);
SET_PERI_REG_MASK(SLC_RX_LINK, ((uint32)&i2sBufDescOut) & SLC_RXLINK_DESCADDR_MASK);
SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_START);
#endif
}

View File

@ -0,0 +1,36 @@
//Copyright 2015 <>< Charles Lohr, See LICENSE file.
//WS2812 sender that abuses the I2S interface on the WS2812.
#ifndef _WS2812I2S_TEST
#define _WS2812I2S_TEST
//Stuff that should be for the header:
#include <c_types.h>
//Parameters for the I2S DMA behaviour
//#define I2SDMABUFCNT (2) //Number of buffers in the I2S circular buffer
//#define I2SDMABUFLEN (32*2) //Length of one buffer, in 32-bit words.
//NOTE: Blocksize MUST be divisible by 4. Cannot exceed 4092
//Each LED takes up 12 block bytes in WS2812_FOUR_SAMPLE
//Or 9 block bytes in WS2812_THREE_SAMPLE
#define WS_BLOCKSIZE 4000
//You can either have 3 or 4 samples per bit for WS2812s.
//3 sample can't go quite as fast as 4.
//3 sample uses more processing when updating than 4.
//4 takes up more RAM per LED than 3.
//3 has slightly more restrictve timing requirements.
//4 has more DMA load when running.
#define WS2812_THREE_SAMPLE
//#define WS2812_FOUR_SAMPLE
// timing for SK6812 LEDs, always uses 4bit samples
//#define SK6812
void ICACHE_FLASH_ATTR ws2812_init();
void ICACHE_FLASH_ATTR ws2812_push( uint8_t * buffer, uint16_t buffersize ); //Buffersize = Nr LEDs * 3
#endif

1
projection-screen/Makefile Symbolic link
View File

@ -0,0 +1 @@
../Makefile

View File

@ -0,0 +1 @@
COM_SPEED = 9600

View File

@ -0,0 +1,115 @@
#include <SpejsNode.h>
#include <Libraries/RCSwitch/RCSwitch.h>
class ProjectionScreenEndpoint: public Endpoint {
private:
RCSwitch rc;
int codeStop = 0b000110011110110100001000;
int codeUp = 0b000110011110110100000010;
int codeDown = 0b000110011110110100000100;
public:
ProjectionScreenEndpoint() : Endpoint("rcswitch") {
rc.enableTransmit(5); // pin GPIO5 - transmit
rc.setRepeatTransmit(5);
}
EndpointResult onValue(String property, String value) {
if (property == "down") {
if (value == "1" || value == "true") {
rc.send(codeDown, 24);
delay(200);
rc.send(codeDown, 24);
notify("down", "true");
} else {
rc.send(codeUp, 24);
delay(200);
rc.send(codeUp, 24);
notify("down", "false");
}
return 200;
}
return 400;
}
};
class PanasonicProjectorEndpoint: public Endpoint {
private:
const char STARTBYTE = 0x02;
const char ENDBYTE = 0x03;
void send(String message) {
Serial.write(STARTBYTE);
Serial.print(message);
Serial.write(ENDBYTE);
}
enum {
WAITFORSTART,
WAITFOREND,
} serialState = WAITFORSTART;
String buf;
void serialCallback(Stream& stream, char arrivedChar, unsigned short availableCharsCount) {
while(stream.available()) {
char byte = stream.read();
if (serialState == WAITFORSTART) {
if (byte == STARTBYTE) {
serialState = WAITFOREND;
buf = "";
} else {
debugf("panasonic: Invalid byte: %d", byte);
}
} else {
if (byte == ENDBYTE) {
serialState = WAITFORSTART;
processMessage(buf);
} else {
buf += byte;
}
}
}
}
void processMessage(String& msg) {
debugf("got message: %s", msg.c_str());
if (msg == "PON") {
notify("power", "true");
} else if (msg == "POF") {
notify("power", "false");
} else if (msg.startsWith("IIS:")) {
notify("source", msg.substring(4));
}
}
public:
PanasonicProjectorEndpoint() : Endpoint("display") { }
void bind(String _name, SpejsNode* _parent) {
Endpoint::bind(_name, _parent);
Serial.setCallback(StreamDataReceivedDelegate(&PanasonicProjectorEndpoint::serialCallback, this));
}
EndpointResult onValue(String property, String value) {
if (property == "power") {
send(value == "true" ? "PON" : "POF");
return 200;
} else if (property == "source") {
send("IIS:" + value);
return 200;
}
return 400;
}
};
SpejsNode node("projection-screen");
void init() {
node.statusLED.config(2, LOW);
node.init();
Serial.begin(9600);
node.registerEndpoint("screen", new ProjectionScreenEndpoint());
node.registerEndpoint("projector", new PanasonicProjectorEndpoint());
}

View File

@ -0,0 +1,43 @@
unsigned char default_certificate[] = {
0x30, 0x82, 0x01, 0xd7, 0x30, 0x82, 0x01, 0x40, 0x02, 0x09, 0x00, 0x97,
0xdc, 0x5c, 0xc5, 0x3c, 0x5e, 0xee, 0x26, 0x30, 0x0d, 0x06, 0x09, 0x2a,
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x34,
0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x29, 0x61,
0x78, 0x54, 0x4c, 0x53, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74,
0x20, 0x44, 0x6f, 0x64, 0x67, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69,
0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f,
0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x39,
0x31, 0x30, 0x32, 0x33, 0x30, 0x35, 0x34, 0x34, 0x5a, 0x17, 0x0d, 0x33,
0x30, 0x30, 0x35, 0x32, 0x30, 0x32, 0x33, 0x30, 0x35, 0x34, 0x34, 0x5a,
0x30, 0x2c, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c,
0x0d, 0x61, 0x78, 0x54, 0x4c, 0x53, 0x20, 0x50, 0x72, 0x6f, 0x6a, 0x65,
0x63, 0x74, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x30, 0x81,
0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02,
0x81, 0x81, 0x00, 0xf0, 0x80, 0x5d, 0x8f, 0x2e, 0x02, 0xac, 0x68, 0xa2,
0xe1, 0xf2, 0x44, 0x4e, 0xd4, 0xbe, 0x1a, 0xb4, 0x05, 0x3a, 0xf3, 0xfb,
0xfc, 0xee, 0x24, 0xee, 0x7c, 0xc1, 0xed, 0xb9, 0xb7, 0xb5, 0x72, 0xfc,
0x15, 0x5f, 0xa1, 0x67, 0xa4, 0xff, 0x29, 0x7d, 0x55, 0x3b, 0xcd, 0xb4,
0x5e, 0xc2, 0xde, 0xce, 0x8b, 0x54, 0x82, 0xd4, 0x9b, 0xf9, 0x98, 0xbf,
0x17, 0x79, 0x7e, 0x04, 0xaa, 0xfa, 0x66, 0xbd, 0x0b, 0x1e, 0xb1, 0x89,
0xf6, 0x1a, 0x5b, 0x75, 0x7d, 0xd0, 0x16, 0x0d, 0xf1, 0x68, 0x54, 0xb5,
0x22, 0xb7, 0xf3, 0x36, 0x38, 0x76, 0xa8, 0x8f, 0x6b, 0x81, 0xac, 0xf7,
0x39, 0xcd, 0x01, 0x8a, 0x40, 0xf8, 0xcd, 0xc5, 0x23, 0xdb, 0x8f, 0x9f,
0xca, 0xec, 0xe0, 0xa8, 0xf2, 0x6e, 0xa6, 0x4f, 0xc8, 0x71, 0x31, 0xc0,
0x1f, 0x65, 0x78, 0x41, 0xc8, 0x9b, 0x35, 0xbe, 0x49, 0xf3, 0x37, 0x02,
0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x6c,
0xe7, 0xf5, 0x72, 0x81, 0x06, 0x15, 0xea, 0x1a, 0xcc, 0x85, 0x7f, 0x01,
0x6e, 0x02, 0xe0, 0x35, 0x80, 0xf9, 0x92, 0xd9, 0x49, 0x9d, 0x8f, 0x6b,
0x04, 0x69, 0x68, 0x3b, 0x09, 0x93, 0xc0, 0x5c, 0x19, 0x01, 0xd7, 0x8a,
0xa8, 0x6e, 0x76, 0x98, 0x6c, 0xac, 0xc1, 0x74, 0xd0, 0xb7, 0x05, 0x08,
0x28, 0x05, 0xe4, 0x38, 0xa4, 0x1d, 0x6b, 0x13, 0xed, 0x38, 0x34, 0x79,
0xd8, 0x41, 0x48, 0x0f, 0x0d, 0x5b, 0x2c, 0xd9, 0xd2, 0x5a, 0xaa, 0x8d,
0xe0, 0x61, 0xfa, 0xa5, 0x3f, 0x53, 0xc4, 0x21, 0x83, 0x4d, 0x5c, 0x4f,
0x11, 0xe5, 0x25, 0x1c, 0xd1, 0x9a, 0x03, 0x4c, 0x42, 0x08, 0xed, 0x44,
0xdf, 0x6b, 0x17, 0x85, 0xd2, 0x99, 0xf1, 0x9d, 0xdf, 0xde, 0xd2, 0x40,
0x67, 0xf3, 0x03, 0x20, 0xed, 0xaa, 0xc2, 0x00, 0xfe, 0xdd, 0x73, 0x22,
0x1b, 0x67, 0x19, 0x38, 0x50, 0x49, 0xd4
};
unsigned int default_certificate_len = 475;

View File

@ -0,0 +1,54 @@
unsigned char default_private_key[] = {
0x30, 0x82, 0x02, 0x5d, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xf0,
0x80, 0x5d, 0x8f, 0x2e, 0x02, 0xac, 0x68, 0xa2, 0xe1, 0xf2, 0x44, 0x4e,
0xd4, 0xbe, 0x1a, 0xb4, 0x05, 0x3a, 0xf3, 0xfb, 0xfc, 0xee, 0x24, 0xee,
0x7c, 0xc1, 0xed, 0xb9, 0xb7, 0xb5, 0x72, 0xfc, 0x15, 0x5f, 0xa1, 0x67,
0xa4, 0xff, 0x29, 0x7d, 0x55, 0x3b, 0xcd, 0xb4, 0x5e, 0xc2, 0xde, 0xce,
0x8b, 0x54, 0x82, 0xd4, 0x9b, 0xf9, 0x98, 0xbf, 0x17, 0x79, 0x7e, 0x04,
0xaa, 0xfa, 0x66, 0xbd, 0x0b, 0x1e, 0xb1, 0x89, 0xf6, 0x1a, 0x5b, 0x75,
0x7d, 0xd0, 0x16, 0x0d, 0xf1, 0x68, 0x54, 0xb5, 0x22, 0xb7, 0xf3, 0x36,
0x38, 0x76, 0xa8, 0x8f, 0x6b, 0x81, 0xac, 0xf7, 0x39, 0xcd, 0x01, 0x8a,
0x40, 0xf8, 0xcd, 0xc5, 0x23, 0xdb, 0x8f, 0x9f, 0xca, 0xec, 0xe0, 0xa8,
0xf2, 0x6e, 0xa6, 0x4f, 0xc8, 0x71, 0x31, 0xc0, 0x1f, 0x65, 0x78, 0x41,
0xc8, 0x9b, 0x35, 0xbe, 0x49, 0xf3, 0x37, 0x02, 0x03, 0x01, 0x00, 0x01,
0x02, 0x81, 0x80, 0x3b, 0x1d, 0x82, 0x61, 0xc8, 0x50, 0x75, 0xea, 0x7e,
0x67, 0x05, 0x72, 0xce, 0xe1, 0xb2, 0x1c, 0xc4, 0x35, 0x28, 0xe9, 0x81,
0xfe, 0x08, 0xd7, 0x61, 0x1b, 0x9f, 0x5b, 0x7c, 0xb3, 0xf0, 0x50, 0xe4,
0x2f, 0xa8, 0xc2, 0xf6, 0xc3, 0xf2, 0xc8, 0x52, 0xfb, 0x59, 0x68, 0xd5,
0xb6, 0x19, 0x36, 0x45, 0x14, 0xb0, 0x60, 0x3c, 0x3c, 0x5e, 0x9c, 0xb2,
0x13, 0xe6, 0x14, 0x18, 0xb7, 0xa2, 0x36, 0x96, 0xa5, 0xa8, 0xc0, 0x40,
0x95, 0xa4, 0x7d, 0xb1, 0xaf, 0x30, 0xda, 0x4f, 0x29, 0x00, 0x88, 0xac,
0x8d, 0xb6, 0x59, 0x06, 0x55, 0x2a, 0xac, 0x7d, 0x85, 0xa5, 0x93, 0x9a,
0x7f, 0xf9, 0x9c, 0xb3, 0xa4, 0xea, 0x20, 0x14, 0xa3, 0xe8, 0xba, 0x58,
0x87, 0x49, 0x07, 0x87, 0x35, 0x27, 0x41, 0x20, 0xa5, 0x60, 0xfc, 0xa5,
0x48, 0xe7, 0x2d, 0x9d, 0x32, 0x53, 0x27, 0xaf, 0x61, 0x75, 0xe1, 0x02,
0x41, 0x00, 0xff, 0xa8, 0x05, 0xdc, 0xd0, 0xd2, 0x03, 0x26, 0xb4, 0x68,
0x7b, 0x37, 0x80, 0x12, 0xfd, 0xa6, 0x62, 0x1b, 0x79, 0x66, 0x9e, 0x69,
0xf7, 0xb5, 0x4a, 0xbb, 0xde, 0xd4, 0xd6, 0x55, 0xf2, 0x4f, 0x78, 0x73,
0xed, 0x0d, 0xf0, 0xb0, 0x35, 0xa6, 0xdf, 0x4d, 0x73, 0xab, 0x2b, 0x25,
0x1c, 0x65, 0xb8, 0x66, 0x15, 0x8f, 0x0b, 0x63, 0x38, 0xbb, 0x33, 0x11,
0x92, 0x64, 0x64, 0x84, 0xba, 0x47, 0x02, 0x41, 0x00, 0xf0, 0xd3, 0x20,
0x9e, 0x8a, 0xfe, 0x38, 0x2d, 0x13, 0x63, 0x72, 0x5f, 0x53, 0x20, 0xc5,
0x03, 0xc5, 0xd7, 0x07, 0xc6, 0x48, 0xfb, 0x06, 0x42, 0x0a, 0x60, 0x8a,
0x96, 0xe8, 0x56, 0x8b, 0x0d, 0x24, 0x19, 0x33, 0xe8, 0x67, 0xbc, 0x8d,
0xb3, 0xb7, 0x94, 0xaa, 0xa2, 0x9d, 0xbf, 0xde, 0x9a, 0x8a, 0x48, 0x07,
0xfb, 0x27, 0xb3, 0xfb, 0xb0, 0x3a, 0x15, 0xa1, 0xe3, 0x07, 0x97, 0x87,
0x91, 0x02, 0x41, 0x00, 0xb5, 0xee, 0xae, 0x6d, 0x5b, 0xb5, 0x78, 0x44,
0x9c, 0xf2, 0x15, 0x6d, 0x83, 0x99, 0x00, 0x24, 0xdd, 0x80, 0x4b, 0xbe,
0x79, 0x51, 0x53, 0xd4, 0x11, 0xe0, 0xec, 0x4c, 0x6e, 0x53, 0x2f, 0x62,
0xda, 0x87, 0x34, 0xd5, 0x4c, 0xc9, 0x39, 0x05, 0x0d, 0xb8, 0x22, 0x6e,
0x56, 0xff, 0xcb, 0xdb, 0x9f, 0x84, 0x16, 0x27, 0x7b, 0xa5, 0x1a, 0x84,
0x2d, 0x6d, 0x7d, 0xce, 0x2f, 0xb2, 0x3c, 0x95, 0x02, 0x40, 0x04, 0x17,
0xf2, 0xa3, 0xff, 0x44, 0xd6, 0xfb, 0x9d, 0x2a, 0xc1, 0x94, 0xf1, 0x3a,
0xcb, 0x5e, 0x87, 0x0c, 0x62, 0xab, 0x72, 0x2e, 0x22, 0x2b, 0x19, 0x36,
0x0e, 0xe5, 0x05, 0xca, 0x02, 0xcf, 0x14, 0x60, 0x01, 0x4b, 0xe0, 0x07,
0x8a, 0x79, 0x15, 0x93, 0xc7, 0x5a, 0xc0, 0x47, 0xb4, 0xa6, 0xf7, 0xd6,
0xc5, 0x9b, 0xf5, 0x4e, 0xcf, 0xe6, 0x6c, 0xf6, 0x55, 0x2c, 0x20, 0xc2,
0xe8, 0xa1, 0x02, 0x41, 0x00, 0xff, 0x01, 0xf8, 0xa8, 0x50, 0x52, 0x80,
0x18, 0xdc, 0xdd, 0x97, 0x06, 0x1e, 0xe7, 0x2a, 0x44, 0xb0, 0xe3, 0x98,
0x1c, 0x54, 0x49, 0xd1, 0x19, 0x2a, 0x52, 0xca, 0xe3, 0x3d, 0x58, 0xcd,
0xf8, 0x61, 0xf9, 0x0c, 0x3b, 0x17, 0x42, 0xef, 0x8f, 0x55, 0x85, 0x34,
0x2f, 0x04, 0xba, 0x32, 0x57, 0x2f, 0xdf, 0xf9, 0xa3, 0x81, 0x75, 0xd9,
0xe5, 0x76, 0xda, 0x22, 0xb3, 0x34, 0x48, 0x4c, 0x9c
};
unsigned int default_private_key_len = 609;

View File

@ -0,0 +1,45 @@
#ifndef __USER_CONFIG_H__
#define __USER_CONFIG_H__
#ifdef __cplusplus
extern "C" {
#endif
// UART config
#define SERIAL_BAUD_RATE 9600
// ESP SDK config
#define LWIP_OPEN_SRC
#define USE_US_TIMER
// Default types
#define __CORRECT_ISO_CPP_STDLIB_H_PROTO
#include <limits.h>
#include <stdint.h>
// Override c_types.h include and remove buggy espconn
#define _C_TYPES_H_
#define _NO_ESPCON_
// Updated, compatible version of c_types.h
// Just removed types declared in <stdint.h>
#include <espinc/c_types_compatible.h>
// System API declarations
#include <esp_systemapi.h>
// C++ Support
#include <esp_cplusplus.h>
// Extended string conversion for compatibility
#include <stringconversion.h>
// Network base API
#include <espinc/lwip_includes.h>
// Beta boards
#define BOARD_ESP01
#ifdef __cplusplus
}
#endif
#endif

1
temperature/Makefile Symbolic link
View File

@ -0,0 +1 @@
../Makefile

View File

@ -0,0 +1,9 @@
#include <SpejsNode.h>
#include <endpoints/DHTEndpoint.h>
SpejsNode node("ambient");
void init() {
node.init();
node.registerEndpoint("environment", new DHTEndpoint(2, 10000, DHT22));
}