Skip to content
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

I2C slave mode #166

Open
wants to merge 2 commits into
base: development
Choose a base branch
from
Open
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
19 changes: 19 additions & 0 deletions sduino/stm8/cores/sduino/weak_awu.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* "weak" functions to be used if no user-defined function is defined.
*
* This function stub is compiled into the core library. Functions from
* libraries are only linked if a referenced function isnt't defined any other
* object file. This way all library function are a kind of "weak" functions.
*
* this interrupt handler is prototyped in stm8s_it.h and needs a definition
* to avoid linker error
* If there is no other definition of the interrupt handler in user code
* this empty definition is pulled in
*
*/

#include "stm8s.h"
INTERRUPT_HANDLER(AWU_IRQHandler, ITC_IRQ_AWU) {
AWU->CSR; // dummy read to clear the AWUF interrupt flag
}

16 changes: 16 additions & 0 deletions sduino/stm8/cores/sduino/weak_i2c.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* "weak" functions to be used if no user-defined function is defined.
*
* This function stub is compiled into the core library. Functions from
* libraries are only linked if a referenced function isnt't defined any other
* object file. This way all library function are a kind of "weak" functions.
*
* this interrupt handler is prototyped in stm8s_it.h and needs a definition
* to avoid linker error
* If there is no other definition of the interrupt handler in user code
* this empty definition is pulled in
*
*/

#include "stm8s.h"
INTERRUPT_HANDLER(I2C_IRQHandler, ITC_IRQ_TIM2_OVF) {}
17 changes: 17 additions & 0 deletions sduino/stm8/cores/sduino/weak_tim2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* "weak" functions to be used if no user-defined function is defined.
*
* This function stub is compiled into the core library. Functions from
* libraries are only linked if a referenced function isnt't defined any other
* object file. This way all library function are a kind of "weak" functions.
*
* this interrupt handler is prototyped in stm8s_it.h and needs a definition
* to avoid linker error
* If there is no other definition of the interrupt handler in user code
* this empty definition is pulled in
*
*/

#include "stm8s.h"
INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, ITC_IRQ_TIM2_OVF) {}

Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,11 @@

#include <Wire.h>


void setup()
{
Wire_begin();

Serial_begin(9600);
Serial_begin(115200);
while (!Serial); // Leonardo: wait for serial monitor
Serial_println_s("\nI2C Scanner");
}
Expand Down
56 changes: 56 additions & 0 deletions sduino/stm8/libraries/Wire/examples/slave_eeprom/slave_eeprom.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* demo code showing STM8 as a 640-byte serial I2C eeprom
* behaves like AT24C32, but only 640 bytes
* using extEEPROM library : instantiate as: extEEPROM eep(kbits_256, 1, 16); on a I2C master device.
* uses STM8 slave i2c and EEPROM libraries, and shows the use of both receiveEvent and requestEvent callbacks
*/

#include <Wire.h>
#include <EEPROM.h>

#define I2C_ADDRESS 0x50 // typical address for I2C serial eeproms

void receiveEvent(int numBytes);
void requestEvent(void);

uint16_t refAddress = 0;

// function that executes whenever data is requested from master
void requestEvent () {
// let's just deliver 32 bytes = max size for I2C buffer
for (int i=0;i<32;i++){
Wire_write(EEPROM_read(refAddress++));
}
}

// function that executes whenever data is received from master
void receiveEvent(int numBytes) {
// Wire library expects us to read the complete buffer
// first 2 bytes : high & low byte of eeprom address
uint8_t rxBytes[32], aByte;
uint8_t rxIndex = 0;
while (Wire_available()) {
aByte = Wire_read();
if (rxIndex < 32)
rxBytes[rxIndex++] = aByte;
}

if (numBytes >= 2)
refAddress = (rxBytes[0] << 8) | rxBytes[1];
if (numBytes > 2) {
for (rxIndex=2;rxIndex<numBytes;rxIndex++) {
EEPROM_update(refAddress++,rxBytes[rxIndex]); // EEPROM lib prevents writing to non-existing addresses, no need to check here
}
}
// if numBytes == 2 -> we expect a repeated start and a requestEvent will provide the data read from eeprom
// if numBytes < 2 -> not according to spec
}

void setup() {
Wire_beginSlave(I2C_ADDRESS); // join i2c bus with this address
Wire_onReceive(receiveEvent); // register event
Wire_onRequest(requestEvent); // register event
}

