+#
+# Copyright 2008-2011 Michel Pollet <buserror@gmail.com>
+#
+# This file is part of simavr.
+#
+# simavr 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 3 of the License, or
+# (at your option) any later version.
+#
+# simavr 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 simavr. If not, see <http://www.gnu.org/licenses/>.
+
+target= i2ctest
+firm_src = ${wildcard at*${board}.c}
+firmware = ${firm_src:.c=.axf}
+simavr = ../../
+
+SHELL = /bin/bash
+
+IPATH = .
+IPATH += ../parts
+IPATH += ${simavr}/include
+IPATH += ${simavr}/simavr/sim
+
+VPATH = .
+VPATH += ../parts
+
+
+all: obj atmega48_${target}.axf ${target}
+
+include ${simavr}/Makefile.common
+
+atmega48_${target}.axf: atmega48_${target}.c
+
+board = ${OBJ}/${target}.elf
+
+${board} : ${OBJ}/${target}.o
+${board} : ${simavr}/simavr/${OBJ}/libsimavr.a
+
+${target}: ${board}
+ @echo $@ done
+
+clean: clean-${OBJ}
+ rm -rf *.hex *.a *.axf ${target} *.vcd .*.swo .*.swp .*.swm .*.swn
--- /dev/null
+/*
+ atmega48_i2ctest.c
+
+ Copyright 2008-2011 Michel Pollet <buserror@gmail.com>
+
+ This file is part of simavr.
+
+ simavr 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 3 of the License, or
+ (at your option) any later version.
+
+ simavr 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 simavr. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/sleep.h>
+
+// for linker, emulator, and programmer's sake
+#include "avr_mcu_section.h"
+AVR_MCU(F_CPU, "atmega48");
+
+#include "avr_twi_master.c"
+
+#include <stdio.h>
+
+static int uart_putchar(char c, FILE *stream) {
+ if (c == '\n')
+ uart_putchar('\r', stream);
+ loop_until_bit_is_set(UCSR0A, UDRE0);
+ UDR0 = c;
+ return 0;
+}
+
+static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
+ _FDEV_SETUP_WRITE);
+
+int main()
+{
+ stdout = &mystdout;
+
+ sei();
+ TWI_Master_Initialise();
+
+ { // write 2 bytes at some random address
+ uint8_t msg[8] = {
+ 0xa0, // TWI address,
+ 0xaa, 0x01, // eeprom address, in little endian
+ 0xde, 0xad, // data bytes
+ };
+ TWI_Start_Transceiver_With_Data(msg, 5, 1);
+
+ while (TWI_Transceiver_Busy())
+ sleep_mode();
+ }
+ {
+ uint8_t msg[8] = {
+ 0xa0, // TWI address,
+ 0xa8, 0x01, // eeprom address, in little endian
+ };
+ TWI_Start_Transceiver_With_Data(msg, 3, 0); // dont send stop!
+
+ while (TWI_Transceiver_Busy())
+ sleep_mode();
+ }
+ {
+ uint8_t msg[9] = {
+ 0xa0 + 1, // TWI address,
+ };
+ TWI_Start_Transceiver_With_Data(msg, 9, 1); // write 1 byte, read 8, send stop
+
+ while (TWI_Transceiver_Busy())
+ sleep_mode();
+ }
+ cli();
+ sleep_mode();
+}
+
--- /dev/null
+/*****************************************************************************\r
+*\r
+* Atmel Corporation\r
+*\r
+* File : TWI_Master.c\r
+* Compiler : IAR EWAAVR 2.28a/3.10c\r
+* Revision : $Revision: 1.13 $\r
+* Date : $Date: 24. mai 2004 11:31:20 $\r
+* Updated by : $Author: ltwa $\r
+*\r
+* Support mail : avr@atmel.com\r
+*\r
+* Supported devices : All devices with a TWI module can be used.\r
+* The example is written for the ATmega16\r
+*\r
+* AppNote : AVR315 - TWI Master Implementation\r
+*\r
+* Description : This is a sample driver for the TWI hardware modules.\r
+* It is interrupt driveren. All functionality is controlled through \r
+* passing information to and from functions. Se main.c for samples\r
+* of how to use the driver.\r
+*\r
+*\r
+****************************************************************************/\r
+\r
+#include "avr_twi_master.h"\r
+\r
+//static unsigned char TWI_buf[ TWI_BUFFER_SIZE ]; // Transceiver buffer\r
+static unsigned char *TWI_buf;\r
+static unsigned char TWI_msgSize; // Number of bytes to be transmitted.\r
+static unsigned char TWI_sendStop;\r
+static unsigned char TWI_state = TWI_NO_STATE; // State byte. Default set to TWI_NO_STATE.\r
+\r
+union TWI_statusReg TWI_statusReg = {0}; // TWI_statusReg is defined in TWI_Master.h\r
+\r
+/****************************************************************************\r
+Call this function to set up the TWI master to its initial standby state.\r
+Remember to enable interrupts from the main application after initializing the TWI.\r
+****************************************************************************/\r
+void TWI_Master_Initialise(void)\r
+{\r
+ TWBR = TWI_TWBR; // Set bit rate register (Baudrate). Defined in header file.\r
+// TWSR = TWI_TWPS; // Not used. Driver presumes prescaler to be 00.\r
+ TWDR = 0xFF; // Default content = SDA released.\r
+ TWCR = (1<<TWEN)| // Enable TWI-interface and release TWI pins.\r
+ (0<<TWIE)|(0<<TWINT)| // Disable Interupt.\r
+ (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // No Signal requests.\r
+ (0<<TWWC); //\r
+} \r
+ \r
+/****************************************************************************\r
+Call this function to test if the TWI_ISR is busy transmitting.\r
+****************************************************************************/\r
+unsigned char TWI_Transceiver_Busy( void )\r
+{\r
+ return ( TWCR & (1<<TWIE) ); // IF TWI Interrupt is enabled then the Transceiver is busy\r
+}\r
+\r
+/****************************************************************************\r
+Call this function to fetch the state information of the previous operation. The function will hold execution (loop)\r
+until the TWI_ISR has completed with the previous operation. If there was an error, then the function \r
+will return the TWI State code. \r
+****************************************************************************/\r
+unsigned char TWI_Get_State_Info( void )\r
+{\r
+ while ( TWI_Transceiver_Busy() ); // Wait until TWI has completed the transmission.\r
+ return ( TWI_state ); // Return error state.\r
+}\r
+\r
+/****************************************************************************\r
+Call this function to send a prepared message. The first byte must contain the slave address and the\r
+read/write bit. Consecutive bytes contain the data to be sent, or empty locations for data to be read\r
+from the slave. Also include how many bytes that should be sent/read including the address byte.\r
+The function will hold execution (loop) until the TWI_ISR has completed with the previous operation,\r
+then initialize the next operation and return.\r
+****************************************************************************/\r
+void TWI_Start_Transceiver_With_Data(\r
+ unsigned char *msg, unsigned char msgSize, unsigned char sendStop )\r
+{\r
+// unsigned char temp;\r
+\r
+ while ( TWI_Transceiver_Busy() ); // Wait until TWI is ready for next transmission.\r
+\r
+ TWI_msgSize = msgSize; // Number of data to transmit.\r
+ TWI_sendStop = sendStop;\r
+ TWI_buf = msg; // store our current message\r
+ TWI_statusReg.all = 0; \r
+ TWI_state = TWI_NO_STATE ;\r
+ TWCR = (1<<TWEN)| // TWI Interface enabled.\r
+ (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag.\r
+ (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)| // Initiate a START condition.\r
+ (0<<TWWC); //\r
+}\r
+\r
+/****************************************************************************\r
+Call this function to resend the last message. The driver will reuse the data previously put in the transceiver buffers.\r
+The function will hold execution (loop) until the TWI_ISR has completed with the previous operation,\r
+then initialize the next operation and return.\r
+****************************************************************************/\r
+void TWI_Start_Transceiver( void )\r
+{\r
+ while ( TWI_Transceiver_Busy() ); // Wait until TWI is ready for next transmission.\r
+ TWI_statusReg.all = 0; \r
+ TWI_state = TWI_NO_STATE ;\r
+ TWCR = (1<<TWEN)| // TWI Interface enabled.\r
+ (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag.\r
+ (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)| // Initiate a START condition.\r
+ (0<<TWWC); //\r
+}\r
+\r
+/****************************************************************************\r
+Call this function to read out the requested data from the TWI transceiver buffer. I.e. first call\r
+TWI_Start_Transceiver to send a request for data to the slave. Then Run this function to collect the\r
+data when they have arrived. Include a pointer to where to place the data and the number of bytes\r
+requested (including the address field) in the function call. The function will hold execution (loop)\r
+until the TWI_ISR has completed with the previous operation, before reading out the data and returning.\r
+If there was an error in the previous transmission the function will return the TWI error code.\r
+****************************************************************************/\r
+unsigned char TWI_Get_Data_From_Transceiver( unsigned char *msg, unsigned char msgSize )\r
+{\r
+ unsigned char i;\r
+\r
+ while ( TWI_Transceiver_Busy() ); // Wait until TWI is ready for next transmission.\r
+\r
+ if( TWI_statusReg.lastTransOK ) // Last transmission competed successfully. \r
+ { \r
+ for ( i=0; i<msgSize; i++ ) // Copy data from Transceiver buffer.\r
+ {\r
+ msg[ i ] = TWI_buf[ i ];\r
+ }\r
+ }\r
+ return( TWI_statusReg.lastTransOK ); \r
+}\r
+\r
+// ********** Interrupt Handlers ********** //\r
+/****************************************************************************\r
+This function is the Interrupt Service Routine (ISR), and called when the TWI interrupt is triggered;\r
+that is whenever a TWI event has occurred. This function should not be called directly from the main\r
+application.\r
+****************************************************************************/\r
+ISR( TWI_vect )\r
+{\r
+ static unsigned char TWI_bufPtr;\r
+ \r
+ switch (TWSR)\r
+ {\r
+ case TWI_START: // START has been transmitted \r
+ case TWI_REP_START: // Repeated START has been transmitted\r
+ TWI_bufPtr = 0; // Set buffer pointer to the TWI Address location\r
+ case TWI_MTX_ADR_ACK: // SLA+W has been tramsmitted and ACK received\r
+ case TWI_MTX_DATA_ACK: // Data byte has been tramsmitted and ACK received\r
+ if (TWI_bufPtr < TWI_msgSize)\r
+ {\r
+ TWDR = TWI_buf[TWI_bufPtr++];\r
+ TWCR = (1<<TWEN)| // TWI Interface enabled\r
+ (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to send byte\r
+ (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| //\r
+ (0<<TWWC); // \r
+ }else // Send STOP after last byte\r
+ {\r
+ TWI_statusReg.lastTransOK = TRUE; // Set status bits to completed successfully.\r
+ if (TWI_sendStop)\r
+ TWCR = (1<<TWEN)| // TWI Interface enabled\r
+ (0<<TWIE)|(1<<TWINT)| // Disable TWI Interrupt and clear the flag\r
+ (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)| // Initiate a STOP condition?\r
+ (0<<TWWC); //\r
+ }\r
+ break;\r
+ case TWI_MRX_DATA_ACK: // Data byte has been received and ACK tramsmitted\r
+ TWI_buf[TWI_bufPtr++] = TWDR;\r
+ case TWI_MRX_ADR_ACK: // SLA+R has been tramsmitted and ACK received\r
+ if (TWI_bufPtr < (TWI_msgSize-1) ) // Detect the last byte to NACK it.\r
+ {\r
+ TWCR = (1<<TWEN)| // TWI Interface enabled\r
+ (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to read next byte\r
+ (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Send ACK after reception\r
+ (0<<TWWC); // \r
+ }else // Send NACK after next reception\r
+ {\r
+ TWCR = (1<<TWEN)| // TWI Interface enabled\r
+ (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to read next byte\r
+ (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Send NACK after reception\r
+ (0<<TWWC); // \r
+ } \r
+ break; \r
+ case TWI_MRX_DATA_NACK: // Data byte has been received and NACK tramsmitted\r
+ TWI_buf[TWI_bufPtr] = TWDR;\r
+ TWI_statusReg.lastTransOK = TRUE; // Set status bits to completed successfully. \r
+ TWCR = (1<<TWEN)| // TWI Interface enabled\r
+ (0<<TWIE)|(1<<TWINT)| // Disable TWI Interrupt and clear the flag\r
+ (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)| // Initiate a STOP condition.\r
+ (0<<TWWC); //\r
+ break; \r
+ case TWI_ARB_LOST: // Arbitration lost\r
+ TWCR = (1<<TWEN)| // TWI Interface enabled\r
+ (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag\r
+ (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)| // Initiate a (RE)START condition.\r
+ (0<<TWWC); //\r
+ break;\r
+ case TWI_MTX_ADR_NACK: // SLA+W has been tramsmitted and NACK received\r
+ case TWI_MRX_ADR_NACK: // SLA+R has been tramsmitted and NACK received \r
+ case TWI_MTX_DATA_NACK: // Data byte has been tramsmitted and NACK received\r
+// case TWI_NO_STATE // No relevant state information available; TWINT = �0�\r
+ case TWI_BUS_ERROR: // Bus error due to an illegal START or STOP condition\r
+ default: \r
+ TWI_state = TWSR; // Store TWSR and automatically sets clears noErrors bit.\r
+ // Reset TWI Interface\r
+ TWCR = (1<<TWEN)| // Enable TWI-interface and release TWI pins\r
+ (0<<TWIE)|(0<<TWINT)| // Disable Interupt\r
+ (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // No Signal requests\r
+ (0<<TWWC); //\r
+ }\r
+}\r
--- /dev/null
+/*****************************************************************************\r
+*\r
+* Atmel Corporation\r
+*\r
+* File : TWI_Master.h\r
+* Compiler : IAR EWAAVR 2.28a/3.10c\r
+* Revision : $Revision: 1.13 $\r
+* Date : $Date: 24. mai 2004 11:31:22 $\r
+* Updated by : $Author: ltwa $\r
+*\r
+* Support mail : avr@atmel.com\r
+*\r
+* Supported devices : All devices with a TWI module can be used.\r
+* The example is written for the ATmega16\r
+*\r
+* AppNote : AVR315 - TWI Master Implementation\r
+*\r
+* Description : Header file for TWI_Master.c\r
+* Include this file in the application.\r
+*\r
+****************************************************************************/\r
+\r
+/****************************************************************************\r
+ TWI Status/Control register definitions\r
+****************************************************************************/\r
+//#define TWI_BUFFER_SIZE 4 // Set this to the largest message size that will be sent including address byte.\r
+\r
+#define TWI_TWBR 0x0C // TWI Bit rate Register setting.\r
+ // Se Application note for detailed \r
+ // information on setting this value.\r
+// Not used defines!\r
+//#define TWI_TWPS 0x00 // This driver presumes prescaler = 00\r
+\r
+/****************************************************************************\r
+ Global definitions\r
+****************************************************************************/\r
+\r
+union TWI_statusReg // Status byte holding flags.\r
+{\r
+ unsigned char all;\r
+ struct\r
+ {\r
+ unsigned char lastTransOK:1; \r
+ unsigned char unusedBits:7;\r
+ };\r
+};\r
+\r
+extern union TWI_statusReg TWI_statusReg;\r
+\r
+/****************************************************************************\r
+ Function definitions\r
+****************************************************************************/\r
+void TWI_Master_Initialise( void );\r
+unsigned char TWI_Transceiver_Busy( void );\r
+unsigned char TWI_Get_State_Info( void );\r
+void TWI_Start_Transceiver_With_Data(\r
+ unsigned char *msg, unsigned char msgSize, unsigned char sendStop );\r
+void TWI_Start_Transceiver( void );\r
+unsigned char TWI_Get_Data_From_Transceiver( unsigned char *, unsigned char );\r
+\r
+/****************************************************************************\r
+ Bit and byte definitions\r
+****************************************************************************/\r
+#define TWI_READ_BIT 0 // Bit position for R/W bit in "address byte".\r
+#define TWI_ADR_BITS 1 // Bit position for LSB of the slave address bits in the init byte.\r
+\r
+#define TRUE 1\r
+#define FALSE 0\r
+\r
+/****************************************************************************\r
+ TWI State codes\r
+****************************************************************************/\r
+// General TWI Master staus codes \r
+#define TWI_START 0x08 // START has been transmitted \r
+#define TWI_REP_START 0x10 // Repeated START has been transmitted\r
+#define TWI_ARB_LOST 0x38 // Arbitration lost\r
+\r
+// TWI Master Transmitter staus codes \r
+#define TWI_MTX_ADR_ACK 0x18 // SLA+W has been tramsmitted and ACK received\r
+#define TWI_MTX_ADR_NACK 0x20 // SLA+W has been tramsmitted and NACK received \r
+#define TWI_MTX_DATA_ACK 0x28 // Data byte has been tramsmitted and ACK received\r
+#define TWI_MTX_DATA_NACK 0x30 // Data byte has been tramsmitted and NACK received \r
+\r
+// TWI Master Receiver staus codes \r
+#define TWI_MRX_ADR_ACK 0x40 // SLA+R has been tramsmitted and ACK received\r
+#define TWI_MRX_ADR_NACK 0x48 // SLA+R has been tramsmitted and NACK received\r
+#define TWI_MRX_DATA_ACK 0x50 // Data byte has been received and ACK tramsmitted\r
+#define TWI_MRX_DATA_NACK 0x58 // Data byte has been received and NACK tramsmitted\r
+\r
+// TWI Slave Transmitter staus codes\r
+#define TWI_STX_ADR_ACK 0xA8 // Own SLA+R has been received; ACK has been returned\r
+#define TWI_STX_ADR_ACK_M_ARB_LOST 0xB0 // Arbitration lost in SLA+R/W as Master; own SLA+R has been received; ACK has been returned\r
+#define TWI_STX_DATA_ACK 0xB8 // Data byte in TWDR has been transmitted; ACK has been received\r
+#define TWI_STX_DATA_NACK 0xC0 // Data byte in TWDR has been transmitted; NOT ACK has been received\r
+#define TWI_STX_DATA_ACK_LAST_BYTE 0xC8 // Last data byte in TWDR has been transmitted (TWEA = �0�); ACK has been received\r
+\r
+// TWI Slave Receiver staus codes\r
+#define TWI_SRX_ADR_ACK 0x60 // Own SLA+W has been received ACK has been returned\r
+#define TWI_SRX_ADR_ACK_M_ARB_LOST 0x68 // Arbitration lost in SLA+R/W as Master; own SLA+W has been received; ACK has been returned\r
+#define TWI_SRX_GEN_ACK 0x70 // General call address has been received; ACK has been returned\r
+#define TWI_SRX_GEN_ACK_M_ARB_LOST 0x78 // Arbitration lost in SLA+R/W as Master; General call address has been received; ACK has been returned\r
+#define TWI_SRX_ADR_DATA_ACK 0x80 // Previously addressed with own SLA+W; data has been received; ACK has been returned\r
+#define TWI_SRX_ADR_DATA_NACK 0x88 // Previously addressed with own SLA+W; data has been received; NOT ACK has been returned\r
+#define TWI_SRX_GEN_DATA_ACK 0x90 // Previously addressed with general call; data has been received; ACK has been returned\r
+#define TWI_SRX_GEN_DATA_NACK 0x98 // Previously addressed with general call; data has been received; NOT ACK has been returned\r
+#define TWI_SRX_STOP_RESTART 0xA0 // A STOP condition or repeated START condition has been received while still addressed as Slave\r
+\r
+// TWI Miscellaneous status codes\r
+#define TWI_NO_STATE 0xF8 // No relevant state information available; TWINT = �0�\r
+#define TWI_BUS_ERROR 0x00 // Bus error due to an illegal START or STOP condition\r
+\r
--- /dev/null
+/*
+ i2ctest.c
+
+ Copyright 2008-2011 Michel Pollet <buserror@gmail.com>
+
+ This file is part of simavr.
+
+ simavr 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 3 of the License, or
+ (at your option) any later version.
+
+ simavr 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 simavr. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <libgen.h>
+#include <pthread.h>
+
+#include "sim_avr.h"
+#include "avr_twi.h"
+#include "sim_elf.h"
+#include "sim_gdb.h"
+#include "sim_vcd_file.h"
+
+
+typedef struct i2c_eeprom_t {
+ avr_irq_t * irq; // irq list
+ uint8_t addr_base;
+ uint8_t addr_mask;
+
+ uint8_t selected; // selected address
+ int index; // byte index
+
+ uint16_t reg_addr; // read/write address register
+ int size; // also implies the address size, one or two byte
+ uint8_t ee[4096];
+} i2c_eeprom_t;
+
+#include <string.h>
+
+/*
+ * called when a RESET signal is sent
+ */
+static void
+i2c_eeprom_in_hook(
+ struct avr_irq_t * irq,
+ uint32_t value,
+ void * param)
+{
+ i2c_eeprom_t * p = (i2c_eeprom_t*)param;
+ avr_twi_msg_irq_t v;
+ v.u.v = value;
+
+ if (v.u.twi.msg & TWI_COND_STOP) {
+ if (p->selected) {
+ // it was us !
+ printf("eeprom received stop\n");
+ }
+ p->selected = 0;
+ p->index = 0;
+ p->reg_addr = 0;
+ }
+ if (v.u.twi.msg & TWI_COND_START) {
+ p->selected = 0;
+ p->index = 0;
+ if ((p->addr_base & p->addr_mask) == (v.u.twi.addr & p->addr_mask)) {
+ // it's us !
+ p->selected = v.u.twi.addr;
+ avr_raise_irq(p->irq + TWI_IRQ_MISO,
+ avr_twi_irq_msg(TWI_COND_ACK, p->selected, 1));
+ }
+ }
+ if (p->selected) {
+ if (v.u.twi.msg & TWI_COND_WRITE) {
+ printf("eeprom write %02x\n", v.u.twi.data);
+ // address size is how many bytes we use for address register
+ avr_raise_irq(p->irq + TWI_IRQ_MISO,
+ avr_twi_irq_msg(TWI_COND_ACK, p->selected, 1));
+ int addr_size = p->size > 256 ? 2 : 1;
+ if (p->index < addr_size) {
+ p->reg_addr |= (v.u.twi.data << (p->index * 8));
+ printf("eeprom set address to %04x\n", p->reg_addr);
+ } else {
+ printf("eeprom WRITE data %04x: %02x\n", p->reg_addr, v.u.twi.data);
+ p->ee[p->reg_addr++] = v.u.twi.data;
+ }
+ p->reg_addr &= (p->size -1);
+ p->index++;
+ }
+ if (v.u.twi.msg & TWI_COND_READ) {
+ printf("eeprom READ data %04x: %02x\n", p->reg_addr, p->ee[p->reg_addr]);
+ uint8_t data = p->ee[p->reg_addr++];
+ avr_raise_irq(p->irq + TWI_IRQ_MISO,
+ avr_twi_irq_msg(TWI_COND_READ, p->selected, data));
+ p->reg_addr &= (p->size -1);
+ p->index++;
+ }
+ }
+}
+
+static const char * _ee_irq_names[2] = {
+ [TWI_IRQ_MISO] = "8>eeprom.out",
+ [TWI_IRQ_MOSI] = "32<eeprom.in",
+};
+
+void
+i2c_eeprom_init(
+ struct avr_t * avr,
+ i2c_eeprom_t * p,
+ uint8_t addr,
+ uint8_t mask,
+ uint8_t * data,
+ size_t size)
+{
+ memset(p, 0, sizeof(p));
+ memset(p->ee, 0xff, sizeof(p->ee));
+ p->irq = avr_alloc_irq(&avr->irq_pool, 0, 2, _ee_irq_names);
+ avr_irq_register_notify(p->irq + TWI_IRQ_MOSI, i2c_eeprom_in_hook, p);
+
+ p->size = size > sizeof(p->ee) ? sizeof(p->ee) : size;
+ if (data)
+ memcpy(p->ee, data, p->size);
+}
+
+avr_t * avr = NULL;
+avr_vcd_t vcd_file;
+
+i2c_eeprom_t ee;
+
+int main(int argc, char *argv[])
+{
+ elf_firmware_t f;
+ const char * fname = "atmega48_i2ctest.axf";
+ char path[256];
+
+ sprintf(path, "%s/%s", dirname(argv[0]), fname);
+ printf("Firmware pathname is %s\n", fname);
+ elf_read_firmware(fname, &f);
+
+ printf("firmware %s f=%d mmcu=%s\n", fname, (int)f.frequency, f.mmcu);
+
+ avr = avr_make_mcu_by_name(f.mmcu);
+ if (!avr) {
+ fprintf(stderr, "%s: AVR '%s' now known\n", argv[0], f.mmcu);
+ exit(1);
+ }
+ avr_init(avr);
+ avr_load_firmware(avr, &f);
+
+ // initialize our 'peripheral'
+ i2c_eeprom_init(avr, &ee, 0xa0, 0xfe, NULL, 1024);
+
+ // "connect" the IRQs of the button to the port pin of the AVR
+ avr_connect_irq(
+ ee.irq + TWI_IRQ_MISO,
+ avr_io_getirq(avr, AVR_IOCTL_TWI_GETIRQ(0), TWI_IRQ_MISO));
+ avr_connect_irq(
+ avr_io_getirq(avr, AVR_IOCTL_TWI_GETIRQ(0), TWI_IRQ_MOSI),
+ ee.irq + TWI_IRQ_MOSI );
+
+ // even if not setup at startup, activate gdb if crashing
+ avr->gdb_port = 1234;
+ if (0) {
+ //avr->state = cpu_Stopped;
+ avr_gdb_init(avr);
+ }
+
+ /*
+ * VCD file initialization
+ *
+ * This will allow you to create a "wave" file and display it in gtkwave
+ * Pressing "r" and "s" during the demo will start and stop recording
+ * the pin changes
+ */
+ avr_vcd_init(avr, "gtkwave_output.vcd", &vcd_file, 100000 /* usec */);
+ avr_vcd_add_signal(&vcd_file,
+ avr_io_getirq(avr, AVR_IOCTL_TWI_GETIRQ(0), TWI_IRQ_STATUS), 8 /* bits */ ,
+ "TWSR" );
+
+ printf( "Demo launching:\n"
+ );
+
+ while (1)
+ avr_run(avr);
+}
+++ /dev/null
-/*****************************************************************************\r
-*\r
-* Atmel Corporation\r
-*\r
-* File : TWI_Master.c\r
-* Compiler : IAR EWAAVR 2.28a/3.10c\r
-* Revision : $Revision: 1.13 $\r
-* Date : $Date: 24. mai 2004 11:31:20 $\r
-* Updated by : $Author: ltwa $\r
-*\r
-* Support mail : avr@atmel.com\r
-*\r
-* Supported devices : All devices with a TWI module can be used.\r
-* The example is written for the ATmega16\r
-*\r
-* AppNote : AVR315 - TWI Master Implementation\r
-*\r
-* Description : This is a sample driver for the TWI hardware modules.\r
-* It is interrupt driveren. All functionality is controlled through \r
-* passing information to and from functions. Se main.c for samples\r
-* of how to use the driver.\r
-*\r
-*\r
-****************************************************************************/\r
-\r
-#include "ioavr.h" \r
-#include "inavr.h"\r
-#include "TWI_Master.h"\r
-\r
-static unsigned char TWI_buf[ TWI_BUFFER_SIZE ]; // Transceiver buffer\r
-static unsigned char TWI_msgSize; // Number of bytes to be transmitted.\r
-static unsigned char TWI_state = TWI_NO_STATE; // State byte. Default set to TWI_NO_STATE.\r
-\r
-union TWI_statusReg TWI_statusReg = {0}; // TWI_statusReg is defined in TWI_Master.h\r
-\r
-/****************************************************************************\r
-Call this function to set up the TWI master to its initial standby state.\r
-Remember to enable interrupts from the main application after initializing the TWI.\r
-****************************************************************************/\r
-void TWI_Master_Initialise(void)\r
-{\r
- TWBR = TWI_TWBR; // Set bit rate register (Baudrate). Defined in header file.\r
-// TWSR = TWI_TWPS; // Not used. Driver presumes prescaler to be 00.\r
- TWDR = 0xFF; // Default content = SDA released.\r
- TWCR = (1<<TWEN)| // Enable TWI-interface and release TWI pins.\r
- (0<<TWIE)|(0<<TWINT)| // Disable Interupt.\r
- (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // No Signal requests.\r
- (0<<TWWC); //\r
-} \r
- \r
-/****************************************************************************\r
-Call this function to test if the TWI_ISR is busy transmitting.\r
-****************************************************************************/\r
-unsigned char TWI_Transceiver_Busy( void )\r
-{\r
- return ( TWCR & (1<<TWIE) ); // IF TWI Interrupt is enabled then the Transceiver is busy\r
-}\r
-\r
-/****************************************************************************\r
-Call this function to fetch the state information of the previous operation. The function will hold execution (loop)\r
-until the TWI_ISR has completed with the previous operation. If there was an error, then the function \r
-will return the TWI State code. \r
-****************************************************************************/\r
-unsigned char TWI_Get_State_Info( void )\r
-{\r
- while ( TWI_Transceiver_Busy() ); // Wait until TWI has completed the transmission.\r
- return ( TWI_state ); // Return error state.\r
-}\r
-\r
-/****************************************************************************\r
-Call this function to send a prepared message. The first byte must contain the slave address and the\r
-read/write bit. Consecutive bytes contain the data to be sent, or empty locations for data to be read\r
-from the slave. Also include how many bytes that should be sent/read including the address byte.\r
-The function will hold execution (loop) until the TWI_ISR has completed with the previous operation,\r
-then initialize the next operation and return.\r
-****************************************************************************/\r
-void TWI_Start_Transceiver_With_Data( unsigned char *msg, unsigned char msgSize )\r
-{\r
- unsigned char temp;\r
-\r
- while ( TWI_Transceiver_Busy() ); // Wait until TWI is ready for next transmission.\r
-\r
- TWI_msgSize = msgSize; // Number of data to transmit.\r
- TWI_buf[0] = msg[0]; // Store slave address with R/W setting.\r
- if (!( msg[0] & (TRUE<<TWI_READ_BIT) )) // If it is a write operation, then also copy data.\r
- {\r
- for ( temp = 1; temp < msgSize; temp++ )\r
- TWI_buf[ temp ] = msg[ temp ];\r
- }\r
- TWI_statusReg.all = 0; \r
- TWI_state = TWI_NO_STATE ;\r
- TWCR = (1<<TWEN)| // TWI Interface enabled.\r
- (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag.\r
- (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)| // Initiate a START condition.\r
- (0<<TWWC); //\r
-}\r
-\r
-/****************************************************************************\r
-Call this function to resend the last message. The driver will reuse the data previously put in the transceiver buffers.\r
-The function will hold execution (loop) until the TWI_ISR has completed with the previous operation,\r
-then initialize the next operation and return.\r
-****************************************************************************/\r
-void TWI_Start_Transceiver( void )\r
-{\r
- while ( TWI_Transceiver_Busy() ); // Wait until TWI is ready for next transmission.\r
- TWI_statusReg.all = 0; \r
- TWI_state = TWI_NO_STATE ;\r
- TWCR = (1<<TWEN)| // TWI Interface enabled.\r
- (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag.\r
- (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)| // Initiate a START condition.\r
- (0<<TWWC); //\r
-}\r
-\r
-/****************************************************************************\r
-Call this function to read out the requested data from the TWI transceiver buffer. I.e. first call\r
-TWI_Start_Transceiver to send a request for data to the slave. Then Run this function to collect the\r
-data when they have arrived. Include a pointer to where to place the data and the number of bytes\r
-requested (including the address field) in the function call. The function will hold execution (loop)\r
-until the TWI_ISR has completed with the previous operation, before reading out the data and returning.\r
-If there was an error in the previous transmission the function will return the TWI error code.\r
-****************************************************************************/\r
-unsigned char TWI_Get_Data_From_Transceiver( unsigned char *msg, unsigned char msgSize )\r
-{\r
- unsigned char i;\r
-\r
- while ( TWI_Transceiver_Busy() ); // Wait until TWI is ready for next transmission.\r
-\r
- if( TWI_statusReg.lastTransOK ) // Last transmission competed successfully. \r
- { \r
- for ( i=0; i<msgSize; i++ ) // Copy data from Transceiver buffer.\r
- {\r
- msg[ i ] = TWI_buf[ i ];\r
- }\r
- }\r
- return( TWI_statusReg.lastTransOK ); \r
-}\r
-\r
-// ********** Interrupt Handlers ********** //\r
-/****************************************************************************\r
-This function is the Interrupt Service Routine (ISR), and called when the TWI interrupt is triggered;\r
-that is whenever a TWI event has occurred. This function should not be called directly from the main\r
-application.\r
-****************************************************************************/\r
-#pragma vector=TWI_vect\r
-__interrupt void TWI_ISR(void)\r
-{\r
- static unsigned char TWI_bufPtr;\r
- \r
- switch (TWSR)\r
- {\r
- case TWI_START: // START has been transmitted \r
- case TWI_REP_START: // Repeated START has been transmitted\r
- TWI_bufPtr = 0; // Set buffer pointer to the TWI Address location\r
- case TWI_MTX_ADR_ACK: // SLA+W has been tramsmitted and ACK received\r
- case TWI_MTX_DATA_ACK: // Data byte has been tramsmitted and ACK received\r
- if (TWI_bufPtr < TWI_msgSize)\r
- {\r
- TWDR = TWI_buf[TWI_bufPtr++];\r
- TWCR = (1<<TWEN)| // TWI Interface enabled\r
- (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to send byte\r
- (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| //\r
- (0<<TWWC); // \r
- }else // Send STOP after last byte\r
- {\r
- TWI_statusReg.lastTransOK = TRUE; // Set status bits to completed successfully. \r
- TWCR = (1<<TWEN)| // TWI Interface enabled\r
- (0<<TWIE)|(1<<TWINT)| // Disable TWI Interrupt and clear the flag\r
- (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)| // Initiate a STOP condition.\r
- (0<<TWWC); //\r
- }\r
- break;\r
- case TWI_MRX_DATA_ACK: // Data byte has been received and ACK tramsmitted\r
- TWI_buf[TWI_bufPtr++] = TWDR;\r
- case TWI_MRX_ADR_ACK: // SLA+R has been tramsmitted and ACK received\r
- if (TWI_bufPtr < (TWI_msgSize-1) ) // Detect the last byte to NACK it.\r
- {\r
- TWCR = (1<<TWEN)| // TWI Interface enabled\r
- (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to read next byte\r
- (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Send ACK after reception\r
- (0<<TWWC); // \r
- }else // Send NACK after next reception\r
- {\r
- TWCR = (1<<TWEN)| // TWI Interface enabled\r
- (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to read next byte\r
- (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Send NACK after reception\r
- (0<<TWWC); // \r
- } \r
- break; \r
- case TWI_MRX_DATA_NACK: // Data byte has been received and NACK tramsmitted\r
- TWI_buf[TWI_bufPtr] = TWDR;\r
- TWI_statusReg.lastTransOK = TRUE; // Set status bits to completed successfully. \r
- TWCR = (1<<TWEN)| // TWI Interface enabled\r
- (0<<TWIE)|(1<<TWINT)| // Disable TWI Interrupt and clear the flag\r
- (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)| // Initiate a STOP condition.\r
- (0<<TWWC); //\r
- break; \r
- case TWI_ARB_LOST: // Arbitration lost\r
- TWCR = (1<<TWEN)| // TWI Interface enabled\r
- (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag\r
- (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)| // Initiate a (RE)START condition.\r
- (0<<TWWC); //\r
- break;\r
- case TWI_MTX_ADR_NACK: // SLA+W has been tramsmitted and NACK received\r
- case TWI_MRX_ADR_NACK: // SLA+R has been tramsmitted and NACK received \r
- case TWI_MTX_DATA_NACK: // Data byte has been tramsmitted and NACK received\r
-// case TWI_NO_STATE // No relevant state information available; TWINT = \930\94\r
- case TWI_BUS_ERROR: // Bus error due to an illegal START or STOP condition\r
- default: \r
- TWI_state = TWSR; // Store TWSR and automatically sets clears noErrors bit.\r
- // Reset TWI Interface\r
- TWCR = (1<<TWEN)| // Enable TWI-interface and release TWI pins\r
- (0<<TWIE)|(0<<TWINT)| // Disable Interupt\r
- (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // No Signal requests\r
- (0<<TWWC); //\r
- }\r
-}\r
+++ /dev/null
-/*****************************************************************************\r
-*\r
-* Atmel Corporation\r
-*\r
-* File : TWI_Master.h\r
-* Compiler : IAR EWAAVR 2.28a/3.10c\r
-* Revision : $Revision: 1.13 $\r
-* Date : $Date: 24. mai 2004 11:31:22 $\r
-* Updated by : $Author: ltwa $\r
-*\r
-* Support mail : avr@atmel.com\r
-*\r
-* Supported devices : All devices with a TWI module can be used.\r
-* The example is written for the ATmega16\r
-*\r
-* AppNote : AVR315 - TWI Master Implementation\r
-*\r
-* Description : Header file for TWI_Master.c\r
-* Include this file in the application.\r
-*\r
-****************************************************************************/\r
-\r
-/****************************************************************************\r
- TWI Status/Control register definitions\r
-****************************************************************************/\r
-#define TWI_BUFFER_SIZE 4 // Set this to the largest message size that will be sent including address byte.\r
-\r
-#define TWI_TWBR 0x0C // TWI Bit rate Register setting.\r
- // Se Application note for detailed \r
- // information on setting this value.\r
-// Not used defines!\r
-//#define TWI_TWPS 0x00 // This driver presumes prescaler = 00\r
-\r
-/****************************************************************************\r
- Global definitions\r
-****************************************************************************/\r
-\r
-union TWI_statusReg // Status byte holding flags.\r
-{\r
- unsigned char all;\r
- struct\r
- {\r
- unsigned char lastTransOK:1; \r
- unsigned char unusedBits:7;\r
- };\r
-};\r
-\r
-extern union TWI_statusReg TWI_statusReg;\r
-\r
-/****************************************************************************\r
- Function definitions\r
-****************************************************************************/\r
-void TWI_Master_Initialise( void );\r
-unsigned char TWI_Transceiver_Busy( void );\r
-unsigned char TWI_Get_State_Info( void );\r
-void TWI_Start_Transceiver_With_Data( unsigned char * , unsigned char );\r
-void TWI_Start_Transceiver( void );\r
-unsigned char TWI_Get_Data_From_Transceiver( unsigned char *, unsigned char );\r
-\r
-/****************************************************************************\r
- Bit and byte definitions\r
-****************************************************************************/\r
-#define TWI_READ_BIT 0 // Bit position for R/W bit in "address byte".\r
-#define TWI_ADR_BITS 1 // Bit position for LSB of the slave address bits in the init byte.\r
-\r
-#define TRUE 1\r
-#define FALSE 0\r
-\r
-/****************************************************************************\r
- TWI State codes\r
-****************************************************************************/\r
-// General TWI Master staus codes \r
-#define TWI_START 0x08 // START has been transmitted \r
-#define TWI_REP_START 0x10 // Repeated START has been transmitted\r
-#define TWI_ARB_LOST 0x38 // Arbitration lost\r
-\r
-// TWI Master Transmitter staus codes \r
-#define TWI_MTX_ADR_ACK 0x18 // SLA+W has been tramsmitted and ACK received\r
-#define TWI_MTX_ADR_NACK 0x20 // SLA+W has been tramsmitted and NACK received \r
-#define TWI_MTX_DATA_ACK 0x28 // Data byte has been tramsmitted and ACK received\r
-#define TWI_MTX_DATA_NACK 0x30 // Data byte has been tramsmitted and NACK received \r
-\r
-// TWI Master Receiver staus codes \r
-#define TWI_MRX_ADR_ACK 0x40 // SLA+R has been tramsmitted and ACK received\r
-#define TWI_MRX_ADR_NACK 0x48 // SLA+R has been tramsmitted and NACK received\r
-#define TWI_MRX_DATA_ACK 0x50 // Data byte has been received and ACK tramsmitted\r
-#define TWI_MRX_DATA_NACK 0x58 // Data byte has been received and NACK tramsmitted\r
-\r
-// TWI Slave Transmitter staus codes\r
-#define TWI_STX_ADR_ACK 0xA8 // Own SLA+R has been received; ACK has been returned\r
-#define TWI_STX_ADR_ACK_M_ARB_LOST 0xB0 // Arbitration lost in SLA+R/W as Master; own SLA+R has been received; ACK has been returned\r
-#define TWI_STX_DATA_ACK 0xB8 // Data byte in TWDR has been transmitted; ACK has been received\r
-#define TWI_STX_DATA_NACK 0xC0 // Data byte in TWDR has been transmitted; NOT ACK has been received\r
-#define TWI_STX_DATA_ACK_LAST_BYTE 0xC8 // Last data byte in TWDR has been transmitted (TWEA = \930\94); ACK has been received\r
-\r
-// TWI Slave Receiver staus codes\r
-#define TWI_SRX_ADR_ACK 0x60 // Own SLA+W has been received ACK has been returned\r
-#define TWI_SRX_ADR_ACK_M_ARB_LOST 0x68 // Arbitration lost in SLA+R/W as Master; own SLA+W has been received; ACK has been returned\r
-#define TWI_SRX_GEN_ACK 0x70 // General call address has been received; ACK has been returned\r
-#define TWI_SRX_GEN_ACK_M_ARB_LOST 0x78 // Arbitration lost in SLA+R/W as Master; General call address has been received; ACK has been returned\r
-#define TWI_SRX_ADR_DATA_ACK 0x80 // Previously addressed with own SLA+W; data has been received; ACK has been returned\r
-#define TWI_SRX_ADR_DATA_NACK 0x88 // Previously addressed with own SLA+W; data has been received; NOT ACK has been returned\r
-#define TWI_SRX_GEN_DATA_ACK 0x90 // Previously addressed with general call; data has been received; ACK has been returned\r
-#define TWI_SRX_GEN_DATA_NACK 0x98 // Previously addressed with general call; data has been received; NOT ACK has been returned\r
-#define TWI_SRX_STOP_RESTART 0xA0 // A STOP condition or repeated START condition has been received while still addressed as Slave\r
-\r
-// TWI Miscellaneous status codes\r
-#define TWI_NO_STATE 0xF8 // No relevant state information available; TWINT = \930\94\r
-#define TWI_BUS_ERROR 0x00 // Bus error due to an illegal START or STOP condition\r
-\r