Wire ReSTART fix, with others (#1717)
* ReSTART fix, Sequencing fix pr #1665 introduce a problem with ReSTART, when solving this problem I found an interaction between the TxFifo refill, RxFifo empty and CMD[] fill. during certain sequences a dataqueue command would be skipped, this skipping resulted in a mismatch between the contents of the TxFifo and the i2c command sequence. The problem manifested as an ACK error. In addition to this required bug fix I propose: * `Wire.begin()` be changed from a `void` to a `bool` this will allow the reset functionality of `Wire.begin()` to be reported. Currently `Wire.begin()` attempts to reset the i2c Peripheral, but cannot report success/failure. * `Wire.busy()` be added. this `bool` function returns the hardware status of the bus. This status can be use in multi-master environments for application level interleaving of commands, also in single master environment, it can be used to detect a 'hung' bus. With the functional change to `Wire.begin()` this allows app level recover of a hung bus. * `Wire.lastError()` value updated for all errors, previously when interleaving `Wire.endTransmission(false)` and `Wire.readTransmission(false)`, the 128 byte `Wire.write()` buffer was exhausted without generating and error(very exotic). I discovered this error when I created a sequence of directed reads to a EEPROM. Each directed read used 2 bytes of the 128 byte `write()` buffer, so after 64 consecutive ReSTART writes with ReSTART reads, `Wire()` had no room to record the directed address bytes. It generated just a NAK check without setting the EEPROMs internal register address. The succeeding ReSTART read succeeded at incorrect address. * Changes to the HAL layer: ** added `i2cGetStatus()` which returns the i2c peripheral status word, used to detect bus_busy currently ** added `i2cDebug()` programmatic control of debug buffer output ** changed `i2cAddQueue()` to allow data_only queue element this will allow a i2c transaction to use multiple data pointers. ** removed direct access to DumpInts(), DumpI2c() from app, use i2cDebug() to set trigger points * * Update esp32-hal-i2c.c * Update Wire.cpp * ReSTART, Sequencing pr #1665 introduce a problem with ReSTART, when solving this problem I found an interaction between the TxFifo refill, RxFifo empty and CMD[] fill. during certain sequences a dataqueue command would be skipped, this skipping resulted in a mismatch between the contents of the TxFifo and the i2c command sequence. The problem manifested as an ACK error. In addition to this required bug fix I propose: * `Wire.begin()` be changed from a `void` to a `bool` this will allow the reset functionality of `Wire.begin()` to be reported. Currently `Wire.begin()` attempts to reset the i2c Peripheral, but cannot report success/failure. * `Wire.busy()` be added. this `bool` function returns the hardware status of the bus. This status can be use in multi-master environments for application level interleaving of commands, also in single master environment, it can be used to detect a 'hung' bus. With the functional change to `Wire.begin()` this allows app level recover of a hung bus. * `Wire.lastError()` value updated for all errors, previously when interleaving `Wire.endTransmission(false)` and `Wire.readTransmission(false)`, the 128 byte `Wire.write()` buffer was exhausted without generating and error(very exotic). I discovered this error when I created a sequence of directed reads to a EEPROM. Each directed read used 2 bytes of the 128 byte `write()` buffer, so after 64 consecutive ReSTART writes with ReSTART reads, `Wire()` had no room to record the directed address bytes. It generated just a NAK check without setting the EEPROMs internal register address. The succeeding ReSTART read succeeded at incorrect address. * Changes to the HAL layer: ** added `i2cGetStatus()` which returns the i2c peripheral status word, used to detect bus_busy currently ** added `i2cDebug()` programmatic control of debug buffer output ** changed `i2cAddQueue()` to allow data_only queue element this will allow a i2c transaction to use multiple data pointers. ** removed direct access to DumpInts(), DumpI2c() from app, use i2cDebug() to set trigger points * * Forgot DebugFlags Return @andriyadi found this, total brain fade on my part.
This commit is contained in:
		
							parent
							
								
									e346f20aa9
								
							
						
					
					
						commit
						b05430cfd9
					
				@ -36,17 +36,21 @@
 | 
				
			|||||||
/* Stickbreaker ISR mode debug support
 | 
					/* Stickbreaker ISR mode debug support
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ENABLE_I2C_DEBUG_BUFFER
 | 
					ENABLE_I2C_DEBUG_BUFFER
 | 
				
			||||||
  Enable debug interrupt history buffer, setting this define will result in 1544 bytes of RAM
 | 
					  Enable debug interrupt history buffer, fifoTx history buffer.
 | 
				
			||||||
  being used whenever CORE_DEBUG_LEVEL is higher than WARNING. Unless you are debugging
 | 
					  Setting this define will result in 2570 bytes of RAM being used whenever CORE_DEBUG_LEVEL
 | 
				
			||||||
  a problem in the I2C subsystem I would recommend you leave it commented out.
 | 
					  is higher than WARNING. Unless you are debugging a problem in the I2C subsystem,
 | 
				
			||||||
 | 
					  I would recommend you leave it commented out.
 | 
				
			||||||
  */
 | 
					  */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//#define ENABLE_I2C_DEBUG_BUFFER
 | 
					//#define ENABLE_I2C_DEBUG_BUFFER
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO) && (defined ENABLE_I2C_DEBUG_BUFFER)
 | 
					#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO) && (defined ENABLE_I2C_DEBUG_BUFFER)
 | 
				
			||||||
#define INTBUFFMAX 64
 | 
					#define INTBUFFMAX 64
 | 
				
			||||||
 | 
					#define FIFOMAX 512
 | 
				
			||||||
static uint32_t intBuff[INTBUFFMAX][3][2];
 | 
					static uint32_t intBuff[INTBUFFMAX][3][2];
 | 
				
			||||||
static uint32_t intPos[2]= {0,0};
 | 
					static uint32_t intPos[2]= {0,0};
 | 
				
			||||||
 | 
					static uint16_t fifoBuffer[FIFOMAX];
 | 
				
			||||||
 | 
					static uint16_t fifoPos = 0;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// start from tools/sdk/include/soc/soc/i2c_struct.h
 | 
					// start from tools/sdk/include/soc/soc/i2c_struct.h
 | 
				
			||||||
