diff options
Diffstat (limited to 'source/ct-Bot/mcu/TWI_driver.c')
-rw-r--r-- | source/ct-Bot/mcu/TWI_driver.c | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/source/ct-Bot/mcu/TWI_driver.c b/source/ct-Bot/mcu/TWI_driver.c new file mode 100644 index 0000000..db4c0fb --- /dev/null +++ b/source/ct-Bot/mcu/TWI_driver.c @@ -0,0 +1,194 @@ +/* + * c't-Sim - Robotersimulator fuer den c't-Bot + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General + * Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your + * option) any later version. + * This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307, USA. + * + */ + +/*! @file TWI_driver.c + * @brief TWI-Treiber (I2C) + * @author Chris efstathiou hendrix@otenet.gr & Carsten Giesen (info@cnau.de) + * @date 08.04.06 +*/ + +#ifdef MCU +#include <avr/io.h> +#include "TWI_driver.h" +#include "global.h" + + +/*! + * TWI Bus initialsieren + * @return Resultat der Aktion + */ + +int8 Init_TWI(void){ + TWAR = OWN_ADR; /*!< Eigenen Slave Adresse setzen */ + TWBR = 12; /*!< Setze Baudrate auf 100 KHz */ + /*!< 4 MHz xtal */ + TWCR = (1<<TWEN); /*!< TWI-Interface einschalten */ + + return 1; +} + +/*! + * TWI Buss schliesen + * @return Resultat der Aktion + */ + +int8 Close_TWI(void){ + TWCR = (0<<TWEN); /*!< TWI-Interface ausschalten */ + + return 0; +} + +/*! + * Warte auf TWI interrupt + */ + +void Wait_TWI_int(void){ + while (!(TWCR & (1<<TWINT))) + ; +} + +/*! + * Sende Start Sequence + * @return Resultat der Aktion + */ + +uint8 Send_start(void){ + TWCR = ((1<<TWINT)+(1<<TWSTA)+(1<<TWEN)); /*!< Sende START */ + + Wait_TWI_int(); /*!< Warte auf TWI interrupt */ + + if((TWSR != START)&&(TWSR != REP_START)) /*!< Ist der Status ein Anderer als Start (0x08) oder wiederholter Start (0x10) */ + return TWSR; /*!< -> error und Rueckgabe TWSR. */ + return SUCCESS; /*!< wenn OK Rueckgabe SUCCESS */ +} + +/*! + * Sende Stop Sequence + */ + +void Send_stop(void){ + TWCR = ((1<<TWEN)+(1<<TWINT)+(1<<TWSTO)); +} + +/*! + * Hier wird der eigentliche TWI-Treiber angesprochen + * @param *data_pack Container mit den Daten fuer den Treiber + * @return Resultat der Aktion + */ +uint8 Send_to_TWI(tx_type *data_pack){ + uint8 state,i,j; + + state = SUCCESS; + + for(i=0;(data_pack[i].slave_adr != OWN_ADR)&&(state == SUCCESS);i++) { + state = Send_start(); + if (state == SUCCESS) + state = Send_adr(data_pack[i].slave_adr); + + /*! + * Abhaengig von W/R senden oder empfangen + */ + if(!(data_pack[i].slave_adr & R)) { + if (state == SUCCESS){ + /*! + * Wenn W bis alle Daten gesendet sind + */ + for(j=0;((j<data_pack[i].size)&&(state == SUCCESS));j++) + state = Send_byte(data_pack[i].data_ptr[j]); + } + } + else{ + if (state == MRX_ADR_NACK) { + state = Send_start(); + } + + if (state == SUCCESS){ + /*! + * Wenn R bis alle Daten empfangen sind + */ + for(j=0;((j<data_pack[i].size)&&(state == SUCCESS));j++){ + /*! + * Wenn wir keine Daten mehr erwarten NACK senden + */ + if(j == data_pack[i].size-1) + state = Get_byte(data_pack[i].data_ptr++,0); + else + state = Get_byte(data_pack[i].data_ptr++,1); + } + } + } + Send_stop(); + } + Close_TWI(); + + return state; +} + +/*! + * Sende ein Byte + * @param data das zu uebertragende Byte + */ + +uint8 Send_byte(uint8 data){ + Wait_TWI_int(); + TWDR = data; + TWCR = ((1<<TWINT)+(1<<TWEN)); + Wait_TWI_int(); + if(TWSR != MTX_DATA_ACK) + return TWSR; + return SUCCESS; +} + +/*! + * Sende Slave Adresse + * @param adr die gewuenschte Adresse + * @return Resultat der Aktion + */ + +uint8 Send_adr(uint8 adr){ + Wait_TWI_int(); + TWDR = adr; + TWCR = ((1<<TWINT)+(1<<TWEN)); + Wait_TWI_int(); + if((TWSR != MTX_ADR_ACK)&&(TWSR != MRX_ADR_ACK)) + return TWSR; + return SUCCESS; +} + +/*! + * Empfange ein Byte + * @param *rx_ptr Container fuer die Daten + * @param last_byte Flag ob noch Daten erwartet werden + * @return Resultat der Aktion + */ + +uint8 Get_byte(uint8 *rx_ptr,uint8 last_byte){ + Wait_TWI_int(); + if(last_byte) + TWCR = ((1<<TWINT)+(1<<TWEA)+(1<<TWEN)); + else + TWCR = ((1<<TWINT)+(1<<TWEN)); + Wait_TWI_int(); + *rx_ptr = TWDR; + if(((TWSR == MRX_DATA_NACK)&&(last_byte == 0))||(TWSR == MRX_DATA_ACK)) + return SUCCESS; + return TWSR; +} + +#endif |