int Wii_Data( nunchuck_data_t *data ) { int i = 0x21; if (data == 0) return -1; // send 0x00 to let nunchuck know we are going to request data i2c_start(); // send start i2c_sendByte(WII_ADDR); i2c_sendByte(0x00); i2c_stop(); // switch to read mode by adding 1 to WII_ADDR _delay_ms(1); i2c_start(); // send start i2c_sendByte(WII_ADDR | 1); uint8_t *packet = (uint8_t*)data; for(i = 0; i < 6; i++) { if(i < 5) { i2c_ack(); } else { i2c_nack(); } *(packet+i) = i2c_getByte(); } i2c_stop(); return i; }
i2c_interrupt() { static uint8_t addrFailCnt; SOS_MEASUREMENT_IDLE_END(); // TWSR & TW_STATUS_MASK switch (TWSR) { /************************* * Master General States * *************************/ case TWI_START: /* 0x08 */ addrFailCnt = 0; i2c.idx = 0; // Fall through! case TWI_REP_START: /* 0x10 */ i2c_setByte(i2c.addr|((i2c.flags & I2C_TX_FLAG)?0:1)); // only set R/W bit if reading i2c_setCtrlReg((1<<TWINT)|(1<<TWEN)|(1<<TWIE)); break; case TWI_ARB_LOST: /* 0x38 */ i2c_setCtrlReg((1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE)); // Initate a (RE)START condition // TWI hardware will resend start when bus is free and signal TWI_RESTART break; /***************************** * Master Transmitter States * *****************************/ case TWI_MTX_ADR_ACK: /* 0x18 */ i2c.state = I2C_MASTER_TX; if (i2c.flags & I2C_SOS_MSG_FLAG) { // this is a difference between the i2c and uart // uart uses a protocol byte for BOTH raw and sos_msgs // i2c ONLY sends a protocol byte in the case of a sos_msg i2c_setByte(HDLC_SOS_MSG); i2c.msg_state = SOS_MSG_TX_HDR; // this is a sos_msg so a crc is required i2c.crc = crcByte(0, HDLC_SOS_MSG); i2c_setCtrlReg((1<<TWINT)|(1<<TWEN)|(1<<TWIE)); break; } else { i2c.msg_state = SOS_MSG_TX_RAW; } // fall through case TWI_MTX_DATA_ACK: /* 0x28 */ switch (i2c.msg_state) { case SOS_MSG_TX_HDR: i2c_setByte(((uint8_t*)(i2c.msgBuf))[i2c.idx]); // this is a sos_msg so a crc is required i2c.crc = crcByte(i2c.crc, ((uint8_t*)(i2c.msgBuf))[i2c.idx]); i2c.idx++; if (i2c.idx == SOS_MSG_HEADER_SIZE) { i2c.idx = 0; i2c.txPending = i2c.msgLen + SOS_MSG_CRC_SIZE; i2c.msg_state = SOS_MSG_TX_DATA; } break; case SOS_MSG_TX_RAW: case SOS_MSG_TX_DATA: i2c_setByte(i2c.dataBuf[i2c.idx]); if (i2c.flags & I2C_CRC_FLAG) { i2c.crc = crcByte(i2c.crc, i2c.dataBuf[i2c.idx]); } i2c.idx++; if (i2c.idx == i2c.msgLen) { if (!(i2c.flags & I2C_CRC_FLAG)) { // send stop bit and reset interface to ready state i2c.txPending = 0; i2c.msg_state = SOS_MSG_TX_END; } else { i2c.txPending = SOS_MSG_CRC_SIZE; // no unsent bytes i2c.msg_state = SOS_MSG_TX_CRC_LOW; } } break; case SOS_MSG_TX_CRC_LOW: i2c_setByte((uint8_t)(i2c.crc)); i2c.txPending--; i2c.msg_state = SOS_MSG_TX_CRC_HIGH; break; case SOS_MSG_TX_CRC_HIGH: i2c_setByte((uint8_t)(i2c.crc>>8)); i2c.txPending--; i2c.msg_state = SOS_MSG_TX_END; break; case SOS_MSG_TX_END: // send stop bit and reset interface to ready state i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE)); i2c_send_done(i2c.flags); i2c.state = restoreState(); return; default: break; } // normal send byte all stop conditions must return and not get here i2c_setCtrlReg((1<<TWINT)|(1<<TWEN)|(1<<TWIE)); break; case TWI_MTX_ADR_NACK: /* 0x20 */ if (addrFailCnt++ < MAX_ADDR_FAIL) { // try restarting MAX_ADDR_FAIL times then fail i2c_setCtrlReg((1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE)); } else { // reset i2c and send msg fail to process i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE)); i2c_send_done(i2c.flags|I2C_ERROR_FLAG); i2c.state = restoreState(); } break; case TWI_MTX_DATA_NACK: /* 0x30 */ // reset i2c and send msg fail to process i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE)); i2c.txPending = i2c.txPending - i2c.idx + 1; // last byte failed i2c_send_done(i2c.flags|I2C_BUFF_ERR_FLAG); i2c.state = restoreState(); break; /*************************** * Master Receiver States * ***************************/ case TWI_MRX_ADR_ACK: /* 0x40 */ i2c.state = I2C_MASTER_RX; i2c.rxStatus = i2c.flags; // all master rx are done in raw mode with NO protocol byte i2c.msg_state = SOS_MSG_RX_RAW; // a sos message will never be recieved as a manster if (i2c.msgLen == 1) { i2c.msg_state = SOS_MSG_RX_END; i2c_setCtrlReg((1<<TWINT)|(1<<TWEN)|(1<<TWIE)); } else { i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE)); } break; case TWI_MRX_DATA_ACK: /* 0x50 */ i2c.dataBuf[i2c.idx++] = i2c_getByte(); if (i2c.idx < (i2c.msgLen-1)) { i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE)); } else { // unset TWEA (Send NACK after next/last byte) i2c.msg_state = SOS_MSG_RX_END; i2c_setCtrlReg((1<<TWINT)|(1<<TWEN)|(1<<TWIE)); } break; case TWI_MRX_ADR_NACK: /* 0x48 */ if (addrFailCnt++ < MAX_ADDR_FAIL) { // tryrestarting MAX_ADDR_FAIL times then fail i2c_setCtrlReg((1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE)); break; } i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE)); // return data i2c_read_done(i2c.dataBuf, i2c.idx, i2c.rxStatus); i2c.idx = 0; i2c.rxStatus = 0; i2c.state = restoreState(); break; case TWI_MRX_DATA_NACK: /* 0x58 */ i2c.dataBuf[i2c.idx++] = i2c_getByte(); if (i2c.idx < i2c.msgLen) { // nack from master indication rx done // send stop bit, clear interrupt and reset interface to ready state i2c.rxStatus |= I2C_BUFF_ERR_FLAG; } // set flags and return data i2c.rxStatus |= I2C_BUFF_DIRTY_FLAG; i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE)); i2c_read_done(i2c.dataBuf, i2c.idx, i2c.rxStatus); i2c.idx = 0; i2c.rxStatus = 0; i2c.state = restoreState(); break; /**************************** * Slave Transmitter States * ****************************/ case TWI_STX_ADR_ACK: /* 0xA8 */ case TWI_STX_ADR_ACK_M_ARB_LOST: /* 0xB0 */ if (i2c.state != I2C_SLAVE_WAIT) { i2c_send_done(i2c.flags|I2C_ERROR_FLAG); break; } else { saveState(i2c.state); i2c.state = I2C_SLAVE_TX; i2c.msg_state = SOS_MSG_TX_RAW; } // fall through case TWI_STX_DATA_ACK: /* 0xB8 */ if (i2c.msg_state == SOS_MSG_TX_RAW) { i2c_setByte(i2c.dataBuf[i2c.idx++]); // unset TWEA (Send NACK after next/last byte) if (i2c.msgLen == i2c.idx) { i2c_setCtrlReg((1<<TWINT)|(1<<TWEN)|(1<<TWIE)); i2c.txPending = 1; // last byte failed i2c.msg_state = SOS_MSG_TX_END; } else { // Reset the TWI Interupt to wait to ack next byte i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE)); } } break; case TWI_STX_DATA_NACK: /* 0xC0 */ // Master has sent a NACK before expected amount of data was sent. // set dirty bit on send buffer go to end state and issue send done if (i2c.msg_state != SOS_MSG_TX_END) { i2c.txPending = i2c.txPending - i2c.idx + 1; // last byte failed i2c.msg_state = SOS_MSG_TX_END; } else { i2c.txPending = 0; } i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE)); if (i2c.msg_state == SOS_MSG_TX_END) { i2c.msg_state = SOS_MSG_NO_STATE; i2c_send_done(i2c.flags); } break; case TWI_STX_DATA_ACK_LAST_BYTE: /* 0xC8 */ i2c.msg_state = SOS_MSG_NO_STATE; i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE)); i2c_send_done(i2c.flags|I2C_BUFF_ERR_FLAG); break; /************************* * Slave Receiver States * *************************/ // all receptions are done in a raw mode // if it is a sos message it it will be packed later case TWI_SRX_GEN_ACK: /* 0x70 */ case TWI_SRX_GEN_ACK_M_ARB_LOST: /* 0x78 */ i2c.rxStatus = I2C_GEN_ADDR_FLAG; // fall through case TWI_SRX_ADR_ACK: /* 0x60 */ case TWI_SRX_ADR_ACK_M_ARB_LOST: /* 0x68 */ saveState(i2c.state); i2c.state = I2C_SLAVE_RX; i2c.msg_state = SOS_MSG_RX_RAW; i2c.idx = 0; i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE)); break; case TWI_SRX_ADR_DATA_ACK: /* 0x80 */ case TWI_SRX_GEN_DATA_ACK: /* 0x90 */ if (i2c.msg_state == SOS_MSG_RX_RAW) { i2c.rxDataBuf[i2c.idx++] = i2c_getByte(); if (i2c.idx >= I2C_MAX_MSG_LEN) { // buffer overflow i2c.msg_state = SOS_MSG_RX_END; // set flags and return data i2c.rxStatus |= (I2C_BUFF_DIRTY_FLAG|I2C_BUFF_ERR_FLAG); i2c_read_done(i2c.rxDataBuf, i2c.idx, i2c.rxStatus); i2c.idx = 0; i2c.rxStatus = 0; } } i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE)); break; case TWI_SRX_ADR_DATA_NACK: /* 0x88 */ case TWI_SRX_GEN_DATA_NACK: /* 0x98 */ // switch to not addressed mode if (i2c.msg_state == SOS_MSG_RX_RAW) { // set flags and return data i2c.rxStatus |= I2C_BUFF_DIRTY_FLAG; i2c_read_done(i2c.rxDataBuf, i2c.idx, i2c.rxStatus); i2c.idx = 0; i2c.rxStatus = 0; i2c.msg_state = SOS_MSG_RX_END; } i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE)); break; case TWI_SRX_STOP_RESTART: /* 0xA0 */ // reset reciever i2c.msg_state = SOS_MSG_NO_STATE; if (i2c.idx > 0) { // need to make sure data has been read i2c.rxStatus |= I2C_BUFF_DIRTY_FLAG; i2c_read_done(i2c.rxDataBuf, i2c.idx, i2c.rxStatus); i2c.idx = 0; i2c.rxStatus = 0; } i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE)); i2c.state = restoreState(); break; /*************** * Misc States * ***************/ //case TWI_NO_STATE: /* 0xF8 */ case TWI_BUS_ERROR: /* 0x00 */ default: { uint8_t twiStatus=0; // Store TWSR and automatically sets clears noErrors bit. twiStatus = TWSR; // Clear TWINT and reset TWI Interface i2c_setCtrlReg((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE)); i2c.state = I2C_IDLE; // should really be i2c_error i2c_send_done(I2C_NULL_FLAG); break; } } }