Subversion Repositories FlightCtrl

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

/*****************************************************************************************************************************
* File:                 twimaster.c
*
* Purpose:              setup of I2C (TWI)
*
* Functions:    extern void i2c_init (void);                                    // initialize I2C
*                               extern void i2c_start (void);                                   // Start I2C
*                               extern void i2c_reset(void);                                    // resert I2C
*                               extern void i2c_stop (void);                                    // Stop I2C
*                               extern void i2c_write_byte (char byte);                 // write 1 Byte
*
*****************************************************************************************************************************/

#include "twimaster.h"
#include "main.h"

volatile unsigned char twi_state = 0;
unsigned char motor=0;
unsigned char motorread=0, MissingMotor=0;
unsigned char motor_rx[16], motor_rx2[16];
unsigned char MotorPresent[MAX_MOTORS];                                                 // #define MAX_MOTORS      4
unsigned char MotorError[MAX_MOTORS];
unsigned int I2CError=0;


// *************************************************************************************************************************************
// Initzialize I2C (TWI)
//
void i2c_init(void)
{                                                                                                              
        //--------------------------------------------------------------------------------------------------------------------
        // TWSR = TWI Status Register containing: TWS7 TWS6 TWS5 TWS4 TWS3 – TWPS1 TWPS0
        //
        TWSR = 0;                                                                       // TWSR – TWI Status Register
       
        //--------------------------------------------------------------------------------------------------------------------
        // TWBR = TWI Bit Rate Register containing: TWBR7 TWBR6 TWBR5 TWBR4 TWBR3 TWBR2 TWBR1 TWBR0
        // set TWI Bit Rate Register                            // SYSCLK = 16000000 and SCL_CLOCK = 200000
        TWBR = ((SYSCLK/SCL_CLOCK)-16)/2;                       // selects the division factor for the bit rate generator
}
// *************************************************************************************************************************************



//-------------------------------------------------------------------------------------------------------------------------------------
// Start I2C
//
void i2c_start(void)
{
        // ---------------------------------------------------------------------------
        // TWCR = TWI Control Register -> TWINT TWEA TWSTA TWSTO TWWC TWEN – TWIE
        // TWINT = TWI interrupt flag - to be set to one, to reset the TWINT Flag
        // TWSTA = TWI start and should be set to one, that TWI is started as Master.
        // TWEN = TWI enable -> now TWI/I2C is working  properly.
        // TWIE = TWI Interrupt enable is the TWIE Bit -> should be set
        //
        TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE);
}
//-------------------------------------------------------------------------------------------------------------------------------------



//-------------------------------------------------------------------------------------------------------------------------------------
// Stop I2C
//
void i2c_stop(void)
{
        // ---------------------------------------------------------------------------
        // TWCR = TWI Control Register -> TWINT TWEA TWSTA TWSTO TWWC TWEN – TWIE
        // TWINT = TWI interrupt flag - to be set to one, to reset the TWINT Flag
        // TWSTO = TWI STOP Condition Bit (TWSTO = 1) -> now will be stoped
        // TWEN = TWI enable -> TWI/I2C is working  properly
        //
    TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
}
//-------------------------------------------------------------------------------------------------------------------------------------



//-------------------------------------------------------------------------------------------------------------------------------------
// I2C Reset
//
void i2c_reset(void)
{
        i2c_stop();                
        twi_state = 0;
        motor = TWDR;                                                                   // TWI Data Register (TWDR) siehe S 227
        motor = 0;                                                                              // ist das letzte gesendete oder empfangene Byte
        TWCR = 0x80;
        TWAMR = 0;
        TWAR = 0;
        TWDR = 0;
        TWSR = 0;
        TWBR = 0;
        i2c_init();
        i2c_start();
        i2c_write_byte(0);
}
//-------------------------------------------------------------------------------------------------------------------------------------



//---------------------------------------------------------------------------------------------------------------------------------------------
//  write via I2C
//
void i2c_write_byte(char byte)
{
    TWSR = 0x00;
    TWDR = byte;                                                                                                // sende dieses Byte via TWI Data Register
    TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
}
//---------------------------------------------------------------------------------------------------------------------------------------------



//---------------------------------------------------------------------------------------------------------------------------------------------
//  write byte via 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);
}
//---------------------------------------------------------------------------------------------------------------------------------------------



//---------------------------------------------------------------------------------------------------------------------------------------------
// ein Byte gelesen und sendet ACK
//
void I2C_ReceiveByte(void)
{
   TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE) | (1<<TWEA);
}
//---------------------------------------------------------------------------------------------------------------------------------------------



//---------------------------------------------------------------------------------------------------------------------------------------------
// I2C empfing das letzte Byte und sendet kein ACK
//
void I2C_ReceiveLastByte(void)
{
   TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
}
//---------------------------------------------------------------------------------------------------------------------------------------------