void loop() {
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,24 @@
// Created 29 March 2006

// This example code is in the public domain.

/* 2021 - modified for sduino
* Note 1:
* -> receiveEvent is called from ISR context; calling Serial_print can give rise to a deadlock:
* -> if serial buffer is full, Serial_print will busy wait for the UART-TX ISR to send some characters
* -> but this can't work from the TWI ISR, because all ISR's have same priority in sduino
* -> the only reason is works here is because we are serial printing less data than the SERIAL_BUFFER_SIZE
* Note 2: it's important to Wire_read all received bytes in receiveEvent (conform arduino Wire implementation)
* otherwise receiveEvent is not called on the next frame (rxBufferIndex < rxBufferLength in Wire.c)!
*/

#include <Wire.h>

void receiveEvent(int howMany);

void setup() {
Wire.begin(8); // join i2c bus with address #8
Wire.onReceive(receiveEvent); // register event
Serial.begin(9600); // start serial for output
Wire_beginSlave(8); // join i2c bus with address #8
Wire_onReceive(receiveEvent); // register event
Serial_begin(115200); // start serial for output
}

void loop() {
Expand All @@ -25,10 +35,12 @@ void loop() {
// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
while (1 < Wire.available()) { // loop through all but the last
char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character

while (1 < Wire_available()) { // loop through all but the last
char c = Wire_read(); // receive byte as a character
Serial_print_c(c); // print the character
}
int x = Wire.read(); // receive byte as an integer
Serial.println(x); // print the integer
int x = Wire_read(); // receive byte as an integer
Serial_println_u(x); // print the integer

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@
// Created 29 March 2006

// This example code is in the public domain.
// 2021 : modified for sduino


#include <Wire.h>

void requestEvent();

void setup() {
Wire.begin(8); // join i2c bus with address #8
Wire.onRequest(requestEvent); // register event
Wire_beginSlave(8); // join i2c bus with address #8
Wire_onRequest(requestEvent); // register event
}

void loop() {
Expand All @@ -24,6 +27,6 @@ void loop() {
// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
Wire.write("hello "); // respond with message of 6 bytes
Wire_write_s("hello "); // respond with message of 6 bytes
// as expected by master
}
}
2 changes: 1 addition & 1 deletion sduino/stm8/libraries/Wire/library.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ sentence=This library allows you to communicate with I2C and Two Wire Interface
paragraph=It allows the communication with I2C devices like temperature sensors, realtime clocks and many others using SDA (Data Line) and SCL (Clock Line).
category=Communication
url=http://www.arduino.cc/en/Reference/Wire
architectures=avr
architectures=stm8

33 changes: 18 additions & 15 deletions sduino/stm8/libraries/Wire/src/Wire.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ static uint8_t txBufferIndex = 0;
static uint8_t txBufferLength = 0;

static uint8_t transmitting = 0;
static void (*user_onRequest)(void);
static void (*user_onReceive)(int);
static void onRequestService(void);
static void onReceiveService(uint8_t* inBytes, int numBytes);

/*
void (*TwoWire::user_onRequest)(void);
void (*TwoWire::user_onReceive)(int);
Expand All @@ -65,6 +70,14 @@ void Wire_begin(void)
txBufferLength = 0;

twi_init();
twi_attachSlaveTxEvent(onRequestService); // default callback must exist
twi_attachSlaveRxEvent(onReceiveService); // default callback must exist
}

void Wire_beginSlave(uint8_t address)
{
Wire_begin();
twi_setAddress(address);
}

/*
Expand All @@ -87,25 +100,21 @@ void Wire_end(void)
twi_disable();
}


void Wire_setClock(uint32_t clock)
{
twi_setFrequency(clock);
}


void Wire_setTimeout(uint16_t ms)
{
twi_setTimeout(ms);
}


uint8_t Wire_requestFrom2(uint8_t address, uint8_t quantity)
{
return Wire_requestFrom3(address, quantity, (uint8_t)true);
}


uint8_t Wire_requestFrom3(uint8_t address, uint8_t quantity, uint8_t sendStop)
{
uint8_t read;
Expand All @@ -123,7 +132,6 @@ uint8_t Wire_requestFrom3(uint8_t address, uint8_t quantity, uint8_t sendStop)
return read;
}


uint8_t Wire_requestFrom5(uint8_t address, uint8_t quantity, uint32_t iaddress, uint8_t isize, uint8_t sendStop)
{
if (isize > 0) {
Expand Down Expand Up @@ -259,13 +267,11 @@ size_t Wire_write(uint8_t data)
return 1;
}


size_t Wire_write_s(const uint8_t *data)
{
return Wire_write_sn(data,strlen(data));
}


// must be called in:
// slave tx event callback
// or after beginTransmission(address)
Expand All @@ -284,7 +290,6 @@ size_t Wire_write_sn(const uint8_t *data, size_t quantity)
return quantity;
}


// must be called in:
// slave rx event callback
// or after requestFrom(address, numBytes)
Expand All @@ -309,7 +314,6 @@ int Wire_read(void)
return value;
}


// must be called in:
// slave rx event callback
// or after requestFrom(address, numBytes)
Expand All @@ -329,9 +333,8 @@ void Wire_flush(void)
// XXX: to be implemented.
}

/*
// behind the scenes function that is called when data is received
void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
static void onReceiveService(uint8_t* inBytes, int numBytes)
{
// don't bother if user hasn't registered a callback
if(!user_onReceive){
Expand All @@ -356,7 +359,7 @@ void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes)
}

// behind the scenes function that is called when data is requested
void TwoWire::onRequestService(void)
static void onRequestService(void)
{
// don't bother if user hasn't registered a callback
if(!user_onRequest){
Expand All @@ -371,19 +374,19 @@ void TwoWire::onRequestService(void)
}

// sets function called on slave write
void TwoWire::onReceive( void (*function)(int) )
void Wire_onReceive( void (*function)(int) )
{
user_onReceive = function;
}

// sets function called on slave read
void TwoWire::onRequest( void (*function)(void) )
void Wire_onRequest( void (*function)(void) )
{
user_onRequest = function;
}

/*
// Preinstantiate Objects //////////////////////////////////////////////////////

TwoWire Wire = TwoWire();

*/
42 changes: 22 additions & 20 deletions sduino/stm8/libraries/Wire/src/Wire.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,28 +86,30 @@ extern TwoWire Wire;
*/

/* only this minimal interface is currently implemented: */
void Wire_begin(void);
void Wire_end(void);
void Wire_setClock(uint32_t);
void Wire_setTimeout(uint16_t);

void Wire_beginTransmission(uint8_t);
uint8_t Wire_endTransmission1(uint8_t sendStop);
inline uint8_t Wire_endTransmission(void){return Wire_endTransmission1(true);}

size_t Wire_write(uint8_t);
size_t Wire_write_s(const uint8_t *);
size_t Wire_write_sn(const uint8_t *, size_t);
int Wire_available(void);
int Wire_read(void);
int Wire_peek(void);
void Wire_flush(void);

uint8_t Wire_requestFrom2(uint8_t address, uint8_t quantity);
uint8_t Wire_requestFrom3(uint8_t address, uint8_t quantity, uint8_t sendStop);
void Wire_begin(void);
void Wire_beginSlave(uint8_t address);
void Wire_end(void);
void Wire_setClock(uint32_t);
void Wire_setTimeout(uint16_t);

void Wire_beginTransmission(uint8_t);
uint8_t Wire_endTransmission1(uint8_t sendStop);
inline uint8_t Wire_endTransmission(void){return Wire_endTransmission1(true);}

size_t Wire_write(uint8_t);
size_t Wire_write_s(const uint8_t *);
size_t Wire_write_sn(const uint8_t *, size_t);
int Wire_available(void);
int Wire_read(void);
int Wire_peek(void);
void Wire_flush(void);
void Wire_onReceive( void (*function)(int) );
void Wire_onRequest( void (*function)(void) );

uint8_t Wire_requestFrom2(uint8_t address, uint8_t quantity);
uint8_t Wire_requestFrom3(uint8_t address, uint8_t quantity, uint8_t sendStop);
uint8_t Wire_requestFrom5(uint8_t address, uint8_t quantity, uint32_t iaddress, uint8_t isize, uint8_t sendStop);


// Pseudo-OO interface: Plain C disguised as almost-C++, thanks to X-Macros
//
// We want to "inherit" the output functions from Print, so include that
Expand Down
Loading