Statistics: Posted by MelaniaZew — Sun Jul 22, 2018 10:54 am
Statistics: Posted by Driftmonster — Fri Mar 09, 2018 8:10 am
Code:
#include <Wire.h>
int x = 0;
void setup() {
Serial.begin(9600);
Wire.begin(8);
}
void loop()
{
Wire.beginTransmission(8);
Wire.write(x);
Wire.endTransmission();
Serial.println(x);
x++;
delay(100);
}
Code:
... code above...
unsigned int SCL_pin=4; // SCL pin GPIO
unsigned int SDA_pin=5; // SCL pin GPIO
int address = 8;
void receiveEvent(int howMany)
{
Serial.println("receiveEvent()");
while (1 < ESP_I2CSlaveavailable())
{
char c = ESP_I2CSlaveread();
Serial.print(c);
}
}
void requestEvent()
{
Serial.println("requestEvent()");
}
void setup()
{
ESP_I2CSlavebegin(SCL_pin,SDA_pin,address);
ESP_I2CSlaveonRequest(requestEvent);
ESP_I2CSlaveonReceive(receiveEvent);
Serial.begin(9600);
}
void loop()
{
delay(100);
}
Statistics: Posted by biccius — Sat May 20, 2017 10:01 pm
Statistics: Posted by Guest — Mon Feb 13, 2017 2:33 pm
Code:
/* I2C Slave
*
*/
// States
// ======
#define IDL 0x01 // IDL - Idle state
#define SLA 0x02 // SLA - Receiving SLA from master
#define ACK 0x04 // ACK - Sending ACK tomaster
#define NAK 0x08 // NAK - Sending NACK to master
#define RAK 0x10 // RAK - Receiving ACK/NACK from master
#define RCD 0x20 // RCD - Receiving data from master
#define SND 0x40 // SND - Sending data to master
// Flags
// =====
#define STOP 0x01 // STOP - STOP signal detected
#define STRT 0x02 // STRT - START signal detected
#define SLAW 0x04 // SLAW - SLA+W matched our slave address
#define SLAR 0x08 // SLAR - SLA+R matched our slave address
#define BFUL 0x10 // BFUL - I2C buffer full
#define BEMP 0x20 // BEMP - I2C buffer empty
// Pin Defs
unsigned int SCL_pin=4; // SCL pin GPIO
unsigned int SDA_pin=5; // SCL pin GPIO
// macros to avoid using digital write and read (speed up as everything is interrupt driven)
#define SCL_LOW GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS,1<< SCL_pin)
#define SCL_HIGH GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS,1<< SCL_pin)
#define SDA_LOW GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS,1<< SDA_pin)
#define SDA_HIGH GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS,1<< SDA_pin)
#define READ_SCL GPIO_REG_READ(GPIO_IN_ADDRESS)&(1<<SCL_pin)
#define READ_SDA GPIO_REG_READ(GPIO_IN_ADDRESS)&(1<<SDA_pin)
// buffer defs
#define BUFF_ERR 0xffffffff // error code to return if trying to read from an empty buffer or write to full buffer
#define I2CBUFFLEN 32 // buffer size
#define BUFF_READ 0x01 // read buffer item
#define BUFF_WRITE 0x02 // write to buffer
#define BUFF_AVAIL 0x03 // how many items in the buffer
#define BUFF_FLUSH 0x04 // flush the buffer
// misc defs
#define FUNC_RST 1 // used to reset static vars in send/receive functions
#define FUNC_NOT_RST 0 // opposite of FUNC_RST
// global vars (native 32 bit and unsigned for speed)
volatile unsigned int Flags=STOP, State=IDL;
void (*user_onRequest)(void);
void (*user_onReceive)(int);
volatile unsigned int _I2CAddress=0x3f;
void setup() {
}
void loop() {
}
////////////////////////////////////////////////////////////////////////
//
// PRIVATE METHODS
//
////////////////////////////////////////////////////////////////////////
unsigned int PRIV_I2CBuffer(unsigned int _action, unsigned int &_val)
{
volatile static unsigned int _BuffHead=0, _BuffTail=0, _Buffer[I2CBUFFLEN];
switch (_action) {
case BUFF_READ:
if (Flags & BEMP) return false;
_val = _Buffer[_BuffTail];
_BuffTail++;
if (_BuffTail >= I2CBUFFLEN) _BuffTail = 0;
if (_BuffTail == _BuffHead) Flags |= BEMP;
else Flags &= ~BEMP;
Flags &= ~BFUL;
break;
case BUFF_WRITE:
if (Flags & BFUL) return false;
_Buffer[_BuffHead] = _val;
_BuffHead++;
if (_BuffHead >= I2CBUFFLEN) _BuffHead = 0;
if (_BuffHead == _BuffTail) Flags |= BFUL;
else Flags &= ~BFUL;
Flags &= ~BEMP;
break;
case BUFF_AVAIL:
if (Flags & BFUL) _val = I2CBUFFLEN;
else _val = (_BuffHead >= _BuffTail)?_BuffHead - _BuffTail:I2CBUFFLEN - _BuffTail + _BuffHead;
break;
case BUFF_FLUSH:
_BuffHead = 0;
_BuffTail = 0;
Flags |= BEMP;
Flags &= ~BFUL;
break;
}
return true;
}
void onReceiveService(int numBytes)
{
// don't bother if user hasn't registered a callback
if(!user_onReceive) return;
// alert user program
user_onReceive(numBytes);
}
void onRequestService(void){
// // don't bother if user hasn't registered a callback
if(!user_onRequest) return;
// alert user program
user_onRequest();
}
void PRIV_RAKhandler()
{
// nice and easy if we get ACK send more data otherwise stop
if (READ_SDA) PRIV_STOPhandler();
else State = SND;
}
void PRIV_NAKhandler()
{
// nice and simple if we NACK the next response should
// be stop or start both of which will reset the state
SDA_HIGH;
}
void PRIV_ACKhandler()
{
volatile static unsigned int _firstpass = 1;
if (_firstpass) {
SDA_LOW;
_firstpass = 0;
}
else {
SDA_HIGH;
_firstpass = 1;
if (Flags & SLAW) State = RCD;
else {
State = SND;
PRIV_SNDhandler(FUNC_NOT_RST);
}
}
}
void PRIV_RCDhandler(unsigned int _reset)
{
volatile static unsigned int _bitcount=0, _i2cbyte=0, _firstpass=1;
unsigned int _val;
if (_reset) {
_firstpass = 1;
_bitcount = 0;
_i2cbyte = 0;
return;
}
if (_firstpass) {
_firstpass = 0;
_bitcount = 0;
_i2cbyte = 0;
}
_i2cbyte <<= 1;
if (READ_SDA) _i2cbyte |= 1;
_bitcount++;
if (_bitcount > 7) {
_firstpass = 1;
_val = _i2cbyte;
if (!PRIV_I2CBuffer(BUFF_WRITE, _val)) State = NAK;
else {
if (Flags & BFUL) State = NAK;
else State = ACK;
}
}
}
void PRIV_SLAhandler(unsigned int _reset)
{
volatile static unsigned int _bitcount=0, _i2cbyte, _firstpass = 1;
if (_reset) {
_firstpass = 1;
_bitcount = 0;
_i2cbyte = 0;
return;
}
if (_firstpass) {
_firstpass =0;
_bitcount = 0;
_i2cbyte = 0;
}
_i2cbyte <<= 1;
if (READ_SDA) _i2cbyte |= 1;
_bitcount++;
if (_bitcount > 7) {
_firstpass = 1;
if ((_i2cbyte >> 1) == _I2CAddress) {
if (_i2cbyte & 0x01) {
Flags |= SLAR;
onRequestService();
if (Flags & BEMP) State = NAK;
else State = ACK;
}
else Flags|= SLAW;
if (Flags & BFUL) State = NAK;
else State = ACK;
}
}
}
void PRIV_SNDhandler(unsigned int _reset)
{
volatile static unsigned int _bitcount=0, _i2cbyte, _releaseSDA=0, _firstpass = 1;
unsigned int _val;
if (_reset) {
_firstpass = 1;
_bitcount = 0;
return;
}
if (_releaseSDA) {
SDA_HIGH;
State = RAK;
_releaseSDA = 0;
_firstpass = 1;
return;
}
if (!_firstpass) {
PRIV_I2CBuffer(BUFF_READ, _val);
_i2cbyte = _val;
_bitcount = 0;
_firstpass = 0;
}
if (_i2cbyte & 1) SDA_HIGH;
else SDA_LOW;
_i2cbyte >>= 1;
_bitcount++;
if (_bitcount > 7) {
_releaseSDA = 1;
}
}
void PRIV_STRThandler()
{
unsigned int _retval, _val;
if (Flags & SLAW) {
PRIV_I2CBuffer(BUFF_AVAIL, _val);
if (_val) onReceiveService(_val);
}
if (Flags & SLAR) PRIV_I2CBuffer(BUFF_FLUSH, _val);
Flags &= 0xfffffff0;
Flags |= STRT;
State = SLA;
}
void PRIV_STOPhandler()
{
unsigned int _retval, _val;
if (Flags & SLAW) {
PRIV_I2CBuffer(BUFF_AVAIL, _val);
if (_val) onReceiveService(_val);
PRIV_RCDhandler(FUNC_RST);
PRIV_SNDhandler(FUNC_RST);
PRIV_SLAhandler(FUNC_RST);
}
if (Flags & SLAR) PRIV_I2CBuffer(BUFF_FLUSH, _val);
Flags &= 0xfffffff0;
Flags |= STOP;
State = IDL;
}
void PRIV_SCLChangeISR()
{
if (State == IDL) return;
if (READ_SCL) { //read on rising edge
switch (State) {
case RAK:
// receiving ACK from master
PRIV_RAKhandler();
break;
case RCD:
// receiving data from master
PRIV_RCDhandler(FUNC_NOT_RST);
break;
case SLA:
// receiving SLA+R/W from master
PRIV_SLAhandler(FUNC_NOT_RST);
break;
}
}
else { // Sending data to master
SCL_LOW; // Apply Clock Stretch
switch (State) {
case ACK:
// send ack to master
PRIV_ACKhandler();
break;
case NAK:
// send nack to master
PRIV_NAKhandler();
break;
case SND:
// send data to master
PRIV_SNDhandler(FUNC_NOT_RST);
break;
}
SCL_HIGH; // Release Clock Stretch
}
}
void PRIV_SDAChangeISR()
{
if (READ_SCL) {
if (READ_SDA) PRIV_STOPhandler();
else PRIV_STRThandler();
}
}
////////////////////////////////////////////////////////////////////////////////
//
// PUBLIC METHODS
//
///////////////////////////////////////////////////////////////////////////////
unsigned int ESP_I2CSlavewrite(unsigned int _val)
{
unsigned int _retval;
if (Flags & BFUL) return BUFF_ERR;
_retval = PRIV_I2CBuffer(BUFF_WRITE, _val);
return (_retval)?0:BUFF_ERR;
}
unsigned int ESP_I2CSlaveread()
{
unsigned int _retval, _val;
if (Flags & BEMP) return BUFF_ERR;
_retval = PRIV_I2CBuffer(BUFF_READ, _val);
return (_retval)?_val:BUFF_ERR;
}
void ESP_I2CSlaveflush()
{
unsigned int _retval, _val;
PRIV_I2CBuffer(BUFF_FLUSH, _val);
}
unsigned int ESP_I2CSlaveavailable()
{
unsigned int _retval, _val;
_retval = PRIV_I2CBuffer(BUFF_AVAIL, _val);
return _val;
}
void ESP_I2CSlaveonReceive( void (*function)(int) ){
user_onReceive = function;
}
void ESP_I2CSlaveonRequest( void (*function)(void) ){
user_onRequest = function;
}
void ESP_I2CSlavebegin(int scl_pin, int sda_pin, byte address)
{
_I2CAddress = address & 0x7f;
SCL_pin = scl_pin & 0xf;
SDA_pin = sda_pin & 0xf;
pinMode(SCL_pin, OUTPUT_OPEN_DRAIN);
pinMode(SDA_pin, OUTPUT_OPEN_DRAIN);
SCL_HIGH;
SDA_HIGH;
attachInterrupt(digitalPinToInterrupt(SCL_pin), PRIV_SCLChangeISR, CHANGE);
attachInterrupt(digitalPinToInterrupt(SDA_pin), PRIV_SDAChangeISR, CHANGE);
}
Statistics: Posted by Guest — Mon Feb 06, 2017 9:21 am
Statistics: Posted by dkaufmann — Thu Jan 05, 2017 4:36 pm
Statistics: Posted by Guest — Wed Nov 30, 2016 7:54 pm
Statistics: Posted by dkaufmann — Tue Nov 29, 2016 8:54 pm
CNLohr on esp8266.com wrote:
I could respond to interrupt requests in .28 us!
rudi on esp8266.com wrote:
with 80MHz it is 12.5 ns
with 160 MHz it is 6.5 ns ( had measuring on time this by 6.2 ns - see picture )
fastest:
instructions: 4
80 MHz : 12.5ns * 4 = 50 ns
160 MHz : 6.5 ns * 4 = 26 ns ( 6.25 * 4 = 25 ns )
optimated
instructions: 8
80 MHz : 12.5ns * 8 = 100 ns
160 MHz : 6.5 ns * 8 = 52 ns ( 6.25 * 8 = 50 ns )
and does a little be more better as your cool thing with .28 us ( 280 ns )
..
state to high speed usb:
-------------------------------
without DMA and Core 160MHz
without drops - tricks
and with asm blocks
custom Instructions: 6.25ns
bit flow for 1 bit data read:
---------------------------
ISR Fired:
fired 6.25
nop 6.25
clear 6.25
nop 6.25
attach 6.25
nop 6.25
Clock:
low 6.25
nop 6.25
high 6.25
nop 6.25
Data read:
get pin 6.25
nop 6.25
shift pin 6.25
nop 6.25
-----------------------------
14 * 6.5 87.5 ns ( full clock )
87.5 ns * 8 = 700 ns
8 Bit = 0.700 us
1 ms = 1000 * 8 / 0.700 = 11428 Bit / ms
1 s 11428 * 1000 = 11 428 000 Bit/s
11 428 000 Bit/s = 11.428 MBit/s
Code:
static inline unsigned get_ccount(void)
{
unsigned r;
asm volatile ("rsr %0, ccount" : "=r"(r));
return r;
}
the interrupt delay or the GPIO read is too slow. even without debug prints. how do you read/set the GPIO in assembler? in your code I see you use the "normal" GPIO_INPUT_GET function. this is much too slow even with 160MHz. Do you agree?
Can you show me how you do it faster?
Statistics: Posted by rudi — Sat Nov 26, 2016 5:31 am
Statistics: Posted by dkaufmann — Tue Nov 22, 2016 3:44 pm
Code:
// ---------------- Interrupt Service Routine ISR -----------
void gpio_intrHandlerCB (void)
{
// variables
uint8 temp_SDA = GPIO_INPUT_GET(I2C_SDA_PIN);
uint8 temp_SCK = GPIO_INPUT_GET(I2C_SCK_PIN);
i2c_state_t i2c_state = REC_ADDR;
uint8 bit_cntr = 0; // counts clock edges to read data
uint8 byte_cntr = 0; // counts databytes
uint8 i2c_address = 0; // 8 Bit without R/W
uint8 i2c_rec_data = 0; // 8 Bit receive data
uint8 i2c_rwn = 0; // 0: write, 1: read
uint8 i2c_stop = 0; // stop signal
uint16 i2c_TO_cntr = 0;
// read GPIO status register to check which line had an interrupt
uint32 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
// handle SDA Pin Interrupt
//-----------------------------------------------------------------------
if ( (gpio_status & BIT(I2C_SDA_PIN)) && (temp_SCK)) // if SCL = high : START
{
//GPIO_OUTPUT_SET(DEBUG_PIN4, 1);
//GPIO_OUTPUT_SET(DEBUG_PIN4, 0);
// disable interrupt on SDA pin only when START or STOP received
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SDA_PIN), GPIO_PIN_INTR_DISABLE);
if (temp_SDA) // if SDA rising: STOP
{
i2c_stop = 1;
//enable START interrupt again
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SDA_PIN), GPIO_PIN_INTR_ANYEDGE);
}
else // START
{
while (!i2c_stop)
{
switch (i2c_state)
{
case REC_ADDR:
//on next pos edge on SCL: read addr
for (bit_cntr = 0; bit_cntr<7; bit_cntr++)
{
// read 7 bit address
// wait for falling edge
i2c_TO_cntr = 0;
while (GPIO_INPUT_GET(I2C_SCK_PIN) || i2c_TO_cntr >= I2C_TIMEOUT) {
i2c_TO_cntr++;
os_delay_us(1);
}
// wait for rising edge
i2c_TO_cntr = 0;
while (!GPIO_INPUT_GET(I2C_SCK_PIN) || i2c_TO_cntr >= I2C_TIMEOUT) {
i2c_TO_cntr++;
os_delay_us(1);
}
i2c_address |= (((uint8) (GPIO_INPUT_GET(I2C_SDA_PIN))) << (6-bit_cntr));
}
if (i2c_address == I2C_SLAVEADDR)
{
i2c_state = READ_RW;
}
else
{
i2c_state = REC_ADDR; // init start state
i2c_stop = 1; // leave ISR
//enable START interrupt again
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SDA_PIN), GPIO_PIN_INTR_ANYEDGE);
};
break;
case READ_RW: // read the rwn bit (0 = MASTER write, 1 = MASTER read)
// wait for falling edge
i2c_TO_cntr = 0;
while (GPIO_INPUT_GET(I2C_SCK_PIN) || i2c_TO_cntr >= I2C_TIMEOUT) {
i2c_TO_cntr++;
os_delay_us(1);
}
// wait for rising edge
i2c_TO_cntr = 0;
while (!GPIO_INPUT_GET(I2C_SCK_PIN) || i2c_TO_cntr >= I2C_TIMEOUT) {
i2c_TO_cntr++;
os_delay_us(1);
}
i2c_rwn = GPIO_INPUT_GET(I2C_SDA_PIN); // read databit
byte_cntr=0; // reset databyte counter
i2c_state = SEND_ACK;
break;
case SEND_ACK:
// wait for falling edge
i2c_TO_cntr = 0;
while (GPIO_INPUT_GET(I2C_SCK_PIN) || i2c_TO_cntr >= I2C_TIMEOUT) {
i2c_TO_cntr++;
os_delay_us(1);
}
GPIO_OUTPUT_SET(I2C_SDA_PIN, 0); // ACK = SDA low
GPIO_OUTPUT_SET(I2C_INT_PIN, 1); // release interrupt line after receiving correct address
if (i2c_rwn) // SEND_DATA?
{
i2c_state = SEND_DATA; // = MASTER READ DATA
}
else // Receive data
{
i2c_state = REC_DATA; // = MASTER WRITE DATA
}
break;
case SEND_DATA: // C5
// Slave sends Data to master: MSB first
for (bit_cntr = 0; bit_cntr < 8; bit_cntr++)
{
// wait for rising edge
i2c_TO_cntr = 0;
while (!GPIO_INPUT_GET(I2C_SCK_PIN) || i2c_TO_cntr >= I2C_TIMEOUT) {
i2c_TO_cntr++;
os_delay_us(1);
}
// wait for falling edge
i2c_TO_cntr = 0;
while (GPIO_INPUT_GET(I2C_SCK_PIN) || i2c_TO_cntr >= I2C_TIMEOUT) {
i2c_TO_cntr++;
os_delay_us(1);
}
// write data on falling edge
GPIO_OUTPUT_SET(I2C_SDA_PIN, (i2c_TxBuf[byte_cntr]&(0x80 >> bit_cntr)?1:0)); // shift out data: if true = 1 else = 0
}
// check ACK
// wait for rising edge
i2c_TO_cntr = 0;
while (!GPIO_INPUT_GET(I2C_SCK_PIN) || i2c_TO_cntr >= I2C_TIMEOUT) {
i2c_TO_cntr++;
os_delay_us(1);
}
// wait for falling edge
i2c_TO_cntr = 0;
while (GPIO_INPUT_GET(I2C_SCK_PIN) || i2c_TO_cntr >= I2C_TIMEOUT) {
i2c_TO_cntr++;
os_delay_us(1);
}
GPIO_OUTPUT_SET(I2C_SDA_PIN,1); // release SDA Pin
// wait for rising edge
i2c_TO_cntr = 0;
while (!GPIO_INPUT_GET(I2C_SCK_PIN) || i2c_TO_cntr >= I2C_TIMEOUT) {
i2c_TO_cntr++;
os_delay_us(1);
}
if (!GPIO_INPUT_GET(I2C_SDA_PIN)) // ACK:
{
byte_cntr++;
}
else // NACK: END SEND DATA
{
byte_cntr=0; // reset byte counter
i2c_stop = 1;
//enable START interrupt again to read master's answer
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SDA_PIN), GPIO_PIN_INTR_ANYEDGE);
};
break;
case REC_DATA: // C4 -> MASTER WRITE
//Slave reads 8 databit from master
// wait for rising edge
i2c_TO_cntr = 0;
while (!GPIO_INPUT_GET(I2C_SCK_PIN) || i2c_TO_cntr >= I2C_TIMEOUT) {
i2c_TO_cntr++;
os_delay_us(1);
}
for (bit_cntr = 0; bit_cntr < 8; bit_cntr++)
{
temp_SDA = GPIO_INPUT_GET(I2C_SDA_PIN);
i2c_TO_cntr = 0;
while (GPIO_INPUT_GET(I2C_SCK_PIN) || i2c_TO_cntr >= I2C_TIMEOUT) // wait for falling edge (end ack read)
{
i2c_TO_cntr++; // increase time out counter
os_delay_us(1);
// during high: check if data did not change -> STOP
if (temp_SDA != GPIO_INPUT_GET(I2C_SDA_PIN)){
i2c_stop = 1;
i2c_RxCount = byte_cntr+1;
i2c_rec_done = 1;
break;
}
}
if (i2c_stop) // if STOP occured, leave loop
break;
// release SDA pin on falling SCL edge:
GPIO_OUTPUT_SET(I2C_SDA_PIN, 1); // release I2C_SDA_PIN
// wait for rising edge
i2c_TO_cntr = 0;
while (!GPIO_INPUT_GET(I2C_SCK_PIN) || i2c_TO_cntr >= I2C_TIMEOUT) {
i2c_TO_cntr++;
os_delay_us(1);
}
i2c_rec_data |= (((uint8) (GPIO_INPUT_GET(I2C_SDA_PIN))) << (7-bit_cntr));
}
i2c_RxBuf[byte_cntr]=i2c_rec_data; // store received databyte
byte_cntr++; // increase databyte counter
i2c_rec_data = 0; // reset received databyte
i2c_state = SEND_ACK;
break;
default:
i2c_state = REC_ADDR;
} // end switch
} // end while
// state machine end: stop occured:
i2c_stop = 0; // reset stop flag
i2c_state = REC_ADDR; // init state
i2c_rec_data = 0;
i2c_address = 0;
};
//clear interrupt status for GPIOx (SDA)
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status & BIT(I2C_SDA_PIN));
}
Statistics: Posted by dkaufmann — Mon Nov 21, 2016 4:47 pm
Statistics: Posted by Guest — Thu Nov 03, 2016 4:58 pm
Statistics: Posted by martinayotte — Tue Nov 01, 2016 1:58 am
Statistics: Posted by rudi — Fri Oct 28, 2016 10:24 pm
rudi wrote:martinayotte wrote:Rudi, did you got chance to upload your I2CSlave code somewhere ?
edit:
the missunderstand was cleaned now.
lets see what happens.
rudi
Statistics: Posted by rudi — Fri Oct 28, 2016 12:58 am
martinayotte wrote:Rudi, did you got chance to upload your I2CSlave code somewhere ?
Statistics: Posted by martinayotte — Fri Oct 28, 2016 12:21 am
Statistics: Posted by rudi — Thu Oct 27, 2016 1:22 am
Statistics: Posted by dkaufmann — Wed Oct 26, 2016 10:46 pm
Code:
_l8ui a0, a11, GPIO_OFFSET_INPUT
Code:
static inline unsigned get_ccount(void)
{
unsigned r;
asm volatile ("rsr %0, ccount" : "=r"(r));
return r;
}
Code:
..
t1 = system_get_time(); // API get time
// start
tick1 = get_ccount(); // Spezial Register CCOUNT Abruf und Übertrag / call and get
while (mtick < 100 )
{
// empty
mtick++;
}
t2 = system_get_time(); // API get time
tickdiff = tick2 - tick1; // Wieviel Ticks verbraucht / how many ticks used..
..
Statistics: Posted by rudi — Wed Oct 26, 2016 10:01 pm
Statistics: Posted by dkaufmann — Wed Oct 26, 2016 7:55 pm
Statistics: Posted by rudi — Wed Oct 26, 2016 5:55 pm
Statistics: Posted by dkaufmann — Wed Oct 26, 2016 5:15 pm
Code:
// PIN SETUP..
// (c) dkaufmann, 25.10.2016, Zürich, Switzerland
//SDA on GPIO12
#define I2C_SDA_PIN 12
#define I2C_SDA_MUX PERIPHS_IO_MUX_MTDI_U
#define I2C_SDA_FUNC FUNC_GPIO12
//SCK on GPIO14
#define I2C_SCK_PIN 14
#define I2C_SCK_MUX PERIPHS_IO_MUX_MTMS_U
#define I2C_SCK_FUNC FUNC_GPIO14
Code:
// rudi
// header
#define I2C_SLAVE_SDA_MUX PERIPHS_IO_MUX_MTMS_U //CONFIG THE GPIO MUX HERE
#define I2C_SLAVE_SDL_MUX PERIPHS_IO_MUX_MTCK_U //CONFIG THE GPIO MUX HERE
#define I2C_SLAVE_SDA_GPIO 12 //CONFIG THE GPIO NUMBER HERE
#define I2C_SLAVE_SDL_GPIO 14 //CONFIG THE GPIO NUMBER HERE
// c.file
//SET_PERI_REG_MASK(I2C_SLAVE_SDA_MUX, 0x30);
WRITE_PERI_REG(I2C_SLAVE_SDA_MUX, (READ_PERI_REG(I2C_SLAVE_SDA_MUX)&0xfffffe0f)|0x30);
//SET_PERI_REG_MASK(I2C_SLAVE_SDL_MUX, 0x30);
WRITE_PERI_REG(I2C_SLAVE_SDL_MUX, (READ_PERI_REG(I2C_SLAVE_SDL_MUX)&0xfffffe0f)|0x30);
Code:
// (c) dkaufmann, 25.10.2016, Zürich, Switzerland
//Set SDA as open drain
GPIO_REG_WRITE(
GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_SDA_PIN)),
GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_SDA_PIN))) |
GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)
);
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << I2C_SDA_PIN));
GPIO_OUTPUT_SET(I2C_SDA_PIN, 1);
//Set SCK as open drain
GPIO_REG_WRITE(
GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_SCK_PIN)),
GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_SCK_PIN))) |
GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)
);
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << I2C_SCK_PIN));
GPIO_OUTPUT_SET(I2C_SCK_PIN, 1);
Code:
// rudi
GPIO_REG_WRITE(
GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_SLAVE_SDA_GPIO)),
GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_SLAVE_SDA_GPIO)))|
GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE));//open drain;
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS,GPIO_REG_READ(GPIO_ENABLE_ADDRESS)|(1<<I2C_SLAVE_SDA_GPIO) );
// set..step later
GPIO_REG_WRITE(
GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_SLAVE_SDL_GPIO)),
GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_SLAVE_SDL_GPIO)))|
GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE));//open drain;
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS,GPIO_REG_READ(GPIO_ENABLE_ADDRESS)|(1<<I2C_SLAVE_SDL_GPIO) );
// set..step later
// set pins high
// header
#define I2C_SLAVE_GPIO_SET(pin) \
gpio_output_set(1<<pin,0,1<<pin,0)
#define I2C_SLAVE_GPIO_CLR(pin) \
gpio_output_set(0,1<<pin,1<<pin,0)
#define I2C_SLAVE_GPIO_OUT(pin,val) \
if(val) I2C_SLAVE_GPIO_SET(pin);\
else I2C_SLAVE_GPIO_CLR(pin)
// c.file
I2C_SLAVE_GPIO_SET(I2C_SLAVE_SDA_GPIO);
I2C_SLAVE_GPIO_SET(I2C_SLAVE_SDL_GPIO);
Code:
// rudi
//for test
void read_gpio_sta()
{
ets_printf("gpio in reg : 0x%08x\n",GPIO_REG_READ(GPIO_IN_ADDRESS));
ets_printf("gpio out reg : 0x%08x\n\n",GPIO_REG_READ(GPIO_OUT_ADDRESS));
ets_printf("sda reg set : 0x%08x \n",GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_SLAVE_SDA_GPIO))) );
ets_printf("sdl reg set : 0x%08x \n",GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_SLAVE_SDL_GPIO))) );
}
Code:
// **************************************************
// (c) eMbeddedHome rudi ;-) 07.May 2016
// **************************************************
//** v.0.1
//** ISR for SDA and SCL
//** ===================
//** simple protokol
//** Master send Start
//** Master send addr - Slave check it with ACK/NACK
//** if a write command
//** Master send data - Slave receive it
//** Master send Stop
// **************************************************
void i2c_slave_isr() {
u8 scl=0;
u8 sda=0;
u32 gpio_status = 0;
// welchen read/write Status?
static u8 write_read=0;
// LAST
// 0 = mehr daten
// 1 = waren letze daten
static nLast = 1; // vorgabe mal explizit
gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
ETS_GPIO_INTR_DISABLE() ;
scl=GPIO_INPUT_GET(GPIO_ID_PIN(I2C_SLAVE_SDL_GPIO));
sda=GPIO_INPUT_GET(GPIO_ID_PIN(I2C_SLAVE_SDA_GPIO));
// ets_printf("ISR fired..\n\0");
// ets_printf("%lu fired\n\0", gpio_status);
if(( (gpio_status>>I2C_SLAVE_SDA_GPIO)& BIT0)&&scl) //SDA trigger and sdl high
{
if( sda )// sda posedge , stop
{
ets_printf("stop..\n\0");
// if (startphase == 0) {
//* I2C_SLAVE_STATE = I2C_SLAVE_STATE_IDLE;
I2C_SLAVE_NEXTSTEP = nsWAITING_IDLE;
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDA_GPIO),GPIO_PIN_INTR_NEGEDGE);
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDL_GPIO),GPIO_PIN_INTR_DISABLE);
; // return;
}
else //sda negedge,start
{
ets_printf("start..\n\0");
// if (!startphase) { startphase = 1;
// I2C_SLAVE_STATE = I2C_SLAVE_STATE_RX_ADDR;
// allways at start:
I2C_SLAVE_NEXTSTEP = nsADDR1;
I2C_SLAVE_PING = ADI;
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDA_GPIO),GPIO_PIN_INTR_DISABLE);
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDL_GPIO),GPIO_PIN_INTR_POSEDGE);
; // return;
}
}
else if ( (gpio_status>>I2C_SLAVE_SDL_GPIO)& BIT0) //SDL trigger
{
// TO DO:
// nur antworten wenn ein START vorhanden war
// ansonsten der SLAVE alles mitprotokolliert
// .... see next part...
// switch (I2C_SLAVE_NEXTSTEP) {
Code:
switch (I2C_SLAVE_NEXTSTEP) {
case nsADDR1 : rx_addr = 0;
startphase = 3;
rx_addr = (rx_addr << 1 ) | sda ;
I2C_SLAVE_NEXTSTEP = nsADDR2;
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDA_GPIO),GPIO_PIN_INTR_DISABLE);
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDL_GPIO),GPIO_PIN_INTR_POSEDGE);
break; // return;
case nsADDR2 : rx_addr = (rx_addr << 1 ) | sda ;
I2C_SLAVE_NEXTSTEP = nsADDR3;
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDA_GPIO),GPIO_PIN_INTR_DISABLE);
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDL_GPIO),GPIO_PIN_INTR_POSEDGE);
break; // return;
case nsADDR3 : rx_addr = (rx_addr << 1 ) | sda ;
I2C_SLAVE_NEXTSTEP = nsADDR4;
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDA_GPIO),GPIO_PIN_INTR_DISABLE);
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDL_GPIO),GPIO_PIN_INTR_POSEDGE);
break; // return;
case nsADDR4 : rx_addr = (rx_addr << 1 ) | sda ;
I2C_SLAVE_NEXTSTEP = nsADDR5;
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDA_GPIO),GPIO_PIN_INTR_DISABLE);
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDL_GPIO),GPIO_PIN_INTR_POSEDGE);
break; // return;
case nsADDR5 : rx_addr = (rx_addr << 1 ) | sda ;
I2C_SLAVE_NEXTSTEP = nsADDR6;
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDA_GPIO),GPIO_PIN_INTR_DISABLE);
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDL_GPIO),GPIO_PIN_INTR_POSEDGE);
break; // return;
case nsADDR6 : rx_addr = (rx_addr << 1 ) | sda ;
I2C_SLAVE_NEXTSTEP = nsADDR7;
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDA_GPIO),GPIO_PIN_INTR_DISABLE);
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDL_GPIO),GPIO_PIN_INTR_POSEDGE);
break; // return;
case nsADDR7 : rx_addr = (rx_addr << 1 ) | sda ;
I2C_SLAVE_NEXTSTEP = nsADDR8;
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDA_GPIO),GPIO_PIN_INTR_DISABLE);
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDL_GPIO),GPIO_PIN_INTR_POSEDGE);
break; // return;
case nsADDR8 : rx_addr = (rx_addr << 1 ) | sda ;
// addr match
if ( !1 || ((rx_daten & 0xfe) == I2C_SLAVE_ADDRESS)) // write & read adress is checked here
{ // addr missmatch
ets_printf("rx_addr 0x%2x not match \n\0", rx_addr);
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDA_GPIO),GPIO_PIN_INTR_NEGEDGE); // important thing
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDL_GPIO),GPIO_PIN_INTR_DISABLE);
goto missmatch;
break;
}
else
{
ets_printf("wAdmatch:0x%2x\n\0", rx_addr);
I2C_SLAVE_GPIO_OUT(12,0); // send ACK low
rx_addr = 0;
// Neue VAR write_read
// I2C_SLAVE_COMMAND = WRITE;
// write_read = 1;
I2C_SLAVE_NEXTSTEP = nsADDR9;
CALLED = ad8;
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDA_GPIO),GPIO_PIN_INTR_DISABLE);
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDL_GPIO),GPIO_PIN_INTR_NEGEDGE); // important thing
}
break; // return;
case nsADDR9 : if(!CALLED==ad8) ets_printf("false route from %d \n\0", CALLED);
// GO I2C_SLAVE_GPIO_OUT(12,0);
// check read or write
if ( 1 & rx_addr) // its a read from Slave by the Master
{
I2C_SLAVE_COMMAND = READ;
I2C_SLAVE_NEXTSTEP = nsADDR1; // bzw IDLE
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDA_GPIO),GPIO_PIN_INTR_DISABLE);
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDL_GPIO),GPIO_PIN_INTR_POSEDGE);
}
else // its a write from Master to Slave
{
ACK1;
I2C_SLAVE_COMMAND = WRITE;
I2C_SLAVE_NEXTSTEP = nsDATA1;
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDA_GPIO),GPIO_PIN_INTR_ANYEDGE); // important
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDL_GPIO),GPIO_PIN_INTR_POSEDGE); // important
}
break;
...
...
Code:
...
...
case nsIDLE : // DO NOTHING
ets_printf("nsIDLE\n\0");
break;
case nsWAITING_IDLE : // nothing sollte stop werden
ets_printf("%d: nsWaiting_IDLE \n\0", CALLED);
break;
default : ets_printf("default\n\0");
}
}
missmatch:
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status);
ETS_GPIO_INTR_ENABLE() ;
}
// *******************************************
// last edit 7 May 2016
//
// *******************************************
Code:
// rudi
typedef enum{
nsSTART,
nsSTOP,
nsADDR1,
nsADDR2,
nsADDR3,
nsADDR4,
nsADDR5,
nsADDR6,
nsADDR7,
nsADDR8,
nsADDR9,
nsADDR9A,
nsADDR10,
nsDATA1,
nsDATA2,
nsDATA3,
nsDATA4,
nsDATA5,
nsDATA6,
nsDATA7,
nsDATA8,
nsDATA9,
nsDATA9A,
nsDATA10,
nsWDATA1,
nsWDATA2,
nsWDATA3,
nsWDATA4,
nsWDATA5,
nsWDATA6,
nsWDATA7,
nsWDATA8,
nsWDATA9,
nsWDATA10,
nsACK_A,
nsACK_B,
nsNACK_A,
nsNACK_B,
nsLAST_ADDR,
nsLAST_DATA,
nsFALSE_TRIGGER,
nsWAITING_IDLE,
nsCHECK_ADDRESS_MATCH,
nsIDLE
}I2C_SLAVE_STEPS;
typedef enum {
WRITE,
READ,
IDLE
} I2C_SLAVE_COMMANDS;
// rudi
// simple
#define I2C_START_DEDECTED 1
#define I2C_STOP_DEDECTED 2
#define I2C_ADDR_MISMATCH 3
#define I2C_SLAVE_ADDRESS 0x30
#define SINGLE 1 // in this code, one Byte transfer -> means SendStart SendAddr, SendByte, SendStop
Statistics: Posted by rudi — Wed Oct 26, 2016 5:05 am
Code:
//Set SDA as open drain
GPIO_REG_WRITE(
GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_SDA_PIN)),
GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_SDA_PIN))) |
GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)
);
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << I2C_SDA_PIN));
GPIO_OUTPUT_SET(I2C_SDA_PIN, 1);
//Set SCK as open drain
GPIO_REG_WRITE(
GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_SCK_PIN)),
GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_SCK_PIN))) |
GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)
);
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << I2C_SCK_PIN));
GPIO_OUTPUT_SET(I2C_SCK_PIN, 1);
Statistics: Posted by dkaufmann — Tue Oct 25, 2016 5:04 pm
Code:
//SDA on GPIO12
#define I2C_SDA_PIN 12
#define I2C_SDA_MUX PERIPHS_IO_MUX_MTDI_U
#define I2C_SDA_FUNC FUNC_GPIO12
//SCK on GPIO14
#define I2C_SCK_PIN 14
#define I2C_SCK_MUX PERIPHS_IO_MUX_MTMS_U
#define I2C_SCK_FUNC FUNC_GPIO14
Statistics: Posted by dkaufmann — Tue Oct 25, 2016 4:07 pm
Code:
ETS_GPIO_INTR_ATTACH(gpio_intrHandlerCB, NULL); //Register the interrupt function
ETS_GPIO_INTR_ENABLE() ; //Enable the GPIO interrupt in general
// enable interrupt on SDA negative edge to detect start
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SDA_PIN), GPIO_PIN_INTR_NEGEDGE);
Code:
// (c) dkaufmann, 25.10.2016, Zürich, Switzerland
// ---------------- Interrupt Service Routine ISR -----------
void gpio_intrHandlerCB (void)
{
// variables
// define I2C-SLAVE states
typedef enum { REC_ADDR,
READ_RW,
SEND_ACK,
REC_DATA,
SEND_DATA
} i2c_state_t;
i2c_state_t i2c_state = REC_ADDR;
uint8 bit_cntr = 0; // counts clock edges to read data
uint8 byte_cntr = 0; // counts databytes
uint8 i2c_address = 0; // 8 Bit without R/W
uint8 i2c_rec_data = 0; // 8 Bit receive data
uint8 i2c_rwn = 0; // 0: write, 1: read
uint8 i2c_stop = 0; // stop signal
uint8 temp = 0;
// read GPIO status register to check which line had an interrupt
uint32 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
// handle SDA Pin Interrupt
//-----------------------------------------------------------------------
if (gpio_status & BIT(I2C_SDA_PIN)) // if (neg) edge SDA interrupt
{
if (GPIO_INPUT_GET(I2C_SCK_PIN)) // if SCK high: start
{
// disable interrupt on SDA pin only when START received
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SDA_PIN), GPIO_PIN_INTR_DISABLE);
while (!i2c_stop)
{
switch (i2c_state)
{
case REC_ADDR:
//on next pos edge on SCL: read addr
for (bit_cntr = 0; bit_cntr<7; bit_cntr++)
{
//read 7 bit address
while (GPIO_INPUT_GET(I2C_SCK_PIN)); // wait for falling edge
while (!GPIO_INPUT_GET(I2C_SCK_PIN)); // wait for rising edge
i2c_address |= (((uint8) (GPIO_INPUT_GET(I2C_SDA_PIN))) << (6-bit_cntr));
}
if (i2c_address == I2C_SLAVEADDR)
{
i2c_state = READ_RW;
}
else
{
i2c_state = REC_ADDR; // init start state
i2c_stop = 1; // leave ISR
//enable START interrupt again
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SDA_PIN), GPIO_PIN_INTR_NEGEDGE);
};
break;
case READ_RW: // read the rwn bit (0 = MASTER write, 1 = MASTER read)
while (GPIO_INPUT_GET(I2C_SCK_PIN)); // wait for falling edge
while (!GPIO_INPUT_GET(I2C_SCK_PIN)); // wait for rising edge
i2c_rwn = GPIO_INPUT_GET(I2C_SDA_PIN); // read databit
byte_cntr=0; // reset databyte counter
i2c_state = SEND_ACK;
break;
case SEND_ACK:
while (GPIO_INPUT_GET(I2C_SCK_PIN));// wait for falling edge
GPIO_OUTPUT_SET(I2C_SDA_PIN, 0); // ACK = SDA low
if (i2c_rwn) // SEND_DATA?
{
i2c_state = SEND_DATA; // = MASTER READ DATA
}
else // Receive data
{
i2c_state = REC_DATA; // = MASTER WRITE DATA
}
break;
case SEND_DATA: // C5
// Slave sends Data to master: MSB first
for (bit_cntr = 0; bit_cntr < 8; bit_cntr++)
{
while (!GPIO_INPUT_GET(I2C_SCK_PIN)); // wait for rising edge
while (GPIO_INPUT_GET(I2C_SCK_PIN)); // wait for falling edge
// write data on falling edge
GPIO_OUTPUT_SET(I2C_SDA_PIN, (i2c_TxBuf[byte_cntr]&(0x80 >> bit_cntr)?1:0)); // shift out data: if true = 1 else = 0
}
// check ACK
while (!GPIO_INPUT_GET(I2C_SCK_PIN)); // wait for rising edge - Master reads
while (GPIO_INPUT_GET(I2C_SCK_PIN)); // wait for falling edge - Master ends read
GPIO_OUTPUT_SET(I2C_SDA_PIN,1); // release SDA Pin
while (!GPIO_INPUT_GET(I2C_SCK_PIN)); // wait for rising edge
if (!GPIO_INPUT_GET(I2C_SDA_PIN)) // ACK:
{
byte_cntr++;
}
else // NACK: END SEND DATA
{
byte_cntr=0; // reset byte counter
i2c_stop = 1;
//enable START interrupt again to read master's answer
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SDA_PIN), GPIO_PIN_INTR_NEGEDGE);
};
break;
case REC_DATA: // C4 -> MASTER WRITE
//Slave reads 8 databit from master
while (!GPIO_INPUT_GET(I2C_SCK_PIN)); // wait for rising edge (ACK read)
for (bit_cntr = 0; bit_cntr < 8; bit_cntr++)
{
temp = GPIO_INPUT_GET(I2C_SDA_PIN);
while (GPIO_INPUT_GET(I2C_SCK_PIN)) // wait for falling edge (end ack read)
{
// during high: check if data did not change -> STOP
if (temp != GPIO_INPUT_GET(I2C_SDA_PIN)){
i2c_stop = 1;
i2c_RxCount = byte_cntr+1;
i2c_rec_done = 1;
break;
}
}
if (i2c_stop) // if STOP occured, leave loop
break;
// release SDA pin on falling SCL edge:
GPIO_OUTPUT_SET(I2C_SDA_PIN, 1); // release I2C_SDA_PIN
while (!GPIO_INPUT_GET(I2C_SCK_PIN)); // wait for rising edge
i2c_rec_data |= (((uint8) (GPIO_INPUT_GET(I2C_SDA_PIN))) << (7-bit_cntr));
}
i2c_RxBuf[byte_cntr]=i2c_rec_data; // store received databyte
byte_cntr++; // increase databyte counter
i2c_rec_data = 0; // reset received databyte
i2c_state = SEND_ACK;
break;
default:
i2c_state = REC_ADDR;
} // end switch
} // end while
// state machine end: stop occured:
i2c_stop = 0; // reset stop flag
i2c_state = REC_ADDR; // init state
i2c_rec_data = 0;
i2c_address = 0;
};
//clear interrupt status for GPIOx (SDA)
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status & BIT(I2C_SDA_PIN));
}
}
Statistics: Posted by dkaufmann — Tue Oct 25, 2016 3:58 pm
Statistics: Posted by apollo0226 — Tue Oct 25, 2016 11:01 am
Statistics: Posted by rudi — Tue Oct 25, 2016 3:59 am
Code:
if(( (gpio_status>>I2C_SLAVE_SDA_GPIO)& BIT0)&&scl) //SDA trigger and scl high
Code:
if( sda )// sda posedge , stop
{
ets_printf("stop..\n\0");
Code:
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDA_GPIO),GPIO_PIN_INTR_NEGEDGE);
gpio_pin_intr_state_set(GPIO_ID_PIN(I2C_SLAVE_SDL_GPIO),GPIO_PIN_INTR_DISABLE);
Code:
else //sda negedge,start
{
ets_printf("start..\n\0");
apollo0226 wrote:
So when the Interrupt first trigger , it must be start condition, because SCL is high, SDA is low.
apollo0226 wrote:
So I get the 8 bit and set ACK, this is slave address and R/W bit.
apollo0226 wrote:
I compare it , is this my slave address? if no ,
set the NACK and exit, If yes, go to check R/W bit to Read or Write.
If Read , get more data.
apollo0226 wrote:
a) My question is when do I stop ?
b) Checking SCL and SDA both high (STOP condition) in the SDA ISR ?
c) Do the SCL need to set to Interrupt ? if yes , active high or low? What do it do in SCL ISR?
d) If you give us the sample code , it will help a lot.
Statistics: Posted by rudi — Tue Oct 25, 2016 3:29 am
Statistics: Posted by apollo0226 — Mon Oct 24, 2016 10:54 pm
Statistics: Posted by rudi — Mon Oct 24, 2016 8:20 pm
Statistics: Posted by apollo0226 — Mon Oct 24, 2016 4:41 pm
Statistics: Posted by rudi — Sun Oct 23, 2016 4:38 pm
Code:
DeCoco wrote:
- if rising edge SDA and SCL = 1 : START condition
- if rising edge SCL: count a counter with each rising edge:
Statistics: Posted by rudi — Sun Oct 23, 2016 5:44 am
Statistics: Posted by Guest — Sun Oct 23, 2016 1:28 am
Code:
switch(rec_cntr) {
case 0 ... 7: // read address
os_printf("read i2c_address, counter = %d\n", rec_cntr);
break;
case 8: // check address, send ack if ok (0) or not (1)
os_printf("check i2c_address, counter = %d\n", rec_cntr);
break;
case 9 ... 16: // write databyte
os_printf("write data, counter = %d\n", rec_cntr);
break;
case 17: // read ACK (must be 0)
os_printf("read ack, counter = %d\n", rec_cntr);
break;
case 18: // read stop
os_printf("read stop, counter = %d\n", rec_cntr);
rec_cntr = 0; // reset rec_countr
break;
default: rec_cntr = 0; // reset rec_cntr
}
rec_cntr++; // increase counter
Statistics: Posted by Guest — Fri Oct 14, 2016 6:45 pm
Statistics: Posted by rudi — Tue Sep 27, 2016 6:27 pm
Statistics: Posted by rudi — Wed Sep 21, 2016 8:54 am
Statistics: Posted by rudi — Tue Sep 13, 2016 11:05 pm
Statistics: Posted by Dustupendr — Mon Aug 22, 2016 7:30 pm
Code:
// we include Headers here
#include <osapi.h>
#include <c_types.h>
#include <i2c_master.h>
// global vars
uint8 addr = 0x54;
uint8 cmdWrite = 0;
uint8 cmdRead = 1;
uint8 ACK = 0;
uint8 sendByte = 0;
uint32 counter()
{
static uint32 count = 0;
count++;
sendByte = count;
return count;
}
void i2c_talk()
{
i2c_master_start();
i2c_master_writeByte(addr+cmdWrite);
ACK = i2c_master_checkAck();
if (ACK)
{
os_printf("ACK ADDR True\n");
i2c_master_writeByte(sendByte);
}
else
{
os_printf("addr does not match\n");
}
i2c_master_stop();
}
void i2c_demo_init()
{
i2c_master_gpio_init();
os_delay_us(30 * 1000 );
i2c_master_init();
os_delay_us(30 * 1000 );
}
void user_init()
{
i2c_demo_init();
while (1)
{
os_printf("count: %d\n", counter() );
i2c_talk(sendByte);
system_soft_wdt_feed();
os_delay_us(1 * 1000 * 1000);
}
}
Statistics: Posted by rudi — Mon Aug 01, 2016 8:01 pm
Statistics: Posted by rudi — Mon Aug 01, 2016 7:01 am
Code:
/* i2c_master_demo */
#include <osapi.h>
#include <c_types.h>
#include <i2c_master.h>
uint8 addr = 0x54;
uint8 cmdWrite = 0;
uint8 cmdRead = 1;
uint8 ACK = 0;
uint8 sendByte = 0;
uint32 counter()
{
static uint32 count = 0;
count++;
sendByte = count;
return count;
}
void i2c_talk()
{
i2c_master_start();
i2c_master_writeByte(addr+cmdWrite);
ACK = i2c_master_checkAck();
if (ACK)
{
i2c_master_writeByte(sendByte);
os_printf("ACK ADDR True\n");
}
else
{
os_printf("addr does not match\n");
}
i2c_master_stop();
}
void i2c_demo_init()
{
/* FYI this function are extern from driver pack
void i2c_master_gpio_init(void);
void i2c_master_init(void);
#define i2c_master_wait os_delay_us
void i2c_master_stop(void);
void i2c_master_start(void);
void i2c_master_setAck(uint8 level);
uint8 i2c_master_getAck(void);
uint8 i2c_master_readByte(void);
void i2c_master_writeByte(uint8 wrdata);
bool i2c_master_checkAck(void);
void i2c_master_send_ack(void);
void i2c_master_send_nack(void); */
i2c_master_gpio_init();
os_delay_us(30 * 1000 );
i2c_master_init();
os_delay_us(30 * 1000 );
}
void user_rf_pre_init()
{
}
void user_init()
{
i2c_demo_init();
while (1)
{
os_printf("count: %d\n", counter() );
i2c_talk(sendByte);
// os_printf("hello world\n");;
system_soft_wdt_feed();;
// os_delay_us(1 * 1000 * 1000);;
os_delay_us(20 * 1000);;
}
}
Statistics: Posted by rudi — Mon Aug 01, 2016 6:44 am