summaryrefslogtreecommitdiffstats
path: root/source/ct-Bot/mcu/TWI_driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/ct-Bot/mcu/TWI_driver.c')
-rw-r--r--source/ct-Bot/mcu/TWI_driver.c194
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