void read_xyz(uint8_t *buff) { uint16_t msg[] = {0x3a, 0x01, I2C_RESTART, 0x3b, I2C_READ, I2C_READ, I2C_READ, I2C_READ}; i2c_send_sequence(msg, 8, buff, LPM0_bits); LPM0; while(!i2c_done()); }
/** * @fn wakeup_tsl2561 * @author TheFwGuy * @brief Wakeup TSL2561 * * @param None * @return None */ void wakeup_tsl2561(void) { while(!i2c_done()); i2c_send_sequence((uint16_t *)seqwq, TSL2561_WAKEUP_LEN, (uint8_t *)recseq, 0); __delay_cycles(500000); /* Approx 35 ms */ }
/** * @fn config_tsl2561 * @author TheFwGuy * @brief Configure TSL2561 * * @param Integration time * @param Gain * @return None */ void config_tsl2561() { seqcn[2] = _tsl2561IntegrationTime | _tsl2561Gain; while(!i2c_done()); i2c_send_sequence((uint16_t *)seqcn, TSL2561_CONFIG_LEN, (uint8_t *)recseq, 0); }
void write_register(uint16_t reg, uint16_t val) { uint16_t msg[] = {0x3a, 0, 0}; msg[1] = reg; msg[2] = val; i2c_send_sequence(msg, 3, 0, LPM0_bits); LPM0; while(!i2c_done()); }
uint8_t read_register(uint16_t reg) { uint8_t val = 0; uint16_t msg[] = {0x3a, 0, I2C_RESTART, 0x3b, I2C_READ}; msg[1] = reg; i2c_send_sequence(msg, 5, &val, LPM0_bits); LPM0; while(!i2c_done()); return val; }
int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer unsigned char readin[32]; memset(readin, 0xFF, sizeof(readin)); /* Initiate the I2C bus */ i2c_init(USIDIV_5, USISSEL_2); #if 0 writeEEPROM(text, strlen(text)); #else i2c_send_sequence(arrayWrite, sizeof(arrayWrite), readin, 0); while(!i2c_done()) ; __delay_cycles(25000); // Wait 25 ms #endif #if 1 i2c_send_sequence(arrayRead, sizeof(arrayRead), readin, CPUOFF); while(!i2c_done()) ; #endif return 0; }
/** * @fn read_tsl2561 * @author TheFwGuy * @brief Read the TSL2561 * * @param Reading (TSL2561_FULLSPECTRUM, TSL2561_VISIBLE or TSL2561_INFRARED) * @return Intensity (LUX) */ int read_tsl2561(unsigned char reading) { uint16_t ch0 = 0; uint16_t ch1 = 0; uint32_t luxres; #if defined(READWORD) uint16_t seqread_CH0[] = TSL2561_READ16_CH0; uint16_t seqread_CH1[] = TSL2561_READ16_CH1; #else uint8_t result = 0; uint16_t seqread_lsb_CH0[] = TSL2561_READ8_CH0_LSB; uint16_t seqread_lsb_CH1[] = TSL2561_READ8_CH1_LSB; uint16_t seqread_msb_CH0[] = TSL2561_READ8_CH0_MSB; uint16_t seqread_msb_CH1[] = TSL2561_READ8_CH1_MSB; #endif /* Wake up sensor */ wakeup_tsl2561(); switch(reading) { case TSL2561_FULLSPECTRUM: #if defined(READWORD) while(!i2c_done()); i2c_send_sequence((uint16_t *)seqread_CH0, TSL2561_READ16_CH0_LEN, (uint8_t *)recseq, 0); ch0 = 256 * recseq[0] + recseq[1]; while(!i2c_done()); i2c_send_sequence((uint16_t *)seqread_CH1, TSL2561_READ16_CH1_LEN, (uint8_t *)recseq, 0); ch1 = 256 * recseq[0] + recseq[1]; #else while(!i2c_done()); i2c_send_sequence((uint16_t *)seqread_lsb_CH0, TSL2561_READ8_CH0_LSB_LEN, (uint8_t *)&result, 0); ch0 = result; while(!i2c_done()); i2c_send_sequence((uint16_t *)seqread_msb_CH0, TSL2561_READ8_CH0_MSB_LEN, (uint8_t *)&result, 0); ch0 += (result * 256); while(!i2c_done()); i2c_send_sequence((uint16_t *)seqread_lsb_CH1, TSL2561_READ8_CH1_LSB_LEN, (uint8_t *)&result, 0); ch1 = result; while(!i2c_done()); i2c_send_sequence((uint16_t *)seqread_msb_CH1, TSL2561_READ8_CH1_MSB_LEN, (uint8_t *)&result, 0); ch1 += (result * 256); #endif break; } sleep_tsl2561(); luxres = luxcalc(ch0, ch1); return (luxres); }
/** * @fn init_tsl2561 * @author TheFwGuy * @brief Init TSL2561 * * @param None * @return None */ void init_tsl2561(void) { /* * Read Tsl2561 ID */ recseq[0] = 0; while(!i2c_done()); i2c_send_sequence((uint16_t *)seqid, TSL2561_READID_LEN, (uint8_t *)recseq, 0); // if (recseq[0] == 0) // { // /* No chipset present - TBD what to do */ // } wakeup_tsl2561(); config_tsl2561(); sleep_tsl2561(); }
int main(void) { int count; int readSens; init(); /* Initialize the system */ #if defined LIGHT_SENSOR init_tsl2561(); #endif // wakeup_tsl2561(); while(1) { #if defined LIGHT_SENSOR /* * By default the light sensor is read. The encoder determine the position of the servo. * Pushing the pushbutton changes the mode. * Encoder vs. light sensor */ if(Pushbutton == ON) { switch(TogglePosition) { default: case 0: EncCounter = PWMSTART; TogglePosition = 1; break; case 1: // EncCounter = PWMSTOP; TogglePosition = 0; break; } Pushbutton = OFF; } if(TogglePosition) { if(i2c_done()) { readSens = read_tsl2561(TSL2561_FULLSPECTRUM); if(readSens < 4) EncCounter = PWMSTART; else if(readSens < 10) EncCounter = PWMSTART+10; else if(readSens < 40) EncCounter = PWMSTART+20; else if(readSens < 200) EncCounter = PWMSTART+30; else EncCounter = PWMSTOP; } } #else /* * The light sensor is not used. * The encoder determine the position of the servo. * Pushing the pushbutton changes the end-to-end */ if(Pushbutton == ON) { switch(TogglePosition) { default: case 0: EncCounter = PWMSTART; TogglePosition = 1; break; case 1: EncCounter = PWMSTOP; TogglePosition = 0; break; } Pushbutton = OFF; } #endif TA0CCR1 = EncCounter; /* * Update the Output port */ LED_PORT = Port1Shadow; } }
/** * @fn sleep_tsl2561 * @author TheFwGuy * @brief Put TSL2561 in sleep * * @param None * @return None */ void sleep_tsl2561(void) { while(!i2c_done()); i2c_send_sequence((uint16_t *)seqsl, TSL2561_SLEEP_LEN, (uint8_t *)recseq, 0); }
// // I2C ISR base handler // void i2c_isr_handler(struct i2cStruct* i2c, uint8_t bus) { uint8_t status, c1, data; uint8_t already_done=already_done=i2c_done(i2c); status = *(i2c->S); c1 = *(i2c->C1); I2C_DEBUG_INIT; I2C_DEBUG_STR("I"); I2C_DEBUG_REGS; // interrupt, reg dump if(c1 & I2C_C1_MST) { // // Master Mode // if(c1 & I2C_C1_TX) { // Continue Master Transmit I2C_DEBUG_STR("MT"); // master transmit // check if Master Tx or Rx if(i2c->currentStatus == I2C_SENDING) { // check if slave ACK'd if(status & I2C_S_RXAK) { I2C_DEBUG_STR("N"); // NAK if(i2c->txBufferIndex == 0) i2c->currentStatus = I2C_ADDR_NAK; // NAK on Addr else i2c->currentStatus = I2C_DATA_NAK; // NAK on Data // send STOP, change to Rx mode, intr disabled I2C_DEBUG_STR("STOP"); *(i2c->C1) = I2C_C1_IICEN; } else { I2C_DEBUG_STR("A"); // ACK // check if last byte transmitted if(++i2c->txBufferIndex >= i2c->txBufferLength) { // Tx complete, change to waiting state i2c->currentStatus = I2C_WAITING; // send STOP if configured if(i2c->currentStop == I2C_STOP) { // send STOP, change to Rx mode, intr disabled I2C_DEBUG_STR("STOP"); *(i2c->C1) = I2C_C1_IICEN; } else { // no STOP, stay in Tx mode, intr disabled *(i2c->C1) = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX; } } else { // transmit next byte *(i2c->D) = i2c->txBuffer[i2c->txBufferIndex]; I2C_DEBUG_STR("D:"); I2C_DEBUG_HEX(i2c->txBuffer[i2c->txBufferIndex]); // Tx data } } I2C_DEBUG_STRB("\n"); *(i2c->S) = I2C_S_IICIF; // clear intr // return;// fall through to user_onFinish() code } else if(i2c->currentStatus == I2C_SEND_ADDR) { // Master Receive, addr sent if(status & I2C_S_ARBL) { // Arbitration Lost I2C_DEBUG_STR("ARBL\n"); // arb lost i2c->currentStatus = I2C_ARB_LOST; *(i2c->C1) = I2C_C1_IICEN; // change to Rx mode, intr disabled (does this send STOP if ARBL flagged?) *(i2c->S) = I2C_S_ARBL | I2C_S_IICIF; // clear arbl flag and intr // return;// fall through to user_onFinish() code } else { if(status & I2C_S_RXAK) { // Slave addr NAK I2C_DEBUG_STR("N"); // NAK i2c->currentStatus = I2C_ADDR_NAK; // NAK on Addr // send STOP, change to Rx mode, intr disabled I2C_DEBUG_STR("STOP"); *(i2c->C1) = I2C_C1_IICEN; } else { // Slave addr ACK, change to Rx mode I2C_DEBUG_STR("A"); // ACK i2c->currentStatus = I2C_RECEIVING; if(i2c->reqCount == 1) *(i2c->C1) = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_MST | I2C_C1_TXAK; // no STOP, Rx, NAK on recv else *(i2c->C1) = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_MST; // no STOP, change to Rx data = *(i2c->D); // dummy read } I2C_DEBUG_STRB("\n"); *(i2c->S) = I2C_S_IICIF; // clear intr } // return; // fall through to user_onFinish() code } else if(i2c->currentStatus == I2C_TIMEOUT) { // send STOP if configured if(i2c->currentStop == I2C_STOP) { // send STOP, change to Rx mode, intr disabled I2C_DEBUG_STR("STOP\n"); I2C_DEBUG_STR("TMOUT\n"); *(i2c->C1) = I2C_C1_IICEN; } else { // no STOP, stay in Tx mode, intr disabled I2C_DEBUG_STR("TMOUT\n"); *(i2c->C1) = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX; } *(i2c->S) = I2C_S_IICIF; // clear intr // return; // fall through to user_onFinish() code } else { // Should not be in Tx mode if not sending // send STOP, change to Rx mode, intr disabled I2C_DEBUG_STR("WTF\n"); *(i2c->C1) = I2C_C1_IICEN; *(i2c->S) = I2C_S_IICIF; // clear intr // return; // fall through to user_onFinish() code } } else { // Continue Master Receive I2C_DEBUG_STR("MR"); // master receive // check if 2nd to last byte or timeout if((i2c->rxBufferLength+2) == i2c->reqCount || (i2c->currentStatus == I2C_TIMEOUT && !i2c->timeoutRxNAK)) *(i2c->C1) = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_MST | I2C_C1_TXAK; // no STOP, Rx, NAK on recv // if last byte or timeout send STOP if((i2c->rxBufferLength+1) >= i2c->reqCount || (i2c->currentStatus == I2C_TIMEOUT && i2c->timeoutRxNAK)) { i2c->timeoutRxNAK = 0; // clear flag if(i2c->currentStatus != I2C_TIMEOUT) i2c->currentStatus = I2C_WAITING; // Rx complete, change to waiting state // change to Tx mode *(i2c->C1) = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX; // grab last data data = *(i2c->D); I2C_DEBUG_STR("D:"); I2C_DEBUG_HEX(data); // Rx data if(i2c->rxBufferLength < I2C_RX_BUFFER_LENGTH) i2c->rxBuffer[i2c->rxBufferLength++] = data; if(i2c->currentStop == I2C_STOP) { I2C_DEBUG_STR("N"); I2C_DEBUG_STR("STOP\n"); // NAK and STOP delayMicroseconds(1); // empirical patch, lets things settle before issuing STOP *(i2c->C1) = I2C_C1_IICEN; // send STOP, change to Rx mode, intr disabled } else I2C_DEBUG_STR("N\n"); // NAK no STOP if(i2c->currentStatus == I2C_TIMEOUT) I2C_DEBUG_STR("TMOUT\n"); // timeout } else { // grab next data data = *(i2c->D); I2C_DEBUG_STR("D:"); I2C_DEBUG_HEX(data); // Rx data if(i2c->rxBufferLength < I2C_RX_BUFFER_LENGTH) i2c->rxBuffer[i2c->rxBufferLength++] = data; I2C_DEBUG_STR("A\n"); // not last byte, mark as ACK } if(i2c->currentStatus == I2C_TIMEOUT && !i2c->timeoutRxNAK) i2c->timeoutRxNAK = 1; // set flag to indicate NAK sent *(i2c->S) = I2C_S_IICIF; // clear intr // return;// fall through to user_onFinish() code } if ( i2c->user_onFinish && !already_done && i2c_done(i2c) ) { i2c->user_onFinish(); } return; } else { // // Slave Mode // if(status & I2C_S_ARBL) { // Arbitration Lost I2C_DEBUG_STR("ARBL"); // arb lost *(i2c->S) = I2C_S_ARBL; // clear arbl flag if(!(status & I2C_S_IAAS)) { I2C_DEBUG_STRB("\n"); *(i2c->S) = I2C_S_IICIF; // clear intr return; } } if(status & I2C_S_IAAS) { // If in Slave Rx already, then RepSTART occured, run callback if(i2c->currentStatus == I2C_SLAVE_RX && i2c->user_onReceive != NULL) { I2C_DEBUG_STR("RSTART"); i2c->rxBufferIndex = 0; i2c->user_onReceive(i2c->rxBufferLength); } // Is Addressed As Slave if(status & I2C_S_SRW) { // Begin Slave Transmit I2C_DEBUG_STR("AST"); // addressed slave transmit i2c->currentStatus = I2C_SLAVE_TX; i2c->txBufferLength = 0; if(i2c->user_onRequest != NULL) i2c->user_onRequest(); // load Tx buffer with data I2C_DEBUG_STR("BL:"); I2C_DEBUG_HEX(i2c->txBufferLength >> 8); I2C_DEBUG_HEX(i2c->txBufferLength); // buf len if(i2c->txBufferLength == 0) i2c->txBuffer[0] = 0; // send 0's if buffer empty *(i2c->C1) = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_TX; i2c->rxAddr = (*(i2c->D) >> 1); // read to get target addr *(i2c->D) = i2c->txBuffer[0]; // send first data i2c->txBufferIndex = 1; I2C_DEBUG_STR("D:"); I2C_DEBUG_HEX(i2c->txBuffer[0]); // Tx data } else { // Begin Slave Receive I2C_DEBUG_STR("ASR"); // addressed slave receive i2c->irqCount = 0; // setup SDA-rising ISR if(i2c->currentPins == I2C_PINS_18_19) attachInterrupt(18, i2c_t3::sda0_rising_isr, RISING); else if(i2c->currentPins == I2C_PINS_16_17) attachInterrupt(17, i2c_t3::sda0_rising_isr, RISING); #if I2C_BUS_NUM >= 2 else if(i2c->currentPins == I2C_PINS_29_30) attachInterrupt(30, i2c_t3::sda1_rising_isr, RISING); else if(i2c->currentPins == I2C_PINS_26_31) attachInterrupt(31, i2c_t3::sda1_rising_isr, RISING); #endif i2c->currentStatus = I2C_SLAVE_RX; i2c->rxBufferLength = 0; *(i2c->C1) = I2C_C1_IICEN | I2C_C1_IICIE; i2c->rxAddr = (*(i2c->D) >> 1); // read to get target addr } I2C_DEBUG_STRB("\n"); *(i2c->S) = I2C_S_IICIF; // clear intr return; }
uint8_t i2c_t3::done_(struct i2cStruct* i2c) { return i2c_done(i2c); }