I2C Slave Mode

dkaufmann
Posts: 11
Joined: Mon Sep 26, 2016 10:02 pm

Re: I2C Slave Mode

Postby dkaufmann » Wed Oct 26, 2016 10:46 pm

Hi Rudi,

okay I see. thanks for this one. Gonna try it out.

best regards
D.

User avatar
rudi
Posts: 197
Joined: Fri Oct 24, 2014 7:55 pm

Re: I2C Slave Mode

Postby rudi » Thu Oct 27, 2016 1:22 am

dkaufmann wrote:Hi Rudi,

okay I see. thanks for this one. Gonna try it out.

best regards
D.


one hint i get perhabs for you important too :)

- CCOUNT SR it's 32 bits
- overflow of CCOUNT detectable? -- no, there's nothing that can tell you about an overflow. No interrupt, no overflow bit.
- is there an interrupt for CCOUNT? Yes, there is a number of CCOMPARE SRs. You can write a value there and then an IRQ will be raised once CCOUNT reaches that value.

For more details please see xtensa ISA book (e.g. http://0x04.net/~mwk/doc/xtensa.pdf ), 4.4.6 Timer interrupt option.

have phun
best wishes

rudi ;-)

-------------------------------------
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪

User avatar
martinayotte
Posts: 10
Joined: Tue Nov 04, 2014 4:33 am

Re: I2C Slave Mode

Postby martinayotte » Fri Oct 28, 2016 12:21 am

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


I don't understand your above comment ...
My question was : do you have any github where we can look at your ESP8266 I2C Slave code ?

User avatar
rudi
Posts: 197
Joined: Fri Oct 24, 2014 7:55 pm

Re: I2C Slave Mode

Postby rudi » Fri Oct 28, 2016 12:58 am

martinayotte wrote:
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


I don't understand your above comment ...
My question was : do you have any github where we can look at your ESP8266 I2C Slave code ?


;-)
this was other theme - i have wait for the devkitc from john and want make a esp family i2c example,
but had not get .. this theme is cleared - not to do with you, martin, sry for the
confusion.

need we the github code any more?
we have here opendrain setup, ack , start, stop, isr and other as example.

best wishes
rudi ;-)

-------------------------------------
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪

User avatar
martinayotte
Posts: 10
Joined: Tue Nov 04, 2014 4:33 am

Re: I2C Slave Mode

Postby martinayotte » Fri Oct 28, 2016 10:05 pm

@Rudi, Few weeks ago, you were saying that you will share this I2C Slave code, and said that it should be after Chinese holiday ...

User avatar
rudi
Posts: 197
Joined: Fri Oct 24, 2014 7:55 pm

Re: I2C Slave Mode

Postby rudi » Fri Oct 28, 2016 10:24 pm

martinayotte wrote:@Rudi, Few weeks ago, you were saying that you will share this I2C Slave code, and said that it should be after Chinese holiday ...

edit:
yes i did this say.

read the code here - this is my share -

but me was say too, that i get devKitC,
but i have not get. so my thinked demo project i can not build.
this would be a gift on second birthday to bbs

i had pm you the things what happens, but you have not read more weeks.

at just in time - i get no devkitc from adafruit, olimex or espressif.
so - i cant build my thinked demo with all espressif boards
and i do not start again theme in esp8266 that was done in last year.. sry

and btw:
here now a part of detailed things in the thread that you not read on technicals docu.
- pin setup
- opendrain
- isr theme
- start, stop, addr, data

where is the problem now to build an own project with this as base?

if there is no understand for the code here,
there cant be an understand of the demo project too,
so please.

copy & paste is not good for teach.
so my steps are teached bit by bit with each instruction to do INTR on SDA, SCL
in v 0.1 for Start, Stop, Read cmd , Write cmd, SDA, SCL, Addr Match, ISR

your steps now: Data ( its the same principal ) and a idea what you do with I2C.
example send cmd by I2C Master to I2C Slave for AT Commands based on I2C.

i do nobody hims homework.
nobody pay me the time or gives me DevKitC to do the things...
and i am not work at espressif - i am customer like you.

sry

i do not more coment this theme here martin.
there stands all info to create a own I2C Slave.c and Header and demo project.

rudi

-------------------------------------
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪

User avatar
martinayotte
Posts: 10
Joined: Tue Nov 04, 2014 4:33 am

Re: I2C Slave Mode

Postby martinayotte » Tue Nov 01, 2016 1:58 am

I don't understand, I see an email from you on Oct 19, but it has been flag "deleted by you", so I can't read it.
You've said that you will share your code, but had never shared it.
Now, you are saying "i do nobody hims homework" ... :-(
With such attitude, probably yourself won't get any help from other when you will need it ...

davydnorris

Re: I2C Slave Mode

Postby davydnorris » Thu Nov 03, 2016 4:58 pm

martinayotte wrote:I don't understand, I see an email from you on Oct 19, but it has been flag "deleted by you", so I can't read it.
You've said that you will share your code, but had never shared it.
Now, you are saying "i do nobody hims homework" ... :-(
With such attitude, probably yourself won't get any help from other when you will need it ...


I have to say Martin, I don't think rudi will ever need much help from others - he is a legend, and a prolific poster here and in the other ESP forums. He has my respect big time!!

I took the info here and was able to get code running pretty quickly - I don't think there's anything missing from the explanations that I have found so far.

Big thanks rudi!!

User avatar
martinayotte
Posts: 10
Joined: Tue Nov 04, 2014 4:33 am

Re: I2C Slave Mode

Postby martinayotte » Sat Nov 05, 2016 5:06 am

He asked for help in the past, I've even help him once, but I don't think I will anymore.

dkaufmann
Posts: 11
Joined: Mon Sep 26, 2016 10:02 pm

Re: I2C Slave Mode

Postby dkaufmann » Mon Nov 21, 2016 4:47 pm

Dear all,

I also shared some code here about the I2C slave code. But I still have some troubles with interrupt latencies. Sometimes I detect wrong START messages because the delay of measuring the inputs is too bad. Any ideas how to avoid this problem? By the way, I measure the inputs right at the beginning of the ISR.

any help is appreciated. here is my code of the ISR:

Code: Select all

// ---------------- 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));
   }


Who is online

Users browsing this forum: No registered users and 2 guests