@ -154,7 +158,7 @@ typedef union {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// individual dq element
 | 
					// individual dq element
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    uint8_t *data;           // datapointer for read/write buffer
 | 
					    uint8_t *data;           // data pointer for read/write buffer
 | 
				
			||||||
    uint16_t length;         // size of data buffer
 | 
					    uint16_t length;         // size of data buffer
 | 
				
			||||||
    uint16_t position;       // current position for next char in buffer (<length)
 | 
					    uint16_t position;       // current position for next char in buffer (<length)
 | 
				
			||||||
    uint16_t cmdBytesNeeded; // used to control number of I2C_COMMAND_t blocks added to queue
 | 
					    uint16_t cmdBytesNeeded; // used to control number of I2C_COMMAND_t blocks added to queue
 | 
				
			||||||
@ -179,9 +183,10 @@ struct i2c_struct_t {
 | 
				
			|||||||
    I2C_DATA_QUEUE_t * dq;
 | 
					    I2C_DATA_QUEUE_t * dq;
 | 
				
			||||||
    uint16_t queueCount; // number of dq entries in queue.
 | 
					    uint16_t queueCount; // number of dq entries in queue.
 | 
				
			||||||
    uint16_t queuePos; // current queue that still has or needs data (out/in)
 | 
					    uint16_t queuePos; // current queue that still has or needs data (out/in)
 | 
				
			||||||
    uint16_t errorByteCnt;  // count of bytes moved (both in and out)
 | 
					    int16_t  errorByteCnt;  // byte pos where error happened, -1 devId, 0..(length-1) data
 | 
				
			||||||
    uint16_t errorQueue; // errorByteCnt is in this queue,(for error locus)
 | 
					    uint16_t errorQueue; // errorByteCnt is in this queue,(for error locus)
 | 
				
			||||||
    uint32_t exitCode;
 | 
					    uint32_t exitCode;
 | 
				
			||||||
 | 
					    uint32_t debugFlags;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
@ -197,16 +202,16 @@ enum {
 | 
				
			|||||||
#define I2C_MUTEX_UNLOCK()
 | 
					#define I2C_MUTEX_UNLOCK()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static i2c_t _i2c_bus_array[2] = {
 | 
					static i2c_t _i2c_bus_array[2] = {
 | 
				
			||||||
    {(volatile i2c_dev_t *)(DR_REG_I2C_EXT_BASE_FIXED), 0, -1, -1,I2C_NONE,I2C_NONE,I2C_ERROR_OK,NULL,NULL,NULL,0,0,0,0},
 | 
					    {(volatile i2c_dev_t *)(DR_REG_I2C_EXT_BASE_FIXED), 0, -1, -1,I2C_NONE,I2C_NONE,I2C_ERROR_OK,NULL,NULL,NULL,0,0,0,0,0},
 | 
				
			||||||
    {(volatile i2c_dev_t *)(DR_REG_I2C1_EXT_BASE_FIXED), 1, -1, -1,I2C_NONE,I2C_NONE,I2C_ERROR_OK,NULL,NULL,NULL,0,0,0,0}
 | 
					    {(volatile i2c_dev_t *)(DR_REG_I2C1_EXT_BASE_FIXED), 1, -1, -1,I2C_NONE,I2C_NONE,I2C_ERROR_OK,NULL,NULL,NULL,0,0,0,0,0}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
#define I2C_MUTEX_LOCK()    do {} while (xSemaphoreTake(i2c->lock, portMAX_DELAY) != pdPASS)
 | 
					#define I2C_MUTEX_LOCK()    do {} while (xSemaphoreTake(i2c->lock, portMAX_DELAY) != pdPASS)
 | 
				
			||||||
#define I2C_MUTEX_UNLOCK()  xSemaphoreGive(i2c->lock)
 | 
					#define I2C_MUTEX_UNLOCK()  xSemaphoreGive(i2c->lock)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static i2c_t _i2c_bus_array[2] = {
 | 
					static i2c_t _i2c_bus_array[2] = {
 | 
				
			||||||
    {(volatile i2c_dev_t *)(DR_REG_I2C_EXT_BASE_FIXED), NULL, 0, -1, -1, I2C_NONE,I2C_NONE,I2C_ERROR_OK,NULL,NULL,NULL,0,0,0,0,0},
 | 
					    {(volatile i2c_dev_t *)(DR_REG_I2C_EXT_BASE_FIXED), NULL, 0, -1, -1, I2C_NONE,I2C_NONE,I2C_ERROR_OK,NULL,NULL,NULL,0,0,0,0,0,0},
 | 
				
			||||||
    {(volatile i2c_dev_t *)(DR_REG_I2C1_EXT_BASE_FIXED), NULL, 1, -1, -1,I2C_NONE,I2C_NONE,I2C_ERROR_OK,NULL,NULL,NULL,0,0,0,0,0}
 | 
					    {(volatile i2c_dev_t *)(DR_REG_I2C1_EXT_BASE_FIXED), NULL, 1, -1, -1,I2C_NONE,I2C_NONE,I2C_ERROR_OK,NULL,NULL,NULL,0,0,0,0,0,0}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -218,6 +223,222 @@ static i2c_t _i2c_bus_array[2] = {
 | 
				
			|||||||
 * ack_exp   - This bit is to set an expected ACK value for the transmitter.
 | 
					 * ack_exp   - This bit is to set an expected ACK value for the transmitter.
 | 
				
			||||||
 * ack_check - This bit is to decide whether the transmitter checks ACK bit. 1 means yes and 0 means no.
 | 
					 * ack_check - This bit is to decide whether the transmitter checks ACK bit. 1 means yes and 0 means no.
 | 
				
			||||||
 * */
 | 
					 * */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Stickbreaker ISR mode debug support
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void IRAM_ATTR i2cDumpCmdQueue(i2c_t *i2c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR)&&(defined ENABLE_I2C_DEBUG_BUFFER)
 | 
				
			||||||
 | 
					    static const char * const cmdName[] ={"RSTART","WRITE","READ","STOP","END"};
 | 
				
			||||||
 | 
					    uint8_t i=0;
 | 
				
			||||||
 | 
					    while(i<16) {
 | 
				
			||||||
 | 
					        I2C_COMMAND_t c;
 | 
				
			||||||
 | 
					        c.val=i2c->dev->command[i].val;
 | 
				
			||||||
 | 
					        log_e("[%2d]\t%c\t%s\tval[%d]\texp[%d]\ten[%d]\tbytes[%d]",i,(c.done?'Y':'N'),
 | 
				
			||||||
 | 
					              cmdName[c.op_code],
 | 
				
			||||||
 | 
					              c.ack_val,
 | 
				
			||||||
 | 
					              c.ack_exp,
 | 
				
			||||||
 | 
					              c.ack_en,
 | 
				
			||||||
 | 
					              c.byte_num);
 | 
				
			||||||
 | 
					        i++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Stickbreaker ISR mode debug support
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void i2cDumpDqData(i2c_t * i2c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)&&(defined ENABLE_I2C_DEBUG_BUFFER)
 | 
				
			||||||
 | 
					    uint16_t a=0;
 | 
				
			||||||
 | 
					    char buff[140];
 | 
				
			||||||
 | 
					    I2C_DATA_QUEUE_t *tdq;
 | 
				
			||||||
 | 
					    int digits=0,lenDigits=0;
 | 
				
			||||||
 | 
					    a = i2c->queueCount;
 | 
				
			||||||
 | 
					    while(a>0) {
 | 
				
			||||||
 | 
					        digits++;
 | 
				
			||||||
 | 
					        a /= 10;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    while(a<i2c->queueCount) { // find maximum number of len decimal digits for formatting
 | 
				
			||||||
 | 
					        if (i2c->dq[a].length > lenDigits ) lenDigits = i2c->dq[a].length;
 | 
				
			||||||
 | 
					        a++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    a=0;
 | 
				
			||||||
 | 
					    while(lenDigits>0){
 | 
				
			||||||
 | 
					      a++;
 | 
				
			||||||
 | 
					      lenDigits /= 10;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    lenDigits = a;
 | 
				
			||||||
 | 
					    a = 0;
 | 
				
			||||||
 | 
					    while(a<i2c->queueCount) {
 | 
				
			||||||
 | 
					        tdq=&i2c->dq[a];
 | 
				
			||||||
 | 
					        char buf1[10],buf2[10];
 | 
				
			||||||
 | 
					        sprintf(buf1,"%0*d",lenDigits,tdq->length);
 | 
				
			||||||
 | 
					        sprintf(buf2,"%0*d",lenDigits,tdq->position);
 | 
				
			||||||
 | 
					        log_i("[%0*d] %sbit %x %c %s buf@=%p, len=%s, pos=%s, ctrl=%d%d%d%d%d",digits,a,
 | 
				
			||||||
 | 
					        (tdq->ctrl.addr>0x100)?"10":"7",
 | 
				
			||||||
 | 
					        (tdq->ctrl.addr>0x100)?(((tdq->ctrl.addr&0x600)>>1)|(tdq->ctrl.addr&0xff)):(tdq->ctrl.addr>>1),
 | 
				
			||||||
 | 
					        (tdq->ctrl.mode)?'R':'W',
 | 
				
			||||||
 | 
					        (tdq->ctrl.stop)?"STOP":"",
 | 
				
			||||||
 | 
					        tdq->data,
 | 
				
			||||||
 | 
					        buf1,buf2,
 | 
				
			||||||
 | 
					        tdq->ctrl.startCmdSent,tdq->ctrl.addrCmdSent,tdq->ctrl.dataCmdSent,(tdq->ctrl.stop)?tdq->ctrl.stopCmdSent:0,tdq->ctrl.addrSent
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        uint16_t offset = 0;
 | 
				
			||||||
 | 
					        while(offset<tdq->length) {
 | 
				
			||||||
 | 
					            memset(buff,' ',140);
 | 
				
			||||||
 | 
					            buff[139]='\0';
 | 
				
			||||||
 | 
					            uint16_t i = 0,j;
 | 
				
			||||||
 | 
					            j=sprintf(buff,"0x%04x: ",offset);
 | 
				
			||||||
 | 
					            while((i<32)&&(offset < tdq->length)) {
 | 
				
			||||||
 | 
					                char ch = tdq->data[offset];
 | 
				
			||||||
 | 
					                sprintf((char*)&buff[(i*3)+41],"%02x ",ch);
 | 
				
			||||||
 | 
					                if((ch<32)||(ch>126)) {
 | 
				
			||||||
 | 
					                    ch='.';
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                j+=sprintf((char*)&buff[j],"%c",ch);
 | 
				
			||||||
 | 
					                buff[j]=' ';
 | 
				
			||||||
 | 
					                i++;
 | 
				
			||||||
 | 
					                offset++;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            log_i("%s",buff);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        a++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void i2cDumpI2c(i2c_t * i2c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    log_e("i2c=%p",i2c);
 | 
				
			||||||
 | 
					    log_i("dev=%p date=%p",i2c->dev,i2c->dev->date);
 | 
				
			||||||
 | 
					#if !CONFIG_DISABLE_HAL_LOCKS
 | 
				
			||||||
 | 
					    log_i("lock=%p",i2c->lock);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    log_i("num=%d",i2c->num);
 | 
				
			||||||
 | 
					    log_i("mode=%d",i2c->mode);
 | 
				
			||||||
 | 
					    log_i("stage=%d",i2c->stage);
 | 
				
			||||||
 | 
					    log_i("error=%d",i2c->error);
 | 
				
			||||||
 | 
					    log_i("event=%p bits=%x",i2c->i2c_event,(i2c->i2c_event)?xEventGroupGetBits(i2c->i2c_event):0);
 | 
				
			||||||
 | 
					    log_i("intr_handle=%p",i2c->intr_handle);
 | 
				
			||||||
 | 
					    log_i("dq=%p",i2c->dq);
 | 
				
			||||||
 | 
					    log_i("queueCount=%d",i2c->queueCount);
 | 
				
			||||||
 | 
					    log_i("queuePos=%d",i2c->queuePos);
 | 
				
			||||||
 | 
					    log_i("errorByteCnt=%d",i2c->errorByteCnt);
 | 
				
			||||||
 | 
					    log_i("errorQueue=%d",i2c->errorQueue);
 | 
				
			||||||
 | 
					    log_i("debugFlags=0x%08X",i2c->debugFlags);
 | 
				
			||||||
 | 
					    if(i2c->dq) {
 | 
				
			||||||
 | 
					        i2cDumpDqData(i2c);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void i2cDumpInts(uint8_t num)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO) && (defined ENABLE_I2C_DEBUG_BUFFER)  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint32_t b;
 | 
				
			||||||
 | 
					    log_i("%u row\tcount\tINTR\tTX\tRX\tTick ",num);
 | 
				
			||||||
 | 
					    for(uint32_t a=1; a<=INTBUFFMAX; a++) {
 | 
				
			||||||
 | 
					        b=(a+intPos[num])%INTBUFFMAX;
 | 
				
			||||||
 | 
					        if(intBuff[b][0][num]!=0) {
 | 
				
			||||||
 | 
					            log_i("[%02d]\t0x%04x\t0x%04x\t0x%04x\t0x%04x\t0x%08x",b,((intBuff[b][0][num]>>16)&0xFFFF),(intBuff[b][0][num]&0xFFFF),((intBuff[b][1][num]>>16)&0xFFFF),(intBuff[b][1][num]&0xFFFF),intBuff[b][2][num]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    log_i("Debug Buffer not Enabled");
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void IRAM_ATTR i2cDumpStatus(i2c_t * i2c){
 | 
				
			||||||
 | 
					#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)&&(defined ENABLE_I2C_DEBUG_BUFFER)
 | 
				
			||||||
 | 
					    typedef union {
 | 
				
			||||||
 | 
					        struct {
 | 
				
			||||||
 | 
					            uint32_t ack_rec:             1;        /*This register stores the value of ACK bit.*/
 | 
				
			||||||
 | 
					            uint32_t slave_rw:            1;        /*when in slave mode  1:master read slave  0: master write slave.*/
 | 
				
			||||||
 | 
					            uint32_t time_out:            1;        /*when I2C takes more than time_out_reg clocks to receive a data then this register changes to high level.*/
 | 
				
			||||||
 | 
					            uint32_t arb_lost:            1;        /*when I2C lost control of SDA line  this register changes to high level.*/
 | 
				
			||||||
 | 
					            uint32_t bus_busy:            1;        /*1:I2C bus is busy transferring data. 0:I2C bus is in idle state.*/
 | 
				
			||||||
 | 
					            uint32_t slave_addressed:     1;        /*when configured as i2c slave  and the address send by master is equal to slave's address  then this bit will be high level.*/
 | 
				
			||||||
 | 
					            uint32_t byte_trans:          1;        /*This register changes to high level when one byte is transferred.*/
 | 
				
			||||||
 | 
					            uint32_t reserved7:           1;
 | 
				
			||||||
 | 
					            uint32_t rx_fifo_cnt:         6;        /*This register represent the amount of data need to send.*/
 | 
				
			||||||
 | 
					            uint32_t reserved14:          4;
 | 
				
			||||||
 | 
					            uint32_t tx_fifo_cnt:         6;        /*This register stores the amount of received data  in ram.*/
 | 
				
			||||||
 | 
					            uint32_t scl_main_state_last: 3;        /*This register stores the value of state machine for i2c module.  3'h0: SCL_MAIN_IDLE  3'h1: SCL_ADDRESS_SHIFT 3'h2: SCL_ACK_ADDRESS  3'h3: SCL_RX_DATA  3'h4 SCL_TX_DATA  3'h5:SCL_SEND_ACK 3'h6:SCL_WAIT_ACK*/
 | 
				
			||||||
 | 
					            uint32_t reserved27:          1;
 | 
				
			||||||
 | 
					            uint32_t scl_state_last:      3;        /*This register stores the value of state machine to produce SCL. 3'h0: SCL_IDLE  3'h1:SCL_START   3'h2:SCL_LOW_EDGE  3'h3: SCL_LOW   3'h4:SCL_HIGH_EDGE   3'h5:SCL_HIGH  3'h6:SCL_STOP*/
 | 
				
			||||||
 | 
					            uint32_t reserved31:          1;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        uint32_t val;
 | 
				
			||||||
 | 
					    } status_reg;
 | 
				
			||||||
 | 
					     
 | 
				
			||||||
 | 
					    status_reg sr;
 | 
				
			||||||
 | 
					    sr.val= i2c->dev->status_reg.val;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    log_i("ack(%d) sl_rw(%d) to(%d) arb(%d) busy(%d) sl(%d) trans(%d) rx(%d) tx(%d) sclMain(%d) scl(%d)",sr.ack_rec,sr.slave_rw,sr.time_out,sr.arb_lost,sr.bus_busy,sr.slave_addressed,sr.byte_trans, sr.rx_fifo_cnt, sr.tx_fifo_cnt,sr.scl_main_state_last, sr.scl_state_last);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void i2cDumpFifo(i2c_t * i2c){
 | 
				
			||||||
 | 
					#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)&&(defined ENABLE_I2C_DEBUG_BUFFER)
 | 
				
			||||||
 | 
					char buf[64];
 | 
				
			||||||
 | 
					uint16_t k = 0;
 | 
				
			||||||
 | 
					uint16_t i = fifoPos+1;
 | 
				
			||||||
 | 
					  i %=FIFOMAX;
 | 
				
			||||||
 | 
					while((fifoBuffer[i]==0)&&(i!=fifoPos)){
 | 
				
			||||||
 | 
					  i++;
 | 
				
			||||||
 | 
					  i %=FIFOMAX;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					if(i != fifoPos){// actual data
 | 
				
			||||||
 | 
					    do{
 | 
				
			||||||
 | 
					      if(fifoBuffer[i] & 0x8000){ // address byte
 | 
				
			||||||
 | 
					        if(fifoBuffer[i] & 0x100) { // read
 | 
				
			||||||
 | 
					          if(fifoBuffer[i] & 0x1) { // valid read dev id
 | 
				
			||||||
 | 
					            k+= sprintf(&buf[k],"READ  0x%02X",(fifoBuffer[i]&0xff)>>1);
 | 
				
			||||||
 | 
					          } else { // invalid read dev id
 | 
				
			||||||
 | 
					            k+= sprintf(&buf[k],"Bad READ  0x%02X",(fifoBuffer[i]&0xff));
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        } else { // write
 | 
				
			||||||
 | 
					          if(fifoBuffer[i] & 0x1) { // bad write dev id
 | 
				
			||||||
 | 
					            k+= sprintf(&buf[k],"bad WRITE 0x%02X",(fifoBuffer[i]&0xff));
 | 
				
			||||||
 | 
					          } else { // good Write
 | 
				
			||||||
 | 
					            k+= sprintf(&buf[k],"WRITE 0x%02X",(fifoBuffer[i]&0xff)>>1);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } else k += sprintf(&buf[k],"% 4X ",fifoBuffer[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      i++;
 | 
				
			||||||
 | 
					      i %= FIFOMAX;
 | 
				
			||||||
 | 
					      bool outBuffer=false;
 | 
				
			||||||
 | 
					      if( fifoBuffer[i] & 0x8000){
 | 
				
			||||||
 | 
					        outBuffer=true;
 | 
				
			||||||
 | 
					        k=0;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if((outBuffer)||(k>50)||(i==fifoPos)) log_i("%s",buf);
 | 
				
			||||||
 | 
					      outBuffer = false;
 | 
				
			||||||
 | 
					      if(k>50) {
 | 
				
			||||||
 | 
					        k=sprintf(buf,"-> ");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }while( i!= fifoPos);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void IRAM_ATTR i2cTriggerDumps(i2c_t * i2c, uint8_t trigger, const char locus[]){
 | 
				
			||||||
 | 
					#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)&&(defined ENABLE_I2C_DEBUG_BUFFER)
 | 
				
			||||||
 | 
					    if( trigger ){
 | 
				
			||||||
 | 
					      log_i("%s",locus);      
 | 
				
			||||||
 | 
					      if(trigger & 1) i2cDumpI2c(i2c);
 | 
				
			||||||
 | 
					      if(trigger & 2) i2cDumpInts(i2c->num);
 | 
				
			||||||
 | 
					      if(trigger & 4) i2cDumpCmdQueue(i2c);
 | 
				
			||||||
 | 
					      if(trigger & 8) i2cDumpStatus(i2c);
 | 
				
			||||||
 | 
					      if(trigger & 16) i2cDumpFifo(i2c);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif    
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					 // end of debug support routines
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
static void IRAM_ATTR i2cSetCmd(i2c_t * i2c, uint8_t index, uint8_t op_code, uint8_t byte_num, bool ack_val, bool ack_exp, bool ack_check)
 | 
					static void IRAM_ATTR i2cSetCmd(i2c_t * i2c, uint8_t index, uint8_t op_code, uint8_t byte_num, bool ack_val, bool ack_exp, bool ack_check)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    I2C_COMMAND_t cmd;
 | 
					    I2C_COMMAND_t cmd;
 | 
				
			||||||
@ -231,41 +452,22 @@ static void IRAM_ATTR i2cSetCmd(i2c_t * i2c, uint8_t index, uint8_t op_code, uin
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Stickbreaker ISR mode debug support
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void IRAM_ATTR dumpCmdQueue(i2c_t *i2c)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR
 | 
					 | 
				
			||||||
    uint8_t i=0;
 | 
					 | 
				
			||||||
    while(i<16) {
 | 
					 | 
				
			||||||
        I2C_COMMAND_t c;
 | 
					 | 
				
			||||||
        c.val=i2c->dev->command[i].val;
 | 
					 | 
				
			||||||
        log_e("[%2d] %c op[%d] val[%d] exp[%d] en[%d] bytes[%d]",i,(c.done?'Y':'N'),
 | 
					 | 
				
			||||||
              c.op_code,
 | 
					 | 
				
			||||||
              c.ack_val,
 | 
					 | 
				
			||||||
              c.ack_exp,
 | 
					 | 
				
			||||||
              c.ack_en,
 | 
					 | 
				
			||||||
              c.byte_num);
 | 
					 | 
				
			||||||
        i++;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Stickbreaker ISR mode support
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void IRAM_ATTR fillCmdQueue(i2c_t * i2c, bool INTS)
 | 
					static void IRAM_ATTR fillCmdQueue(i2c_t * i2c, bool INTS)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /* this function is called on initial i2cProcQueue() or when a I2C_END_DETECT_INT occurs
 | 
					    /* this function is called on initial i2cProcQueue() or when a I2C_END_DETECT_INT occurs
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    uint16_t cmdIdx = 0;
 | 
					    uint16_t cmdIdx = 0;
 | 
				
			||||||
    uint16_t qp = i2c->queuePos;
 | 
					    uint16_t qp = i2c->queuePos; // all queues before queuePos have been completely processed,
 | 
				
			||||||
 | 
					      // so look start by checking the 'current queue' so see if it needs commands added to
 | 
				
			||||||
 | 
					      // hardware peripheral command list. walk through each queue entry until all queues have been
 | 
				
			||||||
 | 
					      // checked
 | 
				
			||||||
    bool done;
 | 
					    bool done;
 | 
				
			||||||
    bool needMoreCmds = false;
 | 
					    bool needMoreCmds = false;
 | 
				
			||||||
    bool ena_rx=false; // if we add a read op, better enable Rx_Fifo IRQ
 | 
					    bool ena_rx=false; // if we add a read op, better enable Rx_Fifo IRQ
 | 
				
			||||||
    bool ena_tx=false; // if we add a Write op, better enable TX_Fifo IRQ
 | 
					    bool ena_tx=false; // if we add a Write op, better enable TX_Fifo IRQ
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while(!needMoreCmds&&(qp < i2c->queueCount)) { // check if more possible cmds
 | 
					    while(!needMoreCmds&&(qp < i2c->queueCount)) { // check if more possible cmds
 | 
				
			||||||
        if(i2c->dq[qp].ctrl.stopCmdSent) {
 | 
					        if(i2c->dq[qp].ctrl.stopCmdSent) {// marks that all required cmds[] have been added to peripheral 
 | 
				
			||||||
            qp++;
 | 
					            qp++;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            needMoreCmds=true;
 | 
					            needMoreCmds=true;
 | 
				
			||||||
@ -282,7 +484,6 @@ static void IRAM_ATTR fillCmdQueue(i2c_t * i2c, bool INTS)
 | 
				
			|||||||
            // (cmdIdx<14)  because a START op cannot directly precede an END op, else a time out cascade occurs
 | 
					            // (cmdIdx<14)  because a START op cannot directly precede an END op, else a time out cascade occurs
 | 
				
			||||||
            i2cSetCmd(i2c, cmdIdx++, I2C_CMD_RSTART, 0, false, false, false);
 | 
					            i2cSetCmd(i2c, cmdIdx++, I2C_CMD_RSTART, 0, false, false, false);
 | 
				
			||||||
            tdq->ctrl.startCmdSent=1;
 | 
					            tdq->ctrl.startCmdSent=1;
 | 
				
			||||||
            done = (cmdIdx>14);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //CMD WRITE ADDRESS
 | 
					        //CMD WRITE ADDRESS
 | 
				
			||||||
@ -341,11 +542,11 @@ static void IRAM_ATTR fillCmdQueue(i2c_t * i2c, bool INTS)
 | 
				
			|||||||
            tdq->ctrl.dataCmdSent=(tdq->cmdBytesNeeded==0); // enough command[] to send all data
 | 
					            tdq->ctrl.dataCmdSent=(tdq->cmdBytesNeeded==0); // enough command[] to send all data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if((!done)&&(tdq->ctrl.dataCmdSent)) { // possibly add stop
 | 
					            if((!done)&&(tdq->ctrl.dataCmdSent)) { // possibly add stop
 | 
				
			||||||
                if(tdq->ctrl.stop) { //send a stop
 | 
					                if(!tdq->ctrl.stopCmdSent){
 | 
				
			||||||
                    i2cSetCmd(i2c, (cmdIdx)++,I2C_CMD_STOP,0,false,false,false);
 | 
					                    if(tdq->ctrl.stop) { //send a stop
 | 
				
			||||||
                    done = cmdIdx > 14;
 | 
					                        i2cSetCmd(i2c, (cmdIdx)++,I2C_CMD_STOP,0,false,false,false);
 | 
				
			||||||
                    tdq->ctrl.stopCmdSent = 1;
 | 
					                        done = cmdIdx > 14;
 | 
				
			||||||
                } else { // dummy a stop because this is a restart
 | 
					                    }
 | 
				
			||||||
                    tdq->ctrl.stopCmdSent = 1;
 | 
					                    tdq->ctrl.stopCmdSent = 1;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -370,7 +571,7 @@ static void IRAM_ATTR fillCmdQueue(i2c_t * i2c, bool INTS)
 | 
				
			|||||||
                        i--;
 | 
					                        i--;
 | 
				
			||||||
                    } else { // unable to stretch, fatal
 | 
					                    } else { // unable to stretch, fatal
 | 
				
			||||||
                        log_e("invalid CMD[] layout Stretch Failed");
 | 
					                        log_e("invalid CMD[] layout Stretch Failed");
 | 
				
			||||||
                        dumpCmdQueue(i2c);
 | 
					                        i2cDumpCmdQueue(i2c);
 | 
				
			||||||
                        done = true;
 | 
					                        done = true;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -409,8 +610,6 @@ static void IRAM_ATTR fillCmdQueue(i2c_t * i2c, bool INTS)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Stickbreaker ISR mode support
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void IRAM_ATTR fillTxFifo(i2c_t * i2c)
 | 
					static void IRAM_ATTR fillTxFifo(i2c_t * i2c)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /*
 | 
					    /*
 | 
				
			||||||
@ -421,6 +620,7 @@ static void IRAM_ATTR fillTxFifo(i2c_t * i2c)
 | 
				
			|||||||
    uint16_t a=i2c->queuePos; // currently executing dq,
 | 
					    uint16_t a=i2c->queuePos; // currently executing dq,
 | 
				
			||||||
    bool full=!(i2c->dev->status_reg.tx_fifo_cnt<31);
 | 
					    bool full=!(i2c->dev->status_reg.tx_fifo_cnt<31);
 | 
				
			||||||
    uint8_t cnt;
 | 
					    uint8_t cnt;
 | 
				
			||||||
 | 
					    bool rxQueueEncountered = false;
 | 
				
			||||||
    while((a < i2c->queueCount) && !full) {
 | 
					    while((a < i2c->queueCount) && !full) {
 | 
				
			||||||
        I2C_DATA_QUEUE_t *tdq = &i2c->dq[a];
 | 
					        I2C_DATA_QUEUE_t *tdq = &i2c->dq[a];
 | 
				
			||||||
        cnt=0;
 | 
					        cnt=0;
 | 
				
			||||||
@ -449,24 +649,38 @@ static void IRAM_ATTR fillTxFifo(i2c_t * i2c)
 | 
				
			|||||||
                        i2c->dev->fifo_data.val = tdq->ctrl.addr&0xFF;
 | 
					                        i2c->dev->fifo_data.val = tdq->ctrl.addr&0xFF;
 | 
				
			||||||
                        cnt++;
 | 
					                        cnt++;
 | 
				
			||||||
                        tdq->ctrl.addrSent=1; // 7bit lowbyte sent
 | 
					                        tdq->ctrl.addrSent=1; // 7bit lowbyte sent
 | 
				
			||||||
 | 
					#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO) && (defined ENABLE_I2C_DEBUG_BUFFER)
 | 
				
			||||||
 | 
					                        uint16_t a = 0x8000 | tdq->ctrl.addr | (tdq->ctrl.mode<<8);
 | 
				
			||||||
 | 
					                        fifoBuffer[fifoPos++] = a;
 | 
				
			||||||
 | 
					                        fifoPos %= FIFOMAX;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        full=!(i2c->dev->status_reg.tx_fifo_cnt<31);
 | 
					 | 
				
			||||||
        // add write data to fifo
 | 
					        // add write data to fifo
 | 
				
			||||||
        //21NOV2017 might want to look into using local capacity counter instead of reading status_reg
 | 
					 | 
				
			||||||
        //  a double while loop, like emptyRxFifo()
 | 
					 | 
				
			||||||
        if(tdq->ctrl.mode==0) { // write
 | 
					        if(tdq->ctrl.mode==0) { // write
 | 
				
			||||||
            if(tdq->ctrl.addrSent == tdq->ctrl.addrReq) { //address has been sent, is Write Mode!
 | 
					            if(tdq->ctrl.addrSent == tdq->ctrl.addrReq) { //address has been sent, is Write Mode!
 | 
				
			||||||
                while((!full)&&(tdq->position < tdq->length)) {
 | 
					                uint32_t moveCnt = 32 - i2c->dev->status_reg.tx_fifo_cnt; // how much room in txFifo?
 | 
				
			||||||
 | 
					                while(( moveCnt>0)&&(tdq->position < tdq->length)) {
 | 
				
			||||||
 | 
					#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO) && (defined ENABLE_I2C_DEBUG_BUFFER)
 | 
				
			||||||
 | 
					                    fifoBuffer[fifoPos++] =  tdq->data[tdq->position];
 | 
				
			||||||
 | 
					                    fifoPos %= FIFOMAX;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
                    i2c->dev->fifo_data.val = tdq->data[tdq->position++];
 | 
					                    i2c->dev->fifo_data.val = tdq->data[tdq->position++];
 | 
				
			||||||
                    cnt++;
 | 
					                    cnt++;
 | 
				
			||||||
                    full=!(i2c->dev->status_reg.tx_fifo_cnt<31);
 | 
					                    moveCnt--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        } else { // read Queue Encountered, can't update QueuePos past this point, emptyRxfifo will do it
 | 
				
			||||||
 | 
					            if( ! rxQueueEncountered ) {
 | 
				
			||||||
 | 
					              rxQueueEncountered = true;
 | 
				
			||||||
 | 
					              if(a > i2c->queuePos){
 | 
				
			||||||
 | 
					                i2c->queuePos = a; 
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					           }              
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO) && (defined ENABLE_I2C_DEBUG_BUFFER)
 | 
					#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO) && (defined ENABLE_I2C_DEBUG_BUFFER)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // update debug buffer tx counts
 | 
					        // update debug buffer tx counts
 | 
				
			||||||
@ -474,65 +688,78 @@ static void IRAM_ATTR fillTxFifo(i2c_t * i2c)
 | 
				
			|||||||
        intBuff[intPos[i2c->num]][1][i2c->num] = (intBuff[intPos[i2c->num]][1][i2c->num]&0xFFFF)|(cnt<<16);
 | 
					        intBuff[intPos[i2c->num]][1][i2c->num] = (intBuff[intPos[i2c->num]][1][i2c->num]&0xFFFF)|(cnt<<16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					        full=!(i2c->dev->status_reg.tx_fifo_cnt<31);
 | 
				
			||||||
        if(!full) {
 | 
					        if(!full) {
 | 
				
			||||||
            a++;    // check next buffer for tx
 | 
					            a++;    // check next buffer for address tx, or write data
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(a >= i2c->queueCount ) { // disable IRQ, the next dq will re-enable it
 | 
					    if(a >= i2c->queueCount ) { // disable TX IRQ, all tx Data has been queued
 | 
				
			||||||
        // (a >= i2c->queueCount) means no more data is available
 | 
					 | 
				
			||||||
        i2c->dev->int_ena.tx_fifo_empty= 0;
 | 
					        i2c->dev->int_ena.tx_fifo_empty= 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    i2c->dev->int_clr.tx_fifo_empty=1;
 | 
					    i2c->dev->int_clr.tx_fifo_empty=1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Stickbreaker ISR mode support
 | 
					
 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static void IRAM_ATTR emptyRxFifo(i2c_t * i2c)
 | 
					static void IRAM_ATTR emptyRxFifo(i2c_t * i2c)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint32_t d, cnt=0, moveCnt;
 | 
					    uint32_t d, cnt=0, moveCnt;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    moveCnt = i2c->dev->status_reg.rx_fifo_cnt;//no need to check the reg until this many are read
 | 
					    moveCnt = i2c->dev->status_reg.rx_fifo_cnt;//no need to check the reg until this many are read
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while((moveCnt > 0)&&(i2c->queuePos < i2c->queueCount)){ // data to move    
 | 
					    while((moveCnt > 0)&&(i2c->queuePos < i2c->queueCount)){ // data to move    
 | 
				
			||||||
      I2C_DATA_QUEUE_t *tdq =&i2c->dq[i2c->queuePos]; //short cut
 | 
					
 | 
				
			||||||
      if(tdq->ctrl.mode == 1){ // read command
 | 
					        I2C_DATA_QUEUE_t *tdq =&i2c->dq[i2c->queuePos]; //short cut
 | 
				
			||||||
         if(moveCnt > (tdq->length - tdq->position)) { //make sure they go in this dq
 | 
					
 | 
				
			||||||
        // part of these reads go into the next dq
 | 
					        while((tdq->position >= tdq->length)&&( i2c->queuePos < i2c->queueCount)){ // find were to store
 | 
				
			||||||
            moveCnt = (tdq->length - tdq->position);
 | 
					            i2c->queuePos++;
 | 
				
			||||||
         }
 | 
					            tdq = &i2c->dq[i2c->queuePos];
 | 
				
			||||||
      } else {// error
 | 
					        }
 | 
				
			||||||
         log_e("RxEmpty(%d) call on TxBuffer? dq=%d",moveCnt,i2c->queuePos);
 | 
					      
 | 
				
			||||||
         return; 
 | 
					        if(i2c->queuePos >= i2c->queueCount){ // bad stuff, rx data but no place to put it!
 | 
				
			||||||
      }
 | 
					            log_e("no Storage location for %d",moveCnt);
 | 
				
			||||||
      while(moveCnt > 0) {
 | 
					        // discard
 | 
				
			||||||
         d = i2c->dev->fifo_data.val;
 | 
					            while(moveCnt>0){
 | 
				
			||||||
         moveCnt--;
 | 
					                d = i2c->dev->fifo_data.val;
 | 
				
			||||||
         cnt++;
 | 
					                moveCnt--;
 | 
				
			||||||
         tdq->data[tdq->position++] = (d&0xFF);
 | 
					                cnt++;
 | 
				
			||||||
         }
 | 
					            }
 | 
				
			||||||
      if(tdq->position >= tdq->length ){ // inc queuePos until next READ command or end of queue
 | 
					            break;
 | 
				
			||||||
        i2c->queuePos++;
 | 
					        }
 | 
				
			||||||
        while((i2c->queuePos < i2c->queueCount)&&(i2c->dq[i2c->queuePos].ctrl.mode !=1)){
 | 
					        
 | 
				
			||||||
          i2c->queuePos++;
 | 
					        if(tdq->ctrl.mode == 1){ // read command
 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        if(i2c->queuePos < i2c->queueCount){ // found new place to store rx data
 | 
					 | 
				
			||||||
            tdq = &i2c->dq[i2c->queuePos]; // update shortcut
 | 
					 | 
				
			||||||
            // see if any more chars showed up while empting Fifo.
 | 
					 | 
				
			||||||
            moveCnt = i2c->dev->status_reg.rx_fifo_cnt;
 | 
					 | 
				
			||||||
            if(moveCnt > (tdq->length - tdq->position)) { //make sure they go in this dq
 | 
					            if(moveCnt > (tdq->length - tdq->position)) { //make sure they go in this dq
 | 
				
			||||||
                // part of these reads go into the next dq
 | 
					        // part of these reads go into the next dq
 | 
				
			||||||
                moveCnt = (tdq->length - tdq->position);
 | 
					                moveCnt = (tdq->length - tdq->position);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        } else {// error
 | 
				
			||||||
 | 
					            log_e("RxEmpty(%d) call on TxBuffer? dq=%d",moveCnt,i2c->queuePos);
 | 
				
			||||||
 | 
					        // discard
 | 
				
			||||||
 | 
					            while(moveCnt>0){
 | 
				
			||||||
 | 
					                d = i2c->dev->fifo_data.val;
 | 
				
			||||||
 | 
					                moveCnt--;
 | 
				
			||||||
 | 
					                cnt++;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					
 | 
				
			||||||
 | 
					        while(moveCnt > 0) { // store data
 | 
				
			||||||
 | 
					            d = i2c->dev->fifo_data.val;
 | 
				
			||||||
 | 
					            moveCnt--;
 | 
				
			||||||
 | 
					            cnt++;
 | 
				
			||||||
 | 
					            tdq->data[tdq->position++] = (d&0xFF);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        moveCnt = i2c->dev->status_reg.rx_fifo_cnt; //any more out there?
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)&& (defined ENABLE_I2C_DEBUG_BUFFER)
 | 
					#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)&& (defined ENABLE_I2C_DEBUG_BUFFER)
 | 
				
			||||||
        // update Debug rxCount
 | 
					        // update Debug rxCount
 | 
				
			||||||
        cnt += (intBuff[intPos[i2c->num]][1][i2c->num])&&0xffFF;
 | 
					        cnt += (intBuff[intPos[i2c->num]][1][i2c->num])&0xffFF;
 | 
				
			||||||
        intBuff[intPos[i2c->num]][1][i2c->num] = (intBuff[intPos[i2c->num]][1][i2c->num]&0xFFFF0000)|cnt;
 | 
					        intBuff[intPos[i2c->num]][1][i2c->num] = (intBuff[intPos[i2c->num]][1][i2c->num]&0xFFFF0000)|cnt;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 }
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void IRAM_ATTR i2cIsrExit(i2c_t * i2c,const uint32_t eventCode,bool Fatal)
 | 
					static void IRAM_ATTR i2cIsrExit(i2c_t * i2c,const uint32_t eventCode,bool Fatal)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -578,16 +805,17 @@ static void IRAM_ATTR i2cIsrExit(i2c_t * i2c,const uint32_t eventCode,bool Fatal
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void IRAM_ATTR i2c_update_error_byte_cnt(i2c_t * i2c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
/* i2c_update_error_byte_cnt 07/18/2018
 | 
					/* i2c_update_error_byte_cnt 07/18/2018
 | 
				
			||||||
  Only called after an error has occurred, so, most of the time this function is never used.
 | 
					  Only called after an error has occurred, so, most of the time this function is never used.
 | 
				
			||||||
  This function obliterates the need to interrupt monitor each byte transferred, at high bitrates
 | 
					  This function obliterates the need to interrupt monitor each byte transferred, at high bitrates
 | 
				
			||||||
  the byte interrupts were overwhelming the OS.  Spurious Interrupts were being generated.
 | 
					  the byte interrupts were overwhelming the OS.  Spurious Interrupts were being generated.
 | 
				
			||||||
  it update errorByteCnt, errorQueue. 
 | 
					  it updates errorByteCnt, errorQueue. 
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void IRAM_ATTR i2c_update_error_byte_cnt(i2c_t * i2c)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    uint16_t a=0; // start at top of DQ, count how many bytes added to tx fifo, and received from rx_fifo.
 | 
					    uint16_t a=0; // start at top of DQ, count how many bytes added to tx fifo, and received from rx_fifo.
 | 
				
			||||||
    uint16_t bc = 0;
 | 
					    int16_t bc = 0;
 | 
				
			||||||
    I2C_DATA_QUEUE_t *tdq;
 | 
					    I2C_DATA_QUEUE_t *tdq;
 | 
				
			||||||
    i2c->errorByteCnt = 0; 
 | 
					    i2c->errorByteCnt = 0; 
 | 
				
			||||||
    while( a < i2c->queueCount){ // add up all bytes loaded into fifo's
 | 
					    while( a < i2c->queueCount){ // add up all bytes loaded into fifo's
 | 
				
			||||||
@ -596,40 +824,34 @@ static void IRAM_ATTR i2c_update_error_byte_cnt(i2c_t * i2c)
 | 
				
			|||||||
        i2c->errorByteCnt += tdq->position; 
 | 
					        i2c->errorByteCnt += tdq->position; 
 | 
				
			||||||
        a++;
 | 
					        a++;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
//  log_v("errorByteCnt=%d",i2c->errorByteCnt);
 | 
					 | 
				
			||||||
  // now errorByteCnt contains total bytes moved into and out of FIFO's
 | 
					  // now errorByteCnt contains total bytes moved into and out of FIFO's
 | 
				
			||||||
  // but, there may still be bytes waiting in Fifo's
 | 
					  // but, there may still be bytes waiting in Fifo's
 | 
				
			||||||
    i2c->errorByteCnt -= i2c->dev->status_reg.tx_fifo_cnt; // waiting to go out;
 | 
					    i2c->errorByteCnt -= i2c->dev->status_reg.tx_fifo_cnt; // waiting to go out;
 | 
				
			||||||
    i2c->errorByteCnt += i2c->dev->status_reg.rx_fifo_cnt; // already received
 | 
					    i2c->errorByteCnt += i2c->dev->status_reg.rx_fifo_cnt; // already received
 | 
				
			||||||
// now walk thru DQ again, find which byte is 'current'
 | 
					// now walk thru DQ again, find which byte is 'current'
 | 
				
			||||||
    bool done = false;
 | 
					 | 
				
			||||||
    bc = i2c->errorByteCnt;
 | 
					    bc = i2c->errorByteCnt;
 | 
				
			||||||
    i2c->errorQueue = 0;
 | 
					    i2c->errorQueue = 0;
 | 
				
			||||||
    while(( i2c->errorQueue < i2c->queueCount)&&( !done )){
 | 
					    while( i2c->errorQueue < i2c->queueCount ){
 | 
				
			||||||
        tdq = &i2c->dq[i2c->errorQueue];
 | 
					        tdq = &i2c->dq[i2c->errorQueue];
 | 
				
			||||||
        if(bc>0){ // not found yet
 | 
					        if(bc>0){ // not found yet
 | 
				
			||||||
            if( tdq->ctrl.addrSent >= bc){ // in address
 | 
					            if( tdq->ctrl.addrSent >= bc){ // in address
 | 
				
			||||||
                done = true;
 | 
					                bc = -1; // in address
 | 
				
			||||||
                continue;
 | 
					                break;
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                bc -= tdq->ctrl.addrSent;
 | 
					                bc -= tdq->ctrl.addrSent;
 | 
				
			||||||
                if( tdq->position >= bc) { // data nak
 | 
					                if( tdq->length > bc) { // data nak
 | 
				
			||||||
                    done = true;
 | 
					                    break;
 | 
				
			||||||
                    continue;
 | 
					 | 
				
			||||||
                } else { // count down
 | 
					                } else { // count down
 | 
				
			||||||
                    bc -= tdq->position;
 | 
					                    bc -= tdq->length;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else break;
 | 
				
			||||||
            done= true;
 | 
					        
 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        i2c->errorQueue++;
 | 
					        i2c->errorQueue++;
 | 
				
			||||||
    }  
 | 
					    }  
 | 
				
			||||||
//  log_v("errorByteCnt=%d errorQueue=%d",i2c->errorByteCnt,i2c->errorQueue);
 | 
					 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
    i2c->errorByteCnt = bc;
 | 
					    i2c->errorByteCnt = bc;
 | 
				
			||||||
}
 | 
					 }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void IRAM_ATTR i2c_isr_handler_default(void* arg)
 | 
					static void IRAM_ATTR i2c_isr_handler_default(void* arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -637,17 +859,14 @@ static void IRAM_ATTR i2c_isr_handler_default(void* arg)
 | 
				
			|||||||
    uint32_t activeInt = p_i2c->dev->int_status.val&0x7FF;
 | 
					    uint32_t activeInt = p_i2c->dev->int_status.val&0x7FF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(p_i2c->stage==I2C_DONE) { //get Out, can't service, not configured
 | 
					    if(p_i2c->stage==I2C_DONE) { //get Out, can't service, not configured
 | 
				
			||||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
 | 
					 | 
				
			||||||
        uint32_t raw = p_i2c->dev->int_raw.val;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
        p_i2c->dev->int_ena.val = 0;
 | 
					        p_i2c->dev->int_ena.val = 0;
 | 
				
			||||||
        p_i2c->dev->int_clr.val = 0x1FFF;
 | 
					        p_i2c->dev->int_clr.val = 0x1FFF;
 | 
				
			||||||
        log_v("eject raw=%p, int=%p",raw,activeInt);
 | 
					#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_VERBOSE
 | 
				
			||||||
 | 
					        uint32_t raw = p_i2c->dev->int_raw.val;
 | 
				
			||||||
 | 
					        log_w("eject raw=%p, int=%p",raw,activeInt);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }else if(!activeInt){ //spurious interrupt, possibly bus relate 20180711
 | 
					 | 
				
			||||||
       log_v("r=0x%x s=0x%x %d",p_i2c->dev->int_raw.val,p_i2c->dev->int_status.val,p_i2c->stage);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    while (activeInt != 0) { // Ordering of 'if(activeInt)' statements is important, don't change
 | 
					    while (activeInt != 0) { // Ordering of 'if(activeInt)' statements is important, don't change
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO) && (defined ENABLE_I2C_DEBUG_BUFFER)
 | 
					    #if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO) && (defined ENABLE_I2C_DEBUG_BUFFER)
 | 
				
			||||||
@ -690,8 +909,7 @@ static void IRAM_ATTR i2c_isr_handler_default(void* arg)
 | 
				
			|||||||
        if (activeInt & I2C_ACK_ERR_INT_ST_M) {//fatal error, abort i2c service
 | 
					        if (activeInt & I2C_ACK_ERR_INT_ST_M) {//fatal error, abort i2c service
 | 
				
			||||||
            if (p_i2c->mode == I2C_MASTER) {
 | 
					            if (p_i2c->mode == I2C_MASTER) {
 | 
				
			||||||
                i2c_update_error_byte_cnt(p_i2c); // calc which byte caused ack Error, check if address or data
 | 
					                i2c_update_error_byte_cnt(p_i2c); // calc which byte caused ack Error, check if address or data
 | 
				
			||||||
                log_v("AcK Err errorByteCnt=%d, errorQueue=%d queuepos=%d",p_i2c->errorByteCnt,p_i2c->errorQueue, p_i2c->queuePos);
 | 
					                if(p_i2c->errorByteCnt < 0 ) { // address
 | 
				
			||||||
                if(p_i2c->errorByteCnt <= p_i2c->dq[p_i2c->errorQueue].ctrl.addrReq) { // address
 | 
					 | 
				
			||||||
                    i2cIsrExit(p_i2c,EVENT_ERROR_NAK,true);
 | 
					                    i2cIsrExit(p_i2c,EVENT_ERROR_NAK,true);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    i2cIsrExit(p_i2c,EVENT_ERROR_DATA_NAK,true); //data
 | 
					                    i2cIsrExit(p_i2c,EVENT_ERROR_DATA_NAK,true); //data
 | 
				
			||||||
@ -750,14 +968,16 @@ static void IRAM_ATTR i2c_isr_handler_default(void* arg)
 | 
				
			|||||||
            p_i2c->dev->int_ena.val = p_i2c->dev->int_ena.val & (~activeInt);
 | 
					            p_i2c->dev->int_ena.val = p_i2c->dev->int_ena.val & (~activeInt);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        activeInt = p_i2c->dev->int_status.val; // start all over if another interrupt happened
 | 
					//        activeInt = p_i2c->dev->int_status.val; // start all over if another interrupt happened
 | 
				
			||||||
 | 
					// 01AUG2018 if another interrupt happened, the OS will schedule another interrupt
 | 
				
			||||||
 | 
					// this is the source of spurious interrupts
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Stickbreaker added for ISR 11/2017
 | 
					/* Stickbreaker added for ISR 11/2017
 | 
				
			||||||
functional with Silicon date=0x16042000
 | 
					functional with Silicon date=0x16042000
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static i2c_err_t i2cAddQueue(i2c_t * i2c,uint8_t mode, uint16_t i2cDeviceAddr, uint8_t *dataPtr, uint16_t dataLen,bool sendStop, EventGroupHandle_t event)
 | 
					static i2c_err_t i2cAddQueue(i2c_t * i2c,uint8_t mode, uint16_t i2cDeviceAddr, uint8_t *dataPtr, uint16_t dataLen,bool sendStop, bool dataOnly, EventGroupHandle_t event)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // need to grab a MUTEX for exclusive Queue,
 | 
					    // need to grab a MUTEX for exclusive Queue,
 | 
				
			||||||
    // what about if ISR is running?
 | 
					    // what about if ISR is running?
 | 
				
			||||||
@ -772,10 +992,21 @@ static i2c_err_t i2cAddQueue(i2c_t * i2c,uint8_t mode, uint16_t i2cDeviceAddr, u
 | 
				
			|||||||
    dqx.position = 0;
 | 
					    dqx.position = 0;
 | 
				
			||||||
    dqx.cmdBytesNeeded = dataLen;
 | 
					    dqx.cmdBytesNeeded = dataLen;
 | 
				
			||||||
    dqx.ctrl.val = 0;
 | 
					    dqx.ctrl.val = 0;
 | 
				
			||||||
 | 
					    if( dataOnly) {
 | 
				
			||||||
 | 
					     /* special case to add a queue data only element.
 | 
				
			||||||
 | 
					        START and devAddr will not be sent, this dq element can have a STOP.
 | 
				
			||||||
 | 
					        allows multiple buffers to be used for one transaction.
 | 
				
			||||||
 | 
					        sequence: normal transaction(sendStop==false), [dataonly(sendStop==false)],dataOnly(sendStop==true)
 | 
				
			||||||
 | 
					       *** Currently only works with WRITE, final byte NAK an READ will cause a fail between dq buffer elements.  (in progress 30JUL2018)
 | 
				
			||||||
 | 
					        */
 | 
				
			||||||
 | 
					        dqx.ctrl.startCmdSent = 1; // mark as already sent
 | 
				
			||||||
 | 
					        dqx.ctrl.addrCmdSent = 1;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        dqx.ctrl.addrReq = ((i2cDeviceAddr&0xFC00)==0x7800)?2:1; // 10bit or 7bit address
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    dqx.ctrl.addr = i2cDeviceAddr;
 | 
					    dqx.ctrl.addr = i2cDeviceAddr;
 | 
				
			||||||
    dqx.ctrl.mode = mode;
 | 
					    dqx.ctrl.mode = mode;
 | 
				
			||||||
    dqx.ctrl.stop= sendStop;
 | 
					    dqx.ctrl.stop= sendStop;
 | 
				
			||||||
    dqx.ctrl.addrReq = ((i2cDeviceAddr&0xFC00)==0x7800)?2:1; // 10bit or 7bit address
 | 
					 | 
				
			||||||
    dqx.queueEvent = event;
 | 
					    dqx.queueEvent = event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(event) { // an eventGroup exist, so, initialize it
 | 
					    if(event) { // an eventGroup exist, so, initialize it
 | 
				
			||||||
@ -808,7 +1039,7 @@ static i2c_err_t i2cAddQueue(i2c_t * i2c,uint8_t mode, uint16_t i2cDeviceAddr, u
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
i2c_err_t i2cAddQueueWrite(i2c_t * i2c, uint16_t i2cDeviceAddr, uint8_t *dataPtr, uint16_t dataLen,bool sendStop,EventGroupHandle_t event)
 | 
					i2c_err_t i2cAddQueueWrite(i2c_t * i2c, uint16_t i2cDeviceAddr, uint8_t *dataPtr, uint16_t dataLen,bool sendStop,EventGroupHandle_t event)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return i2cAddQueue(i2c,0,i2cDeviceAddr,dataPtr,dataLen,sendStop,event);
 | 
					    return i2cAddQueue(i2c,0,i2cDeviceAddr,dataPtr,dataLen,sendStop,false,event);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
i2c_err_t i2cAddQueueRead(i2c_t * i2c, uint16_t i2cDeviceAddr, uint8_t *dataPtr, uint16_t dataLen,bool sendStop,EventGroupHandle_t event)
 | 
					i2c_err_t i2cAddQueueRead(i2c_t * i2c, uint16_t i2cDeviceAddr, uint8_t *dataPtr, uint16_t dataLen,bool sendStop,EventGroupHandle_t event)
 | 
				
			||||||
@ -822,16 +1053,15 @@ i2c_err_t i2cAddQueueRead(i2c_t * i2c, uint16_t i2cDeviceAddr, uint8_t *dataPtr,
 | 
				
			|||||||
    // this is the Industry Standard specification.
 | 
					    // this is the Industry Standard specification.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if((i2cDeviceAddr &0xFC00)==0x7800) { // ten bit read
 | 
					    if((i2cDeviceAddr &0xFC00)==0x7800) { // ten bit read
 | 
				
			||||||
        i2c_err_t err = i2cAddQueue(i2c,0,i2cDeviceAddr,NULL,0,false,event);
 | 
					        i2c_err_t err = i2cAddQueue(i2c,0,i2cDeviceAddr,NULL,0,false,false,event);
 | 
				
			||||||
        if(err==I2C_ERROR_OK) {
 | 
					        if(err==I2C_ERROR_OK) {
 | 
				
			||||||
            return i2cAddQueue(i2c,1,(i2cDeviceAddr>>8),dataPtr,dataLen,sendStop,event);
 | 
					            return i2cAddQueue(i2c,1,(i2cDeviceAddr>>8),dataPtr,dataLen,sendStop,false,event);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            return err;
 | 
					            return err;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return i2cAddQueue(i2c,1,i2cDeviceAddr,dataPtr,dataLen,sendStop,event);
 | 
					    return i2cAddQueue(i2c,1,i2cDeviceAddr,dataPtr,dataLen,sendStop,false,event);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
// Stickbreaker
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
 | 
					i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -847,6 +1077,7 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
 | 
				
			|||||||
    if(i2c == NULL) {
 | 
					    if(i2c == NULL) {
 | 
				
			||||||
        return I2C_ERROR_DEV;
 | 
					        return I2C_ERROR_DEV;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if(i2c->debugFlags & 0xff000000) i2cTriggerDumps(i2c,(i2c->debugFlags>>24),"before ProcQueue");
 | 
				
			||||||
    if (i2c->dev->status_reg.bus_busy) { // return error, let TwoWire() handle resetting the hardware.
 | 
					    if (i2c->dev->status_reg.bus_busy) { // return error, let TwoWire() handle resetting the hardware.
 | 
				
			||||||
        /* if multi master then this if should be changed to this 03/12/2018
 | 
					        /* if multi master then this if should be changed to this 03/12/2018
 | 
				
			||||||
        if(multiMaster){// try to let the bus clear by its self
 | 
					        if(multiMaster){// try to let the bus clear by its self
 | 
				
			||||||
@ -876,6 +1107,8 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
 | 
				
			|||||||
        intBuff[i][2][i2c->num] = 0;
 | 
					        intBuff[i][2][i2c->num] = 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    intPos[i2c->num] = 0;
 | 
					    intPos[i2c->num] = 0;
 | 
				
			||||||
 | 
					    fifoPos = 0;
 | 
				
			||||||
 | 
					    memset(fifoBuffer,0,FIFOMAX);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    // EventGroup is used to signal transmission completion from ISR
 | 
					    // EventGroup is used to signal transmission completion from ISR
 | 
				
			||||||
    // not always reliable. Sometimes, the FreeRTOS scheduler is maxed out and refuses request
 | 
					    // not always reliable. Sometimes, the FreeRTOS scheduler is maxed out and refuses request
 | 
				
			||||||
@ -950,13 +1183,11 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
 | 
				
			|||||||
    // receives the TRANS_START
 | 
					    // receives the TRANS_START
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    
 | 
					    uint32_t interruptsEnabled =
 | 
				
			||||||
    i2c->dev->int_ena.val =
 | 
					 | 
				
			||||||
        I2C_ACK_ERR_INT_ENA | // (BIT(10))  Causes Fatal Error Exit
 | 
					        I2C_ACK_ERR_INT_ENA | // (BIT(10))  Causes Fatal Error Exit
 | 
				
			||||||
        I2C_TRANS_START_INT_ENA | // (BIT(9))  Triggered by trans_start=1, initial,END
 | 
					        I2C_TRANS_START_INT_ENA | // (BIT(9))  Triggered by trans_start=1, initial,END
 | 
				
			||||||
        I2C_TIME_OUT_INT_ENA  | //(BIT(8))  Trigger by SLAVE SCL stretching, NOT an ERROR
 | 
					        I2C_TIME_OUT_INT_ENA  | //(BIT(8))  Trigger by SLAVE SCL stretching, NOT an ERROR
 | 
				
			||||||
        I2C_TRANS_COMPLETE_INT_ENA | // (BIT(7))  triggered by STOP, successful exit
 | 
					        I2C_TRANS_COMPLETE_INT_ENA | // (BIT(7))  triggered by STOP, successful exit
 | 
				
			||||||
//        I2C_MASTER_TRAN_COMP_INT_ENA | // (BIT(6))  counts each byte xfer'd, inc's queuePos
 | 
					 | 
				
			||||||
        I2C_ARBITRATION_LOST_INT_ENA | // (BIT(5))  cause fatal error exit
 | 
					        I2C_ARBITRATION_LOST_INT_ENA | // (BIT(5))  cause fatal error exit
 | 
				
			||||||
        I2C_SLAVE_TRAN_COMP_INT_ENA  | // (BIT(4))  unhandled
 | 
					        I2C_SLAVE_TRAN_COMP_INT_ENA  | // (BIT(4))  unhandled
 | 
				
			||||||
        I2C_END_DETECT_INT_ENA  | // (BIT(3))   refills cmd[] list
 | 
					        I2C_END_DETECT_INT_ENA  | // (BIT(3))   refills cmd[] list
 | 
				
			||||||
@ -964,6 +1195,8 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
 | 
				
			|||||||
        I2C_TXFIFO_EMPTY_INT_ENA | // (BIT(1))    triggers fillTxFifo()
 | 
					        I2C_TXFIFO_EMPTY_INT_ENA | // (BIT(1))    triggers fillTxFifo()
 | 
				
			||||||
        I2C_RXFIFO_FULL_INT_ENA;  // (BIT(0))     trigger emptyRxFifo()
 | 
					        I2C_RXFIFO_FULL_INT_ENA;  // (BIT(0))     trigger emptyRxFifo()
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
 | 
					    i2c->dev->int_ena.val = interruptsEnabled;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
    if(!i2c->intr_handle) { // create ISR for either peripheral
 | 
					    if(!i2c->intr_handle) { // create ISR for either peripheral
 | 
				
			||||||
        // log_i("create ISR %d",i2c->num);
 | 
					        // log_i("create ISR %d",i2c->num);
 | 
				
			||||||
        uint32_t ret = 0;
 | 
					        uint32_t ret = 0;
 | 
				
			||||||
@ -972,9 +1205,9 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
 | 
				
			|||||||
          ESP_INTR_FLAG_LOWMED;   //< Low and medium prio interrupts. These can be handled in C.
 | 
					          ESP_INTR_FLAG_LOWMED;   //< Low and medium prio interrupts. These can be handled in C.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(i2c->num) {
 | 
					        if(i2c->num) {
 | 
				
			||||||
            ret = esp_intr_alloc_intrstatus(ETS_I2C_EXT1_INTR_SOURCE, flags, (uint32_t)&i2c->dev->int_status.val, 0x7FF, &i2c_isr_handler_default,i2c, &i2c->intr_handle);
 | 
					            ret = esp_intr_alloc_intrstatus(ETS_I2C_EXT1_INTR_SOURCE, flags, (uint32_t)&i2c->dev->int_status.val, interruptsEnabled, &i2c_isr_handler_default,i2c, &i2c->intr_handle);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            ret = esp_intr_alloc_intrstatus(ETS_I2C_EXT0_INTR_SOURCE, flags, (uint32_t)&i2c->dev->int_status.val, 0x7FF, &i2c_isr_handler_default,i2c, &i2c->intr_handle);
 | 
					            ret = esp_intr_alloc_intrstatus(ETS_I2C_EXT0_INTR_SOURCE, flags, (uint32_t)&i2c->dev->int_status.val, interruptsEnabled, &i2c_isr_handler_default,i2c, &i2c->intr_handle);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(ret!=ESP_OK) {
 | 
					        if(ret!=ESP_OK) {
 | 
				
			||||||
@ -983,7 +1216,6 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
 | 
				
			|||||||
            return I2C_ERROR_MEMORY;
 | 
					            return I2C_ERROR_MEMORY;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    //hang until it completes.
 | 
					    //hang until it completes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // how many ticks should it take to transfer totalBytes through the I2C hardware,
 | 
					    // how many ticks should it take to transfer totalBytes through the I2C hardware,
 | 
				
			||||||
@ -1052,7 +1284,7 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
 | 
				
			|||||||
        i2c->dev->int_ena.val =0;
 | 
					        i2c->dev->int_ena.val =0;
 | 
				
			||||||
        i2c->dev->int_clr.val = 0x1FFF;
 | 
					        i2c->dev->int_clr.val = 0x1FFF;
 | 
				
			||||||
        i2c_update_error_byte_cnt(i2c);
 | 
					        i2c_update_error_byte_cnt(i2c);
 | 
				
			||||||
        if(i2c->errorByteCnt == 0) { // Bus Busy no bytes Moved
 | 
					        if((i2c->errorByteCnt == 0)&&(i2c->errorQueue==0)) { // Bus Busy no bytes Moved
 | 
				
			||||||
            reason = I2C_ERROR_BUSY;
 | 
					            reason = I2C_ERROR_BUSY;
 | 
				
			||||||
            eBits = eBits | EVENT_ERROR_BUS_BUSY|EVENT_ERROR|EVENT_DONE;
 | 
					            eBits = eBits | EVENT_ERROR_BUS_BUSY|EVENT_ERROR|EVENT_DONE;
 | 
				
			||||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG
 | 
					#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG
 | 
				
			||||||
@ -1103,6 +1335,7 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        b++;
 | 
					        b++;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if(i2c->debugFlags & 0x00ff0000) i2cTriggerDumps(i2c,(i2c->debugFlags>>16),"after ProcQueue");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    I2C_MUTEX_UNLOCK();
 | 
					    I2C_MUTEX_UNLOCK();
 | 
				
			||||||
    return reason;
 | 
					    return reason;
 | 
				
			||||||
@ -1311,6 +1544,8 @@ i2c_err_t i2cFlush(i2c_t * i2c)
 | 
				
			|||||||
    if(i2c==NULL) {
 | 
					    if(i2c==NULL) {
 | 
				
			||||||
        return I2C_ERROR_DEV;
 | 
					        return I2C_ERROR_DEV;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    i2cTriggerDumps(i2c,i2c->debugFlags & 0xff, "FLUSH");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // need to grab a MUTEX for exclusive Queue,
 | 
					    // need to grab a MUTEX for exclusive Queue,
 | 
				
			||||||
    // what out if ISR is running?
 | 
					    // what out if ISR is running?
 | 
				
			||||||
    i2c_err_t rc=I2C_ERROR_OK;
 | 
					    i2c_err_t rc=I2C_ERROR_OK;
 | 
				
			||||||
@ -1425,91 +1660,27 @@ uint32_t i2cGetFrequency(i2c_t * i2c)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Stickbreaker ISR mode debug support
 | 
					uint32_t i2cDebug(i2c_t * i2c, uint32_t setBits, uint32_t resetBits){
 | 
				
			||||||
 */
 | 
					    if(i2c != NULL) {
 | 
				
			||||||
void i2cDumpDqData(i2c_t * i2c)
 | 
					        i2c->debugFlags = ((i2c->debugFlags | setBits) & ~resetBits);
 | 
				
			||||||
{
 | 
					        return i2c->debugFlags;
 | 
				
			||||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_ERROR
 | 
					 | 
				
			||||||
    uint16_t a=0;
 | 
					 | 
				
			||||||
    char buff[140];
 | 
					 | 
				
			||||||
    I2C_DATA_QUEUE_t *tdq;
 | 
					 | 
				
			||||||
    while(a<i2c->queueCount) {
 | 
					 | 
				
			||||||
        tdq=&i2c->dq[a];
 | 
					 | 
				
			||||||
        log_e("[%d] %sbit %x %c %s buf@=%p, len=%d, pos=%d, eventH=%p bits=%x",a,
 | 
					 | 
				
			||||||
        (tdq->ctrl.addr>0x100)?"10":"7",
 | 
					 | 
				
			||||||
        (tdq->ctrl.addr>0x100)?(((tdq->ctrl.addr&0x600)>>1)|(tdq->ctrl.addr&0xff)):(tdq->ctrl.addr>>1),
 | 
					 | 
				
			||||||
        (tdq->ctrl.mode)?'R':'W',
 | 
					 | 
				
			||||||
        (tdq->ctrl.stop)?"STOP":"",
 | 
					 | 
				
			||||||
        tdq->data,tdq->length,tdq->position,tdq->queueEvent,(tdq->queueEvent)?xEventGroupGetBits(tdq->queueEvent):0);
 | 
					 | 
				
			||||||
        uint16_t offset = 0;
 | 
					 | 
				
			||||||
        while(offset<tdq->length) {
 | 
					 | 
				
			||||||
            memset(buff,' ',140);
 | 
					 | 
				
			||||||
            buff[139]='\0';
 | 
					 | 
				
			||||||
            uint16_t i = 0,j;
 | 
					 | 
				
			||||||
            j=sprintf(buff,"0x%04x: ",offset);
 | 
					 | 
				
			||||||
            while((i<32)&&(offset < tdq->length)) {
 | 
					 | 
				
			||||||
                char ch = tdq->data[offset];
 | 
					 | 
				
			||||||
                sprintf((char*)&buff[(i*3)+41],"%02x ",ch);
 | 
					 | 
				
			||||||
                if((ch<32)||(ch>126)) {
 | 
					 | 
				
			||||||
                    ch='.';
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                j+=sprintf((char*)&buff[j],"%c",ch);
 | 
					 | 
				
			||||||
                buff[j]=' ';
 | 
					 | 
				
			||||||
                i++;
 | 
					 | 
				
			||||||
                offset++;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            log_e("%s",buff);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        a++;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
#endif
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
void i2cDumpI2c(i2c_t * i2c)
 | 
					 }
 | 
				
			||||||
{
 | 
					 
 | 
				
			||||||
    log_e("i2c=%p",i2c);
 | 
					uint32_t i2cGetStatus(i2c_t * i2c){
 | 
				
			||||||
    log_e("dev=%p date=%p",i2c->dev,i2c->dev->date);
 | 
					    if(i2c != NULL){
 | 
				
			||||||
#if !CONFIG_DISABLE_HAL_LOCKS
 | 
					        return i2c->dev->status_reg.val;
 | 
				
			||||||
    log_e("lock=%p",i2c->lock);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
    log_e("num=%d",i2c->num);
 | 
					 | 
				
			||||||
    log_e("mode=%d",i2c->mode);
 | 
					 | 
				
			||||||
    log_e("stage=%d",i2c->stage);
 | 
					 | 
				
			||||||
    log_e("error=%d",i2c->error);
 | 
					 | 
				
			||||||
    log_e("event=%p bits=%x",i2c->i2c_event,(i2c->i2c_event)?xEventGroupGetBits(i2c->i2c_event):0);
 | 
					 | 
				
			||||||
    log_e("intr_handle=%p",i2c->intr_handle);
 | 
					 | 
				
			||||||
    log_e("dq=%p",i2c->dq);
 | 
					 | 
				
			||||||
    log_e("queueCount=%d",i2c->queueCount);
 | 
					 | 
				
			||||||
    log_e("queuePos=%d",i2c->queuePos);
 | 
					 | 
				
			||||||
    log_e("errorByteCnt=%d",i2c->errorByteCnt);
 | 
					 | 
				
			||||||
    log_e("errorQueue=%d",i2c->errorQueue);
 | 
					 | 
				
			||||||
    if(i2c->dq) {
 | 
					 | 
				
			||||||
        i2cDumpDqData(i2c);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    else return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
void i2cDumpInts(uint8_t num)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO) && (defined ENABLE_I2C_DEBUG_BUFFER)  
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    uint32_t b;
 | 
					 | 
				
			||||||
    log_e("%u row  count   INTR    TX     RX",num);
 | 
					 | 
				
			||||||
    for(uint32_t a=1; a<=INTBUFFMAX; a++) {
 | 
					 | 
				
			||||||
        b=(a+intPos[num])%INTBUFFMAX;
 | 
					 | 
				
			||||||
        if(intBuff[b][0][num]!=0) {
 | 
					 | 
				
			||||||
            log_e("[%02d] 0x%04x 0x%04x 0x%04x 0x%04x 0x%08x",b,((intBuff[b][0][num]>>16)&0xFFFF),(intBuff[b][0][num]&0xFFFF),((intBuff[b][1][num]>>16)&0xFFFF),(intBuff[b][1][num]&0xFFFF),intBuff[b][2][num]);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
    log_i("Debug Buffer not Enabled");
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* todo
 | 
					/* todo
 | 
				
			||||||
  22JUL18
 | 
					  22JUL18
 | 
				
			||||||
    need to add multi-thread capability, use dq.queueEvent as the group marker. When multiple threads
 | 
					    need to add multi-thread capability, use dq.queueEvent as the group marker. When multiple threads
 | 
				
			||||||
    transactions are present in the same queue, and an error occurs, abort all succeeding unserviced transactions
 | 
					    transactions are present in the same queue, and an error occurs, abort all succeeding unserviced transactions
 | 
				
			||||||
    with the same dq.queueEvent value.  Succeeding unserviced transactions with different dq.queueEvent values
 | 
					    with the same dq.queueEvent value.  Succeeding unserviced transactions with different dq.queueEvent values
 | 
				
			||||||
    can be re-queued and processed independently. 
 | 
					    can be re-queued and processed independently. 
 | 
				
			||||||
 | 
					  30JUL18 complete data only queue elements, this will allow transfers to use multiple data blocks, 
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -48,6 +48,7 @@ i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, uint8_t* buff, uint16_t size, b
 | 
				
			|||||||
i2c_err_t i2cFlush(i2c_t *i2c);
 | 
					i2c_err_t i2cFlush(i2c_t *i2c);
 | 
				
			||||||
i2c_err_t i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed);
 | 
					i2c_err_t i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed);
 | 
				
			||||||
uint32_t i2cGetFrequency(i2c_t * i2c);
 | 
					uint32_t i2cGetFrequency(i2c_t * i2c);
 | 
				
			||||||
 | 
					uint32_t i2cGetStatus(i2c_t * i2c); // Status register of peripheral
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//Functions below should be used only if well understood
 | 
					//Functions below should be used only if well understood
 | 
				
			||||||
//Might be deprecated and removed in future
 | 
					//Might be deprecated and removed in future
 | 
				
			||||||
@ -62,8 +63,17 @@ i2c_err_t i2cAddQueueWrite(i2c_t *i2c, uint16_t i2cDeviceAddr, uint8_t *dataPtr,
 | 
				
			|||||||
i2c_err_t i2cAddQueueRead(i2c_t *i2c, uint16_t i2cDeviceAddr, uint8_t *dataPtr, uint16_t dataLen, bool SendStop, EventGroupHandle_t event);
 | 
					i2c_err_t i2cAddQueueRead(i2c_t *i2c, uint16_t i2cDeviceAddr, uint8_t *dataPtr, uint16_t dataLen, bool SendStop, EventGroupHandle_t event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//stickbreaker debug support
 | 
					//stickbreaker debug support
 | 
				
			||||||
void i2cDumpInts(uint8_t num);
 | 
					uint32_t i2cDebug(i2c_t *, uint32_t setBits, uint32_t resetBits);
 | 
				
			||||||
void i2cDumpI2c(i2c_t *i2c);
 | 
					//  Debug actions have 3 currently defined locus 
 | 
				
			||||||
 | 
					// 0xXX------ : at entry of ProcQueue 
 | 
				
			||||||
 | 
					// 0x--XX---- : at exit of ProcQueue
 | 
				
			||||||
 | 
					// 0x------XX : at entry of Flush
 | 
				
			||||||
 | 
					// 
 | 
				
			||||||
 | 
					// bit 0 causes DumpI2c to execute 
 | 
				
			||||||
 | 
					// bit 1 causes DumpInts to execute
 | 
				
			||||||
 | 
					// bit 2 causes DumpCmdqueue to execute
 | 
				
			||||||
 | 
					// bit 3 causes DumpStatus to execute
 | 
				
			||||||
 | 
					// bit 4 causes DumpFifo to execute
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -58,7 +58,7 @@ TwoWire::~TwoWire()
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)
 | 
					bool TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(sdaPin < 0) { // default param passed
 | 
					    if(sdaPin < 0) { // default param passed
 | 
				
			||||||
        if(num == 0) {
 | 
					        if(num == 0) {
 | 
				
			||||||
@ -70,7 +70,7 @@ void TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)
 | 
				
			|||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            if(sda==-1) {
 | 
					            if(sda==-1) {
 | 
				
			||||||
                log_e("no Default SDA Pin for Second Peripheral");
 | 
					                log_e("no Default SDA Pin for Second Peripheral");
 | 
				
			||||||
                return; //no Default pin for Second Peripheral
 | 
					                return false; //no Default pin for Second Peripheral
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                sdaPin = sda;    // reuse prior pin
 | 
					                sdaPin = sda;    // reuse prior pin
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -87,7 +87,7 @@ void TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)
 | 
				
			|||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            if(scl == -1) {
 | 
					            if(scl == -1) {
 | 
				
			||||||
                log_e("no Default SCL Pin for Second Peripheral");
 | 
					                log_e("no Default SCL Pin for Second Peripheral");
 | 
				
			||||||
                return; //no Default pin for Second Peripheral
 | 
					                return false; //no Default pin for Second Peripheral
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                sclPin = scl;    // reuse prior pin
 | 
					                sclPin = scl;    // reuse prior pin
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -98,10 +98,11 @@ void TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)
 | 
				
			|||||||
    scl = sclPin;
 | 
					    scl = sclPin;
 | 
				
			||||||
    i2c = i2cInit(num, sdaPin, sclPin, frequency);
 | 
					    i2c = i2cInit(num, sdaPin, sclPin, frequency);
 | 
				
			||||||
    if(!i2c) {
 | 
					    if(!i2c) {
 | 
				
			||||||
        return;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    flush();
 | 
					    flush();
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -145,6 +146,7 @@ void TwoWire::beginTransmission(uint16_t address)
 | 
				
			|||||||
    txAddress = address;
 | 
					    txAddress = address;
 | 
				
			||||||
    txIndex = txQueued; // allow multiple beginTransmission(),write(),endTransmission(false) until endTransmission(true)
 | 
					    txIndex = txQueued; // allow multiple beginTransmission(),write(),endTransmission(false) until endTransmission(true)
 | 
				
			||||||
    txLength = txQueued;
 | 
					    txLength = txQueued;
 | 
				
			||||||
 | 
					    last_error = I2C_ERROR_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*stickbreaker isr
 | 
					/*stickbreaker isr
 | 
				
			||||||
@ -202,6 +204,7 @@ size_t TwoWire::write(uint8_t data)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    if(transmitting) {
 | 
					    if(transmitting) {
 | 
				
			||||||
        if(txLength >= I2C_BUFFER_LENGTH) {
 | 
					        if(txLength >= I2C_BUFFER_LENGTH) {
 | 
				
			||||||
 | 
					            last_error = I2C_ERROR_MEMORY;
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        txBuffer[txIndex] = data;
 | 
					        txBuffer[txIndex] = data;
 | 
				
			||||||
@ -209,20 +212,19 @@ size_t TwoWire::write(uint8_t data)
 | 
				
			|||||||
        txLength = txIndex;
 | 
					        txLength = txIndex;
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    last_error = I2C_ERROR_NO_BEGIN; // no begin, not transmitting
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
size_t TwoWire::write(const uint8_t *data, size_t quantity)
 | 
					size_t TwoWire::write(const uint8_t *data, size_t quantity)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(transmitting) {
 | 
					    for(size_t i = 0; i < quantity; ++i) {
 | 
				
			||||||
        for(size_t i = 0; i < quantity; ++i) {
 | 
					        if(!write(data[i])) {
 | 
				
			||||||
            if(!write(data[i])) {
 | 
					            return i;
 | 
				
			||||||
                return i;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return quantity;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return 0;
 | 
					    return quantity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int TwoWire::available(void)
 | 
					int TwoWire::available(void)
 | 
				
			||||||
@ -353,14 +355,13 @@ char * TwoWire::getErrorText(uint8_t err)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/*stickbreaker Dump i2c Interrupt buffer, i2c isr Debugging
 | 
					/*stickbreaker Dump i2c Interrupt buffer, i2c isr Debugging
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void TwoWire::dumpInts()
 | 
					 
 | 
				
			||||||
{
 | 
					uint32_t TwoWire::setDebugFlags( uint32_t setBits, uint32_t resetBits){
 | 
				
			||||||
    i2cDumpInts(num);
 | 
					  return i2cDebug(i2c,setBits,resetBits);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TwoWire::dumpI2C()
 | 
					bool TwoWire::busy(void){
 | 
				
			||||||
{
 | 
					  return ((i2cGetStatus(i2c) & 16 )==16);
 | 
				
			||||||
    i2cDumpI2c(i2c);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TwoWire Wire = TwoWire(0);
 | 
					TwoWire Wire = TwoWire(0);
 | 
				
			||||||
 | 
				
			|||||||
@ -30,7 +30,7 @@
 | 
				
			|||||||
#include "freertos/queue.h"
 | 
					#include "freertos/queue.h"
 | 
				
			||||||
#include "Stream.h"
 | 
					#include "Stream.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define STICKBREAKER V0.2.2
 | 
					#define STICKBREAKER V1.0.1
 | 
				
			||||||
#define I2C_BUFFER_LENGTH 128
 | 
					#define I2C_BUFFER_LENGTH 128
 | 
				
			||||||
typedef void(*user_onRequest)(void);
 | 
					typedef void(*user_onRequest)(void);
 | 
				
			||||||
typedef void(*user_onReceive)(uint8_t*, int);
 | 
					typedef void(*user_onReceive)(uint8_t*, int);
 | 
				
			||||||
@ -67,7 +67,7 @@ protected:
 | 
				
			|||||||
public:
 | 
					public:
 | 
				
			||||||
    TwoWire(uint8_t bus_num);
 | 
					    TwoWire(uint8_t bus_num);
 | 
				
			||||||
    ~TwoWire();
 | 
					    ~TwoWire();
 | 
				
			||||||
    void begin(int sda=-1, int scl=-1, uint32_t frequency=0);
 | 
					    bool begin(int sda=-1, int scl=-1, uint32_t frequency=0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void setClock(uint32_t frequency); // change bus clock without initing hardware
 | 
					    void setClock(uint32_t frequency); // change bus clock without initing hardware
 | 
				
			||||||
    size_t getClock(); // current bus clock rate in hz
 | 
					    size_t getClock(); // current bus clock rate in hz
 | 
				
			||||||
@ -129,8 +129,8 @@ public:
 | 
				
			|||||||
    void onReceive( void (*)(int) );
 | 
					    void onReceive( void (*)(int) );
 | 
				
			||||||
    void onRequest( void (*)(void) );
 | 
					    void onRequest( void (*)(void) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void dumpInts();
 | 
					    uint32_t setDebugFlags( uint32_t setBits, uint32_t resetBits);
 | 
				
			||||||
    void dumpI2C();
 | 
					    bool busy();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern TwoWire Wire;
 | 
					extern TwoWire Wire;
 | 
				
			||||||
@ -138,6 +138,9 @@ extern TwoWire Wire1;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 | 
					V1.0.1 02AUG2018 First Fix after release, Correct ReSTART handling, change Debug control, change begin()
 | 
				
			||||||
 | 
					  to a function, this allow reporting if bus cannot be initialized, Wire.begin() can be used to recover
 | 
				
			||||||
 | 
					  a hung bus busy condition.
 | 
				
			||||||
V0.2.2 13APR2018 preserve custom SCL,SDA,Frequency when no parameters passed to begin()
 | 
					V0.2.2 13APR2018 preserve custom SCL,SDA,Frequency when no parameters passed to begin()
 | 
				
			||||||
V0.2.1 15MAR2018 Hardware reset, Glitch prevention, adding destructor for second i2c testing
 | 
					V0.2.1 15MAR2018 Hardware reset, Glitch prevention, adding destructor for second i2c testing
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user