mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-19 23:22:16 +03:00
Initial SPI Slave implementation and examples (#2234)
* Initial SPI Slave implementation and examples * Update style and info
This commit is contained in:
parent
2364ad4dd0
commit
4217e49b54
118
libraries/SPISlave/examples/SPISlave_Master/SPISlave_Master.ino
Normal file
118
libraries/SPISlave/examples/SPISlave_Master/SPISlave_Master.ino
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
SPI Master Demo Sketch
|
||||||
|
Connect the SPI Master device to the following pins on the esp8266:
|
||||||
|
|
||||||
|
GPIO NodeMCU Name | Uno
|
||||||
|
===================================
|
||||||
|
15 D8 SS | D10
|
||||||
|
13 D7 MOSI | D11
|
||||||
|
12 D6 MISO | D12
|
||||||
|
14 D5 SCK | D13
|
||||||
|
|
||||||
|
Note: If the ESP is booting at a moment when the SPI Master has the Select line HIGH (deselected)
|
||||||
|
the ESP8266 WILL FAIL to boot!
|
||||||
|
See SPISlave_SafeMaster example for possible workaround
|
||||||
|
|
||||||
|
*/
|
||||||
|
#include <SPI.h>
|
||||||
|
|
||||||
|
class ESPMaster
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint8_t _ss_pin;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ESPMaster(uint8_t pin):_ss_pin(pin) {}
|
||||||
|
void begin()
|
||||||
|
{
|
||||||
|
pinMode(_ss_pin, OUTPUT);
|
||||||
|
digitalWrite(_ss_pin, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t readStatus()
|
||||||
|
{
|
||||||
|
digitalWrite(_ss_pin, LOW);
|
||||||
|
SPI.transfer(0x04);
|
||||||
|
uint32_t status = (SPI.transfer(0) | ((uint32_t)(SPI.transfer(0)) << 8) | ((uint32_t)(SPI.transfer(0)) << 16) | ((uint32_t)(SPI.transfer(0)) << 24));
|
||||||
|
digitalWrite(_ss_pin, HIGH);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeStatus(uint32_t status)
|
||||||
|
{
|
||||||
|
digitalWrite(_ss_pin, LOW);
|
||||||
|
SPI.transfer(0x01);
|
||||||
|
SPI.transfer(status & 0xFF);
|
||||||
|
SPI.transfer((status >> 8) & 0xFF);
|
||||||
|
SPI.transfer((status >> 16) & 0xFF);
|
||||||
|
SPI.transfer((status >> 24) & 0xFF);
|
||||||
|
digitalWrite(_ss_pin, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void readData(uint8_t * data)
|
||||||
|
{
|
||||||
|
digitalWrite(_ss_pin, LOW);
|
||||||
|
SPI.transfer(0x03);
|
||||||
|
SPI.transfer(0x00);
|
||||||
|
for(uint8_t i=0; i<32; i++) {
|
||||||
|
data[i] = SPI.transfer(0);
|
||||||
|
}
|
||||||
|
digitalWrite(_ss_pin, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeData(uint8_t * data, size_t len)
|
||||||
|
{
|
||||||
|
uint8_t i=0;
|
||||||
|
digitalWrite(_ss_pin, LOW);
|
||||||
|
SPI.transfer(0x02);
|
||||||
|
SPI.transfer(0x00);
|
||||||
|
while(len-- && i < 32) {
|
||||||
|
SPI.transfer(data[i++]);
|
||||||
|
}
|
||||||
|
while(i++ < 32) {
|
||||||
|
SPI.transfer(0);
|
||||||
|
}
|
||||||
|
digitalWrite(_ss_pin, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
String readData()
|
||||||
|
{
|
||||||
|
char data[33];
|
||||||
|
data[32] = 0;
|
||||||
|
readData((uint8_t *)data);
|
||||||
|
return String(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeData(const char * data)
|
||||||
|
{
|
||||||
|
writeData((uint8_t *)data, strlen(data));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ESPMaster esp(SS);
|
||||||
|
|
||||||
|
void send(const char * message)
|
||||||
|
{
|
||||||
|
Serial.print("Master: ");
|
||||||
|
Serial.println(message);
|
||||||
|
esp.writeData(message);
|
||||||
|
delay(10);
|
||||||
|
Serial.print("Slave: ");
|
||||||
|
Serial.println(esp.readData());
|
||||||
|
Serial.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(115200);
|
||||||
|
SPI.begin();
|
||||||
|
esp.begin();
|
||||||
|
delay(1000);
|
||||||
|
send("Hello Slave!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
delay(1000);
|
||||||
|
send("Are you alive?");
|
||||||
|
}
|
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
SPI Safe Master Demo Sketch
|
||||||
|
Connect the SPI Master device to the following pins on the esp8266:
|
||||||
|
|
||||||
|
GPIO NodeMCU Name | Uno
|
||||||
|
===================================
|
||||||
|
15 D8 SS | D10
|
||||||
|
13 D7 MOSI | D11
|
||||||
|
12 D6 MISO | D12
|
||||||
|
14 D5 SCK | D13
|
||||||
|
|
||||||
|
Note: If the ESP is booting at a moment when the SPI Master has the Select line HIGH (deselected)
|
||||||
|
the ESP8266 WILL FAIL to boot!
|
||||||
|
This sketch tries to go around this issue by only pulsing the Slave Select line to reset the command
|
||||||
|
and keeping the line LOW all other time.
|
||||||
|
|
||||||
|
*/
|
||||||
|
#include <SPI.h>
|
||||||
|
|
||||||
|
class ESPSafeMaster
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint8_t _ss_pin;
|
||||||
|
void _pulseSS()
|
||||||
|
{
|
||||||
|
digitalWrite(_ss_pin, HIGH);
|
||||||
|
delayMicroseconds(5);
|
||||||
|
digitalWrite(_ss_pin, LOW);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
ESPSafeMaster(uint8_t pin):_ss_pin(pin) {}
|
||||||
|
void begin()
|
||||||
|
{
|
||||||
|
pinMode(_ss_pin, OUTPUT);
|
||||||
|
_pulseSS();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t readStatus()
|
||||||
|
{
|
||||||
|
_pulseSS();
|
||||||
|
SPI.transfer(0x04);
|
||||||
|
uint32_t status = (SPI.transfer(0) | ((uint32_t)(SPI.transfer(0)) << 8) | ((uint32_t)(SPI.transfer(0)) << 16) | ((uint32_t)(SPI.transfer(0)) << 24));
|
||||||
|
_pulseSS();
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeStatus(uint32_t status)
|
||||||
|
{
|
||||||
|
_pulseSS();
|
||||||
|
SPI.transfer(0x01);
|
||||||
|
SPI.transfer(status & 0xFF);
|
||||||
|
SPI.transfer((status >> 8) & 0xFF);
|
||||||
|
SPI.transfer((status >> 16) & 0xFF);
|
||||||
|
SPI.transfer((status >> 24) & 0xFF);
|
||||||
|
_pulseSS();
|
||||||
|
}
|
||||||
|
|
||||||
|
void readData(uint8_t * data)
|
||||||
|
{
|
||||||
|
_pulseSS();
|
||||||
|
SPI.transfer(0x03);
|
||||||
|
SPI.transfer(0x00);
|
||||||
|
for(uint8_t i=0; i<32; i++) {
|
||||||
|
data[i] = SPI.transfer(0);
|
||||||
|
}
|
||||||
|
_pulseSS();
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeData(uint8_t * data, size_t len)
|
||||||
|
{
|
||||||
|
uint8_t i=0;
|
||||||
|
_pulseSS();
|
||||||
|
SPI.transfer(0x02);
|
||||||
|
SPI.transfer(0x00);
|
||||||
|
while(len-- && i < 32) {
|
||||||
|
SPI.transfer(data[i++]);
|
||||||
|
}
|
||||||
|
while(i++ < 32) {
|
||||||
|
SPI.transfer(0);
|
||||||
|
}
|
||||||
|
_pulseSS();
|
||||||
|
}
|
||||||
|
|
||||||
|
String readData()
|
||||||
|
{
|
||||||
|
char data[33];
|
||||||
|
data[32] = 0;
|
||||||
|
readData((uint8_t *)data);
|
||||||
|
return String(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeData(const char * data)
|
||||||
|
{
|
||||||
|
writeData((uint8_t *)data, strlen(data));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ESPSafeMaster esp(SS);
|
||||||
|
|
||||||
|
void send(const char * message)
|
||||||
|
{
|
||||||
|
Serial.print("Master: ");
|
||||||
|
Serial.println(message);
|
||||||
|
esp.writeData(message);
|
||||||
|
delay(10);
|
||||||
|
Serial.print("Slave: ");
|
||||||
|
Serial.println(esp.readData());
|
||||||
|
Serial.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(115200);
|
||||||
|
SPI.begin();
|
||||||
|
esp.begin();
|
||||||
|
delay(1000);
|
||||||
|
send("Hello Slave!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
delay(1000);
|
||||||
|
send("Are you alive?");
|
||||||
|
}
|
72
libraries/SPISlave/examples/SPISlave_Test/SPISlave_Test.ino
Normal file
72
libraries/SPISlave/examples/SPISlave_Test/SPISlave_Test.ino
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
SPI Slave Demo Sketch
|
||||||
|
Connect the SPI Master device to the following pins on the esp8266:
|
||||||
|
|
||||||
|
GPIO NodeMCU Name | Uno
|
||||||
|
===================================
|
||||||
|
15 D8 SS | D10
|
||||||
|
13 D7 MOSI | D11
|
||||||
|
12 D6 MISO | D12
|
||||||
|
14 D5 SCK | D13
|
||||||
|
|
||||||
|
Note: If the ESP is booting at a moment when the SPI Master has the Select line HIGH (deselected)
|
||||||
|
the ESP8266 WILL FAIL to boot!
|
||||||
|
See SPISlave_SafeMaster example for possible workaround
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SPISlave.h"
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.setDebugOutput(true);
|
||||||
|
|
||||||
|
// data has been received from the master. Beware that len is always 32
|
||||||
|
// and the buffer is autofilled with zeroes if data is less than 32 bytes long
|
||||||
|
// It's up to the user to implement protocol for handling data length
|
||||||
|
SPISlave.onData([](uint8_t * data, size_t len) {
|
||||||
|
String message = String((char *)data);
|
||||||
|
if(message.equals("Hello Slave!")) {
|
||||||
|
SPISlave.setData("Hello Master!");
|
||||||
|
} else if(message.equals("Are you alive?")) {
|
||||||
|
char answer[33];
|
||||||
|
sprintf(answer,"Alive for %u seconds!", millis() / 1000);
|
||||||
|
SPISlave.setData(answer);
|
||||||
|
} else {
|
||||||
|
SPISlave.setData("Say what?");
|
||||||
|
}
|
||||||
|
Serial.printf("Question: %s\n", (char *)data);
|
||||||
|
});
|
||||||
|
|
||||||
|
// The master has read out outgoing data buffer
|
||||||
|
// that buffer can be set with SPISlave.setData
|
||||||
|
SPISlave.onDataSent([]() {
|
||||||
|
Serial.println("Answer Sent");
|
||||||
|
});
|
||||||
|
|
||||||
|
// status has been received from the master.
|
||||||
|
// The status register is a special register that bot the slave and the master can write to and read from.
|
||||||
|
// Can be used to exchange small data or status information
|
||||||
|
SPISlave.onStatus([](uint32_t data) {
|
||||||
|
Serial.printf("Status: %u\n", data);
|
||||||
|
SPISlave.setStatus(millis()); //set next status
|
||||||
|
});
|
||||||
|
|
||||||
|
// The master has read the status register
|
||||||
|
SPISlave.onStatusSent([]() {
|
||||||
|
Serial.println("Status Sent");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Setup SPI Slave registers and pins
|
||||||
|
SPISlave.begin();
|
||||||
|
|
||||||
|
// Set the status register (if the master reads it, it will read this value)
|
||||||
|
SPISlave.setStatus(millis());
|
||||||
|
|
||||||
|
// Sets the data registers. Limited to 32 bytes at a time.
|
||||||
|
// SPISlave.setData(uint8_t * data, size_t len); is also available with the same limitation
|
||||||
|
SPISlave.setData("Ask me a question!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {}
|
25
libraries/SPISlave/keywords.txt
Normal file
25
libraries/SPISlave/keywords.txt
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#######################################
|
||||||
|
# Syntax Coloring Map SPI Slave
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Datatypes (KEYWORD1)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
SPISlave KEYWORD1
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Methods and Functions (KEYWORD2)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
begin KEYWORD2
|
||||||
|
setData KEYWORD2
|
||||||
|
setStatus KEYWORD2
|
||||||
|
onData KEYWORD2
|
||||||
|
onDataSent KEYWORD2
|
||||||
|
onStatus KEYWORD2
|
||||||
|
onStatusSent KEYWORD2
|
||||||
|
|
||||||
|
#######################################
|
||||||
|
# Constants (LITERAL1)
|
||||||
|
#######################################
|
9
libraries/SPISlave/library.properties
Normal file
9
libraries/SPISlave/library.properties
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
name=SPISlave
|
||||||
|
version=1.0
|
||||||
|
author=Hristo Gochkov
|
||||||
|
maintainer=Hristo Gochkov <hristo@espressif.com>
|
||||||
|
sentence=SPI Slave library for ESP8266
|
||||||
|
paragraph=
|
||||||
|
category=Signal Input/Output
|
||||||
|
url=
|
||||||
|
architectures=esp8266
|
103
libraries/SPISlave/src/SPISlave.cpp
Normal file
103
libraries/SPISlave/src/SPISlave.cpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
SPISlave library for esp8266
|
||||||
|
|
||||||
|
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#include "SPISlave.h"
|
||||||
|
extern "C" {
|
||||||
|
#include "hspi_slave.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPISlaveClass::_data_rx(uint8_t * data, uint8_t len)
|
||||||
|
{
|
||||||
|
if(_data_cb) {
|
||||||
|
_data_cb(data, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void SPISlaveClass::_status_rx(uint32_t data)
|
||||||
|
{
|
||||||
|
if(_status_cb) {
|
||||||
|
_status_cb(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void SPISlaveClass::_data_tx(void)
|
||||||
|
{
|
||||||
|
if(_data_sent_cb) {
|
||||||
|
_data_sent_cb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void SPISlaveClass::_status_tx(void)
|
||||||
|
{
|
||||||
|
if(_status_sent_cb) {
|
||||||
|
_status_sent_cb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void SPISlaveClass::_s_data_rx(void *arg, uint8_t * data, uint8_t len)
|
||||||
|
{
|
||||||
|
reinterpret_cast<SPISlaveClass*>(arg)->_data_rx(data,len);
|
||||||
|
}
|
||||||
|
void SPISlaveClass::_s_status_rx(void *arg, uint32_t data)
|
||||||
|
{
|
||||||
|
reinterpret_cast<SPISlaveClass*>(arg)->_status_rx(data);
|
||||||
|
}
|
||||||
|
void SPISlaveClass::_s_data_tx(void *arg)
|
||||||
|
{
|
||||||
|
reinterpret_cast<SPISlaveClass*>(arg)->_data_tx();
|
||||||
|
}
|
||||||
|
void SPISlaveClass::_s_status_tx(void *arg)
|
||||||
|
{
|
||||||
|
reinterpret_cast<SPISlaveClass*>(arg)->_status_tx();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPISlaveClass::begin()
|
||||||
|
{
|
||||||
|
hspi_slave_onData(&_s_data_rx);
|
||||||
|
hspi_slave_onDataSent(&_s_data_tx);
|
||||||
|
hspi_slave_onStatus(&_s_status_rx);
|
||||||
|
hspi_slave_onStatusSent(&_s_status_tx);
|
||||||
|
hspi_slave_begin(4, this);
|
||||||
|
}
|
||||||
|
void SPISlaveClass::setData(uint8_t * data, size_t len)
|
||||||
|
{
|
||||||
|
if(len > 32) {
|
||||||
|
len = 32;
|
||||||
|
}
|
||||||
|
hspi_slave_setData(data, len);
|
||||||
|
}
|
||||||
|
void SPISlaveClass::setStatus(uint32_t status)
|
||||||
|
{
|
||||||
|
hspi_slave_setStatus(status);
|
||||||
|
}
|
||||||
|
void SPISlaveClass::onData(SpiSlaveDataHandler cb)
|
||||||
|
{
|
||||||
|
_data_cb = cb;
|
||||||
|
}
|
||||||
|
void SPISlaveClass::onDataSent(SpiSlaveSentHandler cb)
|
||||||
|
{
|
||||||
|
_data_sent_cb = cb;
|
||||||
|
}
|
||||||
|
void SPISlaveClass::onStatus(SpiSlaveStatusHandler cb)
|
||||||
|
{
|
||||||
|
_status_cb = cb;
|
||||||
|
}
|
||||||
|
void SPISlaveClass::onStatusSent(SpiSlaveSentHandler cb)
|
||||||
|
{
|
||||||
|
_status_sent_cb = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPISlaveClass SPISlave;
|
69
libraries/SPISlave/src/SPISlave.h
Normal file
69
libraries/SPISlave/src/SPISlave.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
SPISlave library for esp8266
|
||||||
|
|
||||||
|
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#ifndef _SPISLAVE_H_INCLUDED
|
||||||
|
#define _SPISLAVE_H_INCLUDED
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
typedef std::function<void(uint8_t *data, size_t len)> SpiSlaveDataHandler;
|
||||||
|
typedef std::function<void(uint32_t status)> SpiSlaveStatusHandler;
|
||||||
|
typedef std::function<void(void)> SpiSlaveSentHandler;
|
||||||
|
|
||||||
|
class SPISlaveClass
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
SpiSlaveDataHandler _data_cb;
|
||||||
|
SpiSlaveStatusHandler _status_cb;
|
||||||
|
SpiSlaveSentHandler _data_sent_cb;
|
||||||
|
SpiSlaveSentHandler _status_sent_cb;
|
||||||
|
void _data_rx(uint8_t * data, uint8_t len);
|
||||||
|
void _status_rx(uint32_t data);
|
||||||
|
void _data_tx(void);
|
||||||
|
void _status_tx(void);
|
||||||
|
static void _s_data_rx(void *arg, uint8_t * data, uint8_t len);
|
||||||
|
static void _s_status_rx(void *arg, uint32_t data);
|
||||||
|
static void _s_data_tx(void *arg);
|
||||||
|
static void _s_status_tx(void *arg);
|
||||||
|
public:
|
||||||
|
SPISlaveClass()
|
||||||
|
: _data_cb(NULL)
|
||||||
|
, _status_cb(NULL)
|
||||||
|
, _data_sent_cb(NULL)
|
||||||
|
, _status_sent_cb(NULL)
|
||||||
|
{}
|
||||||
|
~SPISlaveClass() {}
|
||||||
|
void begin();
|
||||||
|
void setData(uint8_t * data, size_t len);
|
||||||
|
void setData(const char * data)
|
||||||
|
{
|
||||||
|
setData((uint8_t *)data, strlen(data));
|
||||||
|
}
|
||||||
|
void setStatus(uint32_t status);
|
||||||
|
void onData(SpiSlaveDataHandler cb);
|
||||||
|
void onDataSent(SpiSlaveSentHandler cb);
|
||||||
|
void onStatus(SpiSlaveStatusHandler cb);
|
||||||
|
void onStatusSent(SpiSlaveSentHandler cb);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern SPISlaveClass SPISlave;
|
||||||
|
|
||||||
|
#endif
|
143
libraries/SPISlave/src/hspi_slave.c
Normal file
143
libraries/SPISlave/src/hspi_slave.c
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
SPISlave library for esp8266
|
||||||
|
|
||||||
|
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#include "hspi_slave.h"
|
||||||
|
#include "esp8266_peri.h"
|
||||||
|
#include "ets_sys.h"
|
||||||
|
|
||||||
|
static void (*_hspi_slave_rx_data_cb)(void * arg, uint8_t * data, uint8_t len) = NULL;
|
||||||
|
static void (*_hspi_slave_tx_data_cb)(void * arg) = NULL;
|
||||||
|
static void (*_hspi_slave_rx_status_cb)(void * arg, uint32_t data) = NULL;
|
||||||
|
static void (*_hspi_slave_tx_status_cb)(void * arg) = NULL;
|
||||||
|
static uint8_t _hspi_slave_buffer[33];
|
||||||
|
|
||||||
|
void ICACHE_RAM_ATTR _hspi_slave_isr_handler(void *arg)
|
||||||
|
{
|
||||||
|
uint32_t status;
|
||||||
|
uint32_t istatus;
|
||||||
|
|
||||||
|
istatus = SPIIR;
|
||||||
|
|
||||||
|
if(istatus & (1 << SPII1)) { //SPI1 ISR
|
||||||
|
status = SPI1S;
|
||||||
|
SPI1S &= ~(0x3E0);//disable interrupts
|
||||||
|
SPI1S |= SPISSRES;//reset
|
||||||
|
SPI1S &= ~(0x1F);//clear interrupts
|
||||||
|
SPI1S |= (0x3E0);//enable interrupts
|
||||||
|
|
||||||
|
if((status & SPISRBIS) != 0 && (_hspi_slave_tx_data_cb)) {
|
||||||
|
_hspi_slave_tx_data_cb(arg);
|
||||||
|
}
|
||||||
|
if((status & SPISRSIS) != 0 && (_hspi_slave_tx_status_cb)) {
|
||||||
|
_hspi_slave_tx_status_cb(arg);
|
||||||
|
}
|
||||||
|
if((status & SPISWSIS) != 0 && (_hspi_slave_rx_status_cb)) {
|
||||||
|
uint32_t s = SPI1WS;
|
||||||
|
_hspi_slave_rx_status_cb(arg, s);
|
||||||
|
}
|
||||||
|
if((status & SPISWBIS) != 0 && (_hspi_slave_rx_data_cb)) {
|
||||||
|
uint8_t i;
|
||||||
|
uint32_t data;
|
||||||
|
uint8_t buffer[33];
|
||||||
|
_hspi_slave_buffer[32] = 0;
|
||||||
|
for(i=0; i<8; i++) {
|
||||||
|
data=SPI1W(i);
|
||||||
|
_hspi_slave_buffer[i<<2] = data & 0xff;
|
||||||
|
_hspi_slave_buffer[(i<<2)+1] = (data >> 8) & 0xff;
|
||||||
|
_hspi_slave_buffer[(i<<2)+2] = (data >> 16) & 0xff;
|
||||||
|
_hspi_slave_buffer[(i<<2)+3] = (data >> 24) & 0xff;
|
||||||
|
}
|
||||||
|
_hspi_slave_rx_data_cb(arg, &_hspi_slave_buffer[0], 32);
|
||||||
|
}
|
||||||
|
} else if(istatus & (1 << SPII0)) { //SPI0 ISR
|
||||||
|
SPI0S &= ~(0x3ff);//clear SPI ISR
|
||||||
|
} else if(istatus & (1 << SPII2)) {} //I2S ISR
|
||||||
|
}
|
||||||
|
|
||||||
|
void hspi_slave_begin(uint8_t status_len, void * arg)
|
||||||
|
{
|
||||||
|
status_len &= 7;
|
||||||
|
if(status_len > 4) {
|
||||||
|
status_len == 4; //max 32 bits
|
||||||
|
}
|
||||||
|
if(status_len == 0) {
|
||||||
|
status_len == 1; //min 8 bits
|
||||||
|
}
|
||||||
|
|
||||||
|
pinMode(SS, SPECIAL);
|
||||||
|
pinMode(SCK, SPECIAL);
|
||||||
|
pinMode(MISO, SPECIAL);
|
||||||
|
pinMode(MOSI, SPECIAL);
|
||||||
|
|
||||||
|
SPI1S = SPISE | SPISBE | 0x3E0;
|
||||||
|
SPI1U = SPIUMISOH | SPIUCOMMAND | SPIUSSE;
|
||||||
|
SPI1CLK = 0;
|
||||||
|
SPI1U2 = (7 << SPILCOMMAND);
|
||||||
|
SPI1S1 = (((status_len * 8) - 1) << SPIS1LSTA) | (0xff << SPIS1LBUF) | (7 << SPIS1LWBA) | (7 << SPIS1LRBA) | SPIS1RSTA;
|
||||||
|
SPI1P = (1 << 19);
|
||||||
|
SPI1CMD = SPIBUSY;
|
||||||
|
|
||||||
|
ETS_SPI_INTR_ATTACH(_hspi_slave_isr_handler,arg);
|
||||||
|
ETS_SPI_INTR_ENABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
void hspi_slave_setStatus(uint32_t status)
|
||||||
|
{
|
||||||
|
SPI1WS = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hspi_slave_setData(uint8_t *data, uint8_t len)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
uint32_t out = 0;
|
||||||
|
uint8_t bi = 0;
|
||||||
|
uint8_t wi = 8;
|
||||||
|
|
||||||
|
for(i=0; i<32; i++) {
|
||||||
|
out |= (i<len)?(data[i] << (bi * 8)):0;
|
||||||
|
bi++;
|
||||||
|
bi &= 3;
|
||||||
|
if(!bi) {
|
||||||
|
SPI1W(wi) = out;
|
||||||
|
out = 0;
|
||||||
|
wi++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hspi_slave_onData(void (*rxd_cb)(void *, uint8_t *, uint8_t))
|
||||||
|
{
|
||||||
|
_hspi_slave_rx_data_cb = rxd_cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hspi_slave_onDataSent(void (*txd_cb)(void *))
|
||||||
|
{
|
||||||
|
_hspi_slave_tx_data_cb = txd_cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hspi_slave_onStatus(void (*rxs_cb)(void *, uint32_t))
|
||||||
|
{
|
||||||
|
_hspi_slave_rx_status_cb = rxs_cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hspi_slave_onStatusSent(void (*txs_cb)(void *))
|
||||||
|
{
|
||||||
|
_hspi_slave_tx_status_cb = txs_cb;
|
||||||
|
}
|
41
libraries/SPISlave/src/hspi_slave.h
Normal file
41
libraries/SPISlave/src/hspi_slave.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
SPISlave library for esp8266
|
||||||
|
|
||||||
|
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
|
||||||
|
This file is part of the esp8266 core for Arduino environment.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#ifndef _HSPISLAVE_H_INCLUDED
|
||||||
|
#define _HSPISLAVE_H_INCLUDED
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
//Start SPI SLave
|
||||||
|
void hspi_slave_begin(uint8_t status_len, void * arg);
|
||||||
|
|
||||||
|
//set the status register so the master can read it
|
||||||
|
void hspi_slave_setStatus(uint32_t status);
|
||||||
|
|
||||||
|
//set the data registers (max 32 bytes at a time)
|
||||||
|
void hspi_slave_setData(uint8_t *data, uint8_t len);
|
||||||
|
|
||||||
|
//set the callbacks
|
||||||
|
void hspi_slave_onData(void (*rxd_cb)(void *, uint8_t *, uint8_t));
|
||||||
|
void hspi_slave_onDataSent(void (*txd_cb)(void *));
|
||||||
|
void hspi_slave_onStatus(void (*rxs_cb)(void *, uint32_t));
|
||||||
|
void hspi_slave_onStatusSent(void (*txs_cb)(void *));
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user