コード例 #1
0
ファイル: WiiNunchuck.c プロジェクト: 0xD34D/ATmega
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;
}
コード例 #2
0
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;
				}
		}
}