0,0 → 1,164 |
#include <avr/io.h> |
#include <avr/interrupt.h> |
#include <util/twi.h> |
#include <util/delay.h> |
//#include "eeprom.h" |
#include "twimaster.h" |
//#include "analog.h" |
#include "configuration.h" |
|
volatile uint8_t twi_state = TWI_STATE_IDLE; |
volatile uint8_t dac_channel = 0; |
volatile uint16_t I2CTimeout = 100; |
volatile uint8_t DACValues[4]; |
uint8_t DACChannel = 0; |
|
#define SCL_CLOCK 200000L |
#define I2C_TIMEOUT 30000 |
|
/************************************************** |
* Initialize I2C (TWI) |
**************************************************/ |
void I2C_init(void) { |
uint8_t i; |
uint8_t sreg = SREG; |
cli(); |
|
// SDA is INPUT |
DDRC &= ~(1 << DDC1); |
// SCL is output |
DDRC |= (1 << DDC0); |
// pull up SDA |
PORTC |= (1 << PORTC0) | (1 << PORTC1); |
|
// TWI Status Register |
// prescaler 1 (TWPS1 = 0, TWPS0 = 0) |
TWSR &= ~((1 << TWPS1) | (1 << TWPS0)); |
|
// set TWI Bit Rate Register |
TWBR = ((SYSCLK / SCL_CLOCK) - 16) / 2; |
|
twi_state = TWI_STATE_IDLE; |
SREG = sreg; |
} |
|
/**************************************** |
* Start I2C |
****************************************/ |
void I2C_Start(uint8_t start_state) { |
twi_state = start_state; |
// TWI Control Register |
// clear TWI interrupt flag (TWINT=1) |
// disable TWI Acknowledge Bit (TWEA = 0) |
// enable TWI START Condition Bit (TWSTA = 1), MASTER |
// disable TWI STOP Condition Bit (TWSTO = 0) |
// disable TWI Write Collision Flag (TWWC = 0) |
// enable i2c (TWEN = 1) |
// enable TWI Interrupt (TWIE = 1) |
TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN) | (1 << TWIE); |
} |
|
/**************************************** |
* Stop I2C |
****************************************/ |
void I2C_Stop(uint8_t start_state) { |
twi_state = start_state; |
// TWI Control Register |
// clear TWI interrupt flag (TWINT=1) |
// disable TWI Acknowledge Bit (TWEA = 0) |
// diable TWI START Condition Bit (TWSTA = 1), no MASTER |
// enable TWI STOP Condition Bit (TWSTO = 1) |
// disable TWI Write Collision Flag (TWWC = 0) |
// enable i2c (TWEN = 1) |
// disable TWI Interrupt (TWIE = 0) |
TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); |
} |
|
/**************************************** |
* Write to I2C |
****************************************/ |
void I2C_WriteByte(int8_t byte) { |
// move byte to send into TWI Data Register |
TWDR = byte; |
// clear interrupt flag (TWINT = 1) |
// enable i2c bus (TWEN = 1) |
// enable interrupt (TWIE = 1) |
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE); |
} |
|
/**************************************** |
* Receive byte and send ACK |
****************************************/ |
void I2C_ReceiveByte(void) { |
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE) | (1 << TWEA); |
} |
|
/**************************************** |
* I2C receive last byte and send no ACK |
****************************************/ |
void I2C_ReceiveLastByte(void) { |
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE); |
} |
|
/**************************************** |
* Reset I2C |
****************************************/ |
void I2C_Reset(void) { |
// stop i2c bus |
I2C_Stop(TWI_STATE_IDLE); |
TWCR = (1 << TWINT); // reset to original state incl. interrupt flag reset |
TWAMR = 0; |
TWAR = 0; |
TWDR = 0; |
TWSR = 0; |
TWBR = 0; |
I2C_init(); |
} |
|
/**************************************** |
* I2C ISR |
****************************************/ |
ISR (TWI_vect) |
{ |
switch (twi_state) { // First i2c_start from SendMotorData() |
case 0: break; |
|
// Writing ADC values. |
case 7: |
twi_state++; |
I2C_WriteByte(0x98); // Address the DAC |
break; |
|
case 8: |
twi_state++; |
I2C_WriteByte(0x10 + (DACChannel << 1)); // Select DAC Channel (0x10 = A, 0x12 = B, 0x14 = C) |
break; |
|
case 9: |
twi_state++; |
I2C_WriteByte(DACValues[DACChannel]); |
break; |
|
case 10: |
twi_state++; |
I2C_WriteByte(0x80); // 2nd byte for all channels is 0x80 |
break; |
|
case 11: |
twi_state++; |
I2C_Stop(TWI_STATE_IDLE); |
I2CTimeout = 10; |
// repeat case 7...10 until all DAC Channels are updated |
if (DACChannel < 2) { |
DACChannel++; // jump to next channel |
I2C_Start(TWI_STATE_GYRO_OFFSET_TX); // start transmission for next channel |
} else { |
DACChannel = 0; // reset dac channel counter |
} |
break; |
|
default: |
I2C_Stop(TWI_STATE_IDLE); |
I2CTimeout = 10; |
} |
} |