//-----------------------------------------------------------------------------------------------------------------------------------------------
// Interrupt I2C
//
ISR (TWI_vect)
{
        static unsigned char missing_motor;
       
    switch(twi_state++)
    {
                //----------------------------------------------------------------------------------------------------------------------------
                // write Motor-Data
                //----------------------------------------------------------------------------------------------------------------------------
        case 0:
                    while(Mixer.Motor[motor][0] <= 0 && motor < MAX_MOTORS) motor++;                    // #define MAX_MOTORS      2
                        if(motor == MAX_MOTORS)                                                                                                                 // writing finished -> now read
                        {
                                motor = 0;
                                twi_state = 3;
                                if(motorread==0) i2c_write_byte(0x53);                          // Read-Adress of: Motor 1 = 0x53 / 2 = 0x55 / 3 = 0x57 / 4 = 0x59
                                if(motorread==1) i2c_write_byte(0x57);
                        }
                        else
                        {
                                if(motor==0) i2c_write_byte(0x52);                                      // Write-Adress of: Motor 1 = 0x52 / 2 = 0x54 / 3 = 0x56 / 4 = 0x58
                                if(motor==1) i2c_write_byte(0x56);
            }
                        break;
                       
        case 1:
            i2c_write_byte(Motor[motor++]);
                        break;
                       
        case 2:
                        // TWSR – TWI Status Register -> TWS7 TWS6 TWS5 TWS4 TWS3 - TWPS1 TWPS0
            // Data byte has been transmitted; NOT ACK has been received
                        if(TWSR == 0x30)                                                                               
                        {
                                if(!missing_motor) missing_motor = motor;                                       //
                                if(++MotorError[motor-1] == 0) MotorError[motor-1] = 255;       //
                        }
                       
            i2c_stop();
            I2CTimeout = 10;                                                                                            // counted down every 2ms = watchdog
            twi_state = 0;
            i2c_start();  
            break;
                       
                //----------------------------------------------------------------------------------------------------------
                // read Motor-Data
                //----------------------------------------------------------------------------------------------------------
                case 3:
            if(TWSR != 0x40)                                                                            // Error?
            {                                                                                                           // send 1. Byte to be read             
                                MotorPresent[motorread] = 0;
                                motorread++;
                                if(motorread >= MAX_MOTORS) motorread = 0;                      // #define MAX_MOTORS      2
                                i2c_stop();
                                twi_state = 0;
            }
            else
            {
                                MotorPresent[motorread] = ('1' - '-') + motorread;
                                I2C_ReceiveByte();
            }
            //MissingMotor = missing_motor;
                        MissingMotor = 0;
            missing_motor = 0;
                        break;
                       
                case 4:                                                                                                         // read 1. Byte and send 2. Byte
            motor_rx[motorread] = TWDR;
            I2C_ReceiveLastByte();                                                                      // no acknowledge
            break;
                               
        case 5:
            motor_rx2[motorread++] = TWDR;                                                      // read 2. Byte
            if(motorread >= MAX_MOTORS) motorread = 0;                          // #define MAX_MOTORS      4
            i2c_stop();
            twi_state = 0;
            break;
                       
                //----------------------------------------------------------------------------------------------------------------------------------
                // write Gyro-Offset
                //----------------------------------------------------------------------------------------------------------------------------------
                case 8:
            i2c_write_byte(0x98);                                                                       // Address of DAC see DAC Manual page 17
                break;
                       
        case 9:
            i2c_write_byte(0x10);                                                                       // byte sent to chanel A
                break;
                       
        case 10:
            i2c_write_byte(AnalogOffsetNick);                                           // offset sent to DAC
                break;
                       
        case 11:
            i2c_write_byte(0x80);                                                                       // The 2nd Byte does not care = 0x80 (Dummy)
                break;
                       
        case 12:
            i2c_stop();              
            I2CTimeout = 10;
            i2c_start();  
                break;
               
        case 13:
                        i2c_write_byte(0x98);                                                                   // Address of DAC see DAC Manual page 17
        break;
               
        case 14:
            i2c_write_byte(0x12);                                                                       // byte sent to chanel B
        break;
               
        case 15:
            i2c_write_byte(AnalogOffsetRoll);                                           // offset sent to DAC
        break;
               
        case 16:
            i2c_write_byte(0x80);                                                                       // The 2nd Byte does not care = 0x80 (Dummy)
        break;
               
        case 17:
            i2c_stop();              
            I2CTimeout = 10;
            i2c_start();  
        break;
               
        case 18:
            i2c_write_byte(0x98);                                                                       // Address of DAC see DAC Manual page 17
        break;
               
        case 19:
            i2c_write_byte(0x14);                                                                       // byte sent to chanel C
        break;
               
        case 20:
            i2c_write_byte(AnalogOffsetGier);                                           // offset sent to DAC
        break;
               
        case 21:
            i2c_write_byte(0x80);                                                                       // The 2nd Byte does not care = 0x80 (Dummy)
        break;
               
        case 22:
            i2c_stop();              
            I2CTimeout = 10;
            twi_state = 0;
        break;
               
        default: twi_state = 0;
        break;        
        }
        TWCR |= 0x80;   // TWWC: TWI Write Collision Flag is set to 1
}
//-----------------------------------------------------------------------------------------------------------------------------------