Skip to content

Initial SPI Slave implementation and examples #2234

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Jul 6, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions libraries/SPISlave/examples/SPISlave_Master/SPISlave_Master.ino
Original file line number Diff line number Diff line change
@@ -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?");
}
Original file line number Diff line number Diff line change
@@ -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 changes: 72 additions & 0 deletions libraries/SPISlave/examples/SPISlave_Test/SPISlave_Test.ino
Original file line number Diff line number Diff line change
@@ -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 changes: 25 additions & 0 deletions libraries/SPISlave/keywords.txt
Original file line number Diff line number Diff line change
@@ -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 changes: 9 additions & 0 deletions libraries/SPISlave/library.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name=SPISlave
version=1.0
author=Hristo Gochkov
maintainer=Hristo Gochkov <[email protected]>
sentence=SPI Slave library for ESP8266
paragraph=
category=Signal Input/Output
url=
architectures=esp8266
Loading