Additions from 11/12/2022: Using interruptions for ADC, Added Updated version of USI driver for I2C.
This commit is contained in:
parent
900988633e
commit
8730b36933
11 changed files with 1042 additions and 122 deletions
749
att/usiTwiSlave.c
Executable file
749
att/usiTwiSlave.c
Executable file
|
@ -0,0 +1,749 @@
|
|||
/********************************************************************************
|
||||
|
||||
USI TWI Slave driver.
|
||||
|
||||
Created by Donald R. Blake. donblake at worldnet.att.net
|
||||
Adapted by Jochen Toppe, jochen.toppe at jtoee.com
|
||||
|
||||
---------------------------------------------------------------------------------
|
||||
|
||||
Created from Atmel source files for Application Note AVR312: Using the USI Module
|
||||
as an I2C slave.
|
||||
|
||||
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.
|
||||
|
||||
---------------------------------------------------------------------------------
|
||||
|
||||
Change Activity:
|
||||
|
||||
Date Description
|
||||
------ -------------
|
||||
16 Mar 2007 Created.
|
||||
27 Mar 2007 Added support for ATtiny261, 461 and 861.
|
||||
26 Apr 2007 Fixed ACK of slave address on a read.
|
||||
04 Jul 2007 Fixed USISIF in ATtiny45 def
|
||||
12 Dev 2009 Added callback functions for data requests
|
||||
06 Feb 2016 Minor change to allow mutli-byte requestFrom() from master.
|
||||
10 Feb 2016 Simplied RX/TX buffer code and allowed use of full buffer.
|
||||
13 Feb 2016 Made USI_RECEIVE_CALLBACK() callback fully interrupt-driven
|
||||
12 Dec 2016 Added support for ATtiny167
|
||||
23 Dec 2017 Fixed repeated restart (which broke when making receive callback
|
||||
interrupt-driven)
|
||||
|
||||
********************************************************************************/
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
includes
|
||||
********************************************************************************/
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#include "usiTwiSlave.h"
|
||||
//#include "../common/util.h"
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
device dependent defines
|
||||
********************************************************************************/
|
||||
|
||||
#if defined( __AVR_ATtiny167__ )
|
||||
# define DDR_USI DDRB
|
||||
# define PORT_USI PORTB
|
||||
# define PIN_USI PINB
|
||||
# define PORT_USI_SDA PB0
|
||||
# define PORT_USI_SCL PB2
|
||||
# define PIN_USI_SDA PINB0
|
||||
# define PIN_USI_SCL PINB2
|
||||
# define USI_START_COND_INT USISIF
|
||||
# define USI_START_VECTOR USI_START_vect
|
||||
# define USI_OVERFLOW_VECTOR USI_OVERFLOW_vect
|
||||
#endif
|
||||
|
||||
#if defined( __AVR_ATtiny2313__ )
|
||||
# define DDR_USI DDRB
|
||||
# define PORT_USI PORTB
|
||||
# define PIN_USI PINB
|
||||
# define PORT_USI_SDA PB5
|
||||
# define PORT_USI_SCL PB7
|
||||
# define PIN_USI_SDA PINB5
|
||||
# define PIN_USI_SCL PINB7
|
||||
# define USI_START_COND_INT USISIF
|
||||
# define USI_START_VECTOR USI_START_vect
|
||||
# define USI_OVERFLOW_VECTOR USI_OVERFLOW_vect
|
||||
#endif
|
||||
|
||||
#if defined(__AVR_ATtiny84__) | \
|
||||
defined(__AVR_ATtiny44__)
|
||||
# define DDR_USI DDRA
|
||||
# define PORT_USI PORTA
|
||||
# define PIN_USI PINA
|
||||
# define PORT_USI_SDA PORTA6
|
||||
# define PORT_USI_SCL PORTA4
|
||||
# define PIN_USI_SDA PINA6
|
||||
# define PIN_USI_SCL PINA4
|
||||
# define USI_START_COND_INT USISIF
|
||||
# define USI_START_VECTOR USI_START_vect
|
||||
# define USI_OVERFLOW_VECTOR USI_OVF_vect
|
||||
#endif
|
||||
|
||||
#if defined( __AVR_ATtiny25__ ) | \
|
||||
defined( __AVR_ATtiny45__ ) | \
|
||||
defined( __AVR_ATtiny85__ )
|
||||
# define DDR_USI DDRB
|
||||
# define PORT_USI PORTB
|
||||
# define PIN_USI PINB
|
||||
# define PORT_USI_SDA PB0
|
||||
# define PORT_USI_SCL PB2
|
||||
# define PIN_USI_SDA PINB0
|
||||
# define PIN_USI_SCL PINB2
|
||||
# define USI_START_COND_INT USISIF
|
||||
# define USI_START_VECTOR USI_START_vect
|
||||
# define USI_OVERFLOW_VECTOR USI_OVF_vect
|
||||
#endif
|
||||
|
||||
#if defined( __AVR_ATtiny26__ )
|
||||
# define DDR_USI DDRB
|
||||
# define PORT_USI PORTB
|
||||
# define PIN_USI PINB
|
||||
# define PORT_USI_SDA PB0
|
||||
# define PORT_USI_SCL PB2
|
||||
# define PIN_USI_SDA PINB0
|
||||
# define PIN_USI_SCL PINB2
|
||||
# define USI_START_COND_INT USISIF
|
||||
# define USI_START_VECTOR USI_STRT_vect
|
||||
# define USI_OVERFLOW_VECTOR USI_OVF_vect
|
||||
#endif
|
||||
|
||||
#if defined( __AVR_ATtiny261__ ) | \
|
||||
defined( __AVR_ATtiny461__ ) | \
|
||||
defined( __AVR_ATtiny861__ )
|
||||
# define DDR_USI DDRB
|
||||
# define PORT_USI PORTB
|
||||
# define PIN_USI PINB
|
||||
# define PORT_USI_SDA PB0
|
||||
# define PORT_USI_SCL PB2
|
||||
# define PIN_USI_SDA PINB0
|
||||
# define PIN_USI_SCL PINB2
|
||||
# define USI_START_COND_INT USISIF
|
||||
# define USI_START_VECTOR USI_START_vect
|
||||
# define USI_OVERFLOW_VECTOR USI_OVF_vect
|
||||
#endif
|
||||
|
||||
#if defined( __AVR_ATmega165__ ) | \
|
||||
defined( __AVR_ATmega325__ ) | \
|
||||
defined( __AVR_ATmega3250__ ) | \
|
||||
defined( __AVR_ATmega645__ ) | \
|
||||
defined( __AVR_ATmega6450__ ) | \
|
||||
defined( __AVR_ATmega329__ ) | \
|
||||
defined( __AVR_ATmega3290__ )
|
||||
# define DDR_USI DDRE
|
||||
# define PORT_USI PORTE
|
||||
# define PIN_USI PINE
|
||||
# define PORT_USI_SDA PE5
|
||||
# define PORT_USI_SCL PE4
|
||||
# define PIN_USI_SDA PINE5
|
||||
# define PIN_USI_SCL PINE4
|
||||
# define USI_START_COND_INT USISIF
|
||||
# define USI_START_VECTOR USI_START_vect
|
||||
# define USI_OVERFLOW_VECTOR USI_OVERFLOW_vect
|
||||
#endif
|
||||
|
||||
#if defined( __AVR_ATmega169__ )
|
||||
# define DDR_USI DDRE
|
||||
# define PORT_USI PORTE
|
||||
# define PIN_USI PINE
|
||||
# define PORT_USI_SDA PE5
|
||||
# define PORT_USI_SCL PE4
|
||||
# define PIN_USI_SDA PINE5
|
||||
# define PIN_USI_SCL PINE4
|
||||
# define USI_START_COND_INT USISIF
|
||||
# define USI_START_VECTOR USI_START_vect
|
||||
# define USI_OVERFLOW_VECTOR USI_OVERFLOW_vect
|
||||
#endif
|
||||
|
||||
// These macros make the stop condition detection code more readable.
|
||||
#define USI_PINS_SCL_SDA ( ( 1 << PIN_USI_SDA ) | ( 1 << PIN_USI_SCL ) )
|
||||
#define USI_PINS_SDA ( 1 << PIN_USI_SDA )
|
||||
#define USI_PINS_SCL ( 1 << PIN_USI_SCL )
|
||||
|
||||
/********************************************************************************
|
||||
|
||||
functions implemented as macros
|
||||
|
||||
********************************************************************************/
|
||||
|
||||
#define SET_USI_TO_SEND_ACK( ) \
|
||||
{ \
|
||||
/* prepare ACK, ack is a zero */ \
|
||||
USIDR = 0; \
|
||||
/* set SDA as output */ \
|
||||
DDR_USI |= ( 1 << PORT_USI_SDA ); \
|
||||
/* clear all interrupt flags, except Start Cond */ \
|
||||
USISR = \
|
||||
( 0 << USI_START_COND_INT ) | \
|
||||
( 1 << USIOIF ) | ( 1 << USIPF ) | \
|
||||
( 1 << USIDC )| \
|
||||
/* set USI counter to shift 1 bit */ \
|
||||
( 0x0E << USICNT0 ); \
|
||||
}
|
||||
|
||||
#define SET_USI_TO_READ_ACK( ) \
|
||||
{ \
|
||||
/* set SDA as input */ \
|
||||
DDR_USI &= ~( 1 << PORT_USI_SDA ); \
|
||||
/* prepare ACK */ \
|
||||
USIDR = 0; \
|
||||
/* clear all interrupt flags, except Start Cond */ \
|
||||
USISR = \
|
||||
( 0 << USI_START_COND_INT ) | \
|
||||
( 1 << USIOIF ) | \
|
||||
( 1 << USIPF ) | \
|
||||
( 1 << USIDC ) | \
|
||||
/* set USI counter to shift 1 bit */ \
|
||||
( 0x0E << USICNT0 ); \
|
||||
}
|
||||
|
||||
#define SET_USI_TO_TWI_START_CONDITION_MODE( ) \
|
||||
{ \
|
||||
USICR = \
|
||||
/* enable Start Condition Interrupt, disable Overflow Interrupt */ \
|
||||
( 1 << USISIE ) | ( 0 << USIOIE ) | \
|
||||
/* set USI in Two-wire mode, no USI Counter overflow hold */ \
|
||||
( 1 << USIWM1 ) | ( 0 << USIWM0 ) | \
|
||||
/* Shift Register Clock Source = External, positive edge */ \
|
||||
/* 4-Bit Counter Source = external, both edges */ \
|
||||
( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) | \
|
||||
/* no toggle clock-port pin */ \
|
||||
( 0 << USITC ); \
|
||||
USISR = \
|
||||
/* clear all interrupt flags, except Start Cond */ \
|
||||
( 0 << USI_START_COND_INT ) | ( 1 << USIOIF ) | ( 1 << USIPF ) | \
|
||||
( 1 << USIDC ) | ( 0x0 << USICNT0 ); \
|
||||
}
|
||||
|
||||
#define SET_USI_TO_SEND_DATA( ) \
|
||||
{ \
|
||||
/* set SDA as output */ \
|
||||
DDR_USI |= ( 1 << PORT_USI_SDA ); \
|
||||
/* clear all interrupt flags, except Start Cond */ \
|
||||
USISR = \
|
||||
( 0 << USI_START_COND_INT ) | ( 1 << USIOIF ) | ( 1 << USIPF ) | \
|
||||
( 1 << USIDC) | \
|
||||
/* set USI to shift out 8 bits */ \
|
||||
( 0x0 << USICNT0 ); \
|
||||
}
|
||||
|
||||
#define SET_USI_TO_READ_DATA( ) \
|
||||
{ \
|
||||
/* set SDA as input */ \
|
||||
DDR_USI &= ~( 1 << PORT_USI_SDA ); \
|
||||
/* clear all interrupt flags, except Start Cond */ \
|
||||
USISR = \
|
||||
( 0 << USI_START_COND_INT ) | ( 1 << USIOIF ) | \
|
||||
( 1 << USIPF ) | ( 1 << USIDC ) | \
|
||||
/* set USI to shift out 8 bits */ \
|
||||
( 0x0 << USICNT0 ); \
|
||||
}
|
||||
|
||||
#define USI_RECEIVE_CALLBACK() \
|
||||
{ \
|
||||
if (usi_onReceiverPtr) \
|
||||
{ \
|
||||
if (usiTwiAmountDataInReceiveBuffer()) \
|
||||
{ \
|
||||
usi_onReceiverPtr(usiTwiAmountDataInReceiveBuffer()); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define USI_REQUEST_CALLBACK() \
|
||||
{ \
|
||||
if(usi_onRequestPtr) usi_onRequestPtr(); \
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
|
||||
typedef's
|
||||
|
||||
********************************************************************************/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
USI_SLAVE_CHECK_ADDRESS = 0x00,
|
||||
USI_SLAVE_SEND_DATA = 0x01,
|
||||
USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA = 0x02,
|
||||
USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA = 0x03,
|
||||
USI_SLAVE_REQUEST_DATA = 0x04,
|
||||
USI_SLAVE_GET_DATA_AND_SEND_ACK = 0x05
|
||||
} overflowState_t;
|
||||
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
|
||||
local variables
|
||||
|
||||
********************************************************************************/
|
||||
|
||||
static uint8_t slaveAddress;
|
||||
static uint8_t sleep_enable_bit;
|
||||
static uint8_t in_transaction;
|
||||
static volatile overflowState_t overflowState;
|
||||
|
||||
|
||||
static uint8_t rxBuf[ TWI_RX_BUFFER_SIZE ];
|
||||
static volatile uint8_t rxHead;
|
||||
static volatile uint8_t rxTail;
|
||||
static volatile uint8_t rxCount;
|
||||
|
||||
static uint8_t txBuf[ TWI_TX_BUFFER_SIZE ];
|
||||
static volatile uint8_t txHead;
|
||||
static volatile uint8_t txTail;
|
||||
static volatile uint8_t txCount;
|
||||
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
|
||||
local functions
|
||||
|
||||
********************************************************************************/
|
||||
|
||||
// flushes the TWI buffers
|
||||
|
||||
static void flushTwiBuffers( void )
|
||||
{
|
||||
rxTail = 0;
|
||||
rxHead = 0;
|
||||
rxCount = 0;
|
||||
txTail = 0;
|
||||
txHead = 0;
|
||||
txCount = 0;
|
||||
} // end flushTwiBuffers
|
||||
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
|
||||
public functions
|
||||
|
||||
********************************************************************************/
|
||||
|
||||
// initialise USI for TWI slave mode
|
||||
|
||||
void usiTwiSlaveInit( uint8_t ownAddress )
|
||||
{
|
||||
// initialize the TX and RX buffers to empty
|
||||
flushTwiBuffers( );
|
||||
|
||||
slaveAddress = ownAddress;
|
||||
|
||||
// In Two Wire mode (USIWM1, USIWM0 = 1X), the slave USI will pull SCL
|
||||
// low when a start condition is detected or a counter overflow (only
|
||||
// for USIWM1, USIWM0 = 11). This inserts a wait state. SCL is released
|
||||
// by the ISRs (USI_START_vect and USI_OVERFLOW_vect).
|
||||
|
||||
// Set SCL and SDA as output
|
||||
DDR_USI |= ( 1 << PORT_USI_SCL ) | ( 1 << PORT_USI_SDA );
|
||||
|
||||
// set SCL high
|
||||
PORT_USI |= ( 1 << PORT_USI_SCL );
|
||||
|
||||
// set SDA high
|
||||
PORT_USI |= ( 1 << PORT_USI_SDA );
|
||||
|
||||
// Set SDA and SCL as input
|
||||
DDR_USI &= ~( 1 << PORT_USI_SDA );
|
||||
DDR_USI &= ~( 1 << PORT_USI_SCL );
|
||||
|
||||
USICR =
|
||||
// enable Start Condition Interrupt
|
||||
( 1 << USISIE ) |
|
||||
// disable Overflow Interrupt
|
||||
( 0 << USIOIE ) |
|
||||
// set USI in Two-wire mode, no USI Counter overflow hold
|
||||
( 1 << USIWM1 ) | ( 0 << USIWM0 ) |
|
||||
// Shift Register Clock Source = external, positive edge
|
||||
// 4-Bit Counter Source = external, both edges
|
||||
( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) |
|
||||
// no toggle clock-port pin
|
||||
( 0 << USITC );
|
||||
|
||||
// clear all interrupt flags and reset overflow counter
|
||||
|
||||
USISR = ( 1 << USI_START_COND_INT ) | ( 1 << USIOIF ) | ( 1 << USIPF ) | ( 1 << USIDC );
|
||||
|
||||
// The 'in_transaction' variable remembers if the usiTwiSlave driver is in the middle of
|
||||
// an i2c transaction. Initialize it to zero
|
||||
in_transaction = 0;
|
||||
|
||||
} // end usiTwiSlaveInit
|
||||
|
||||
|
||||
bool usiTwiDataInTransmitBuffer(void)
|
||||
{
|
||||
|
||||
// return 0 (false) if the receive buffer is empty
|
||||
return txCount;
|
||||
|
||||
} // end usiTwiDataInTransmitBuffer
|
||||
|
||||
|
||||
// put data in the transmission buffer, wait if buffer is full
|
||||
|
||||
void usiTwiTransmitByte( uint8_t data )
|
||||
{
|
||||
|
||||
// wait for free space in buffer
|
||||
while ( txCount == TWI_TX_BUFFER_SIZE) ;
|
||||
|
||||
// store data in buffer
|
||||
txBuf[ txHead ] = data;
|
||||
txHead = ( txHead + 1 ) & TWI_TX_BUFFER_MASK;
|
||||
txCount++;
|
||||
|
||||
} // end usiTwiTransmitByte
|
||||
|
||||
|
||||
// return a byte from the receive buffer, wait if buffer is empty
|
||||
|
||||
uint8_t usiTwiReceiveByte( void )
|
||||
{
|
||||
uint8_t rtn_byte;
|
||||
|
||||
// wait for Rx data
|
||||
while ( !rxCount );
|
||||
|
||||
rtn_byte = rxBuf [ rxTail ];
|
||||
// calculate buffer index
|
||||
rxTail = ( rxTail + 1 ) & TWI_RX_BUFFER_MASK;
|
||||
rxCount--;
|
||||
|
||||
// return data from the buffer.
|
||||
return rtn_byte;
|
||||
|
||||
} // end usiTwiReceiveByte
|
||||
|
||||
|
||||
uint8_t usiTwiAmountDataInReceiveBuffer(void)
|
||||
{
|
||||
return rxCount;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
|
||||
USI Start Condition ISR
|
||||
|
||||
********************************************************************************/
|
||||
|
||||
ISR( USI_START_VECTOR )
|
||||
{
|
||||
uint8_t usi_pins;
|
||||
// http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__avr__interrupts.html
|
||||
|
||||
// Notes about ISR. The compiler in the Arduino IDE handles some of the
|
||||
// basic ISR plumbing (unless the "ISR_NAKED" attribute is applied).
|
||||
// * The AVR processor resets the SREG.I bit when jumping into an ISR
|
||||
// * The compiler automatically adds code to save SREG
|
||||
// * < user's ISR code goes here >
|
||||
// * The compiler automatically adds code to restore SREG
|
||||
// * The compiler automatically uses the RETI instruction to return from the ISR.
|
||||
// The RETI instruction enables interrupts after the return from ISR.
|
||||
// The compiler behavior can be altered with attributes into the ISR declaration;
|
||||
// however, the description above is the default.
|
||||
|
||||
// cli() call is not necessary. Processor disables interrupts when
|
||||
// jumping to an ISR
|
||||
|
||||
// no need to save the SREG. The compiler does this automatically when using the
|
||||
// ISR construct without modifying attributes.
|
||||
|
||||
if ( !in_transaction )
|
||||
{
|
||||
// remeber the sleep enable bit when entering the ISR
|
||||
sleep_enable_bit = MCUCR & ( 1 << SE );
|
||||
|
||||
// clear the sleep enable bit to prevent the CPU from entering sleep mode while executing this ISR.
|
||||
MCUCR &= ~( 1 << SE );
|
||||
}
|
||||
|
||||
// set default starting conditions for new TWI package
|
||||
overflowState = USI_SLAVE_CHECK_ADDRESS;
|
||||
|
||||
// set SDA as input
|
||||
DDR_USI &= ~( 1 << PORT_USI_SDA );
|
||||
|
||||
// the start condition is that the master pulls SDA low.
|
||||
|
||||
// wait for SCL to go low to ensure the Start Condition has completed (the
|
||||
// start detector will hold SCL low ) - if a Stop Condition arises then leave
|
||||
// the interrupt to prevent waiting forever - don't use USISR to test for Stop
|
||||
// Condition as in Application Note AVR312 because the Stop Condition Flag is
|
||||
// going to be set from the last TWI sequence
|
||||
|
||||
// while SCL is high and SDA is low
|
||||
while ( ( usi_pins = PIN_USI & USI_PINS_SCL_SDA ) == USI_PINS_SCL );
|
||||
|
||||
// if SDA line was low at SCL edge, then start condition occurred
|
||||
if ( !( usi_pins & USI_PINS_SDA ) )
|
||||
{
|
||||
// a Stop Condition did not occur
|
||||
|
||||
// Execute callback if this is a repeated start
|
||||
if (in_transaction)
|
||||
{
|
||||
USI_RECEIVE_CALLBACK();
|
||||
}
|
||||
|
||||
USICR =
|
||||
// keep Start Condition Interrupt enabled to detect RESTART
|
||||
( 1 << USISIE ) |
|
||||
// enable Overflow Interrupt
|
||||
( 1 << USIOIE ) |
|
||||
// set USI in Two-wire mode, hold SCL low on USI Counter overflow
|
||||
( 1 << USIWM1 ) | ( 1 << USIWM0 ) |
|
||||
// Shift Register Clock Source = External, positive edge
|
||||
// 4-Bit Counter Source = external, both edges
|
||||
( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) |
|
||||
// no toggle clock-port pin
|
||||
( 0 << USITC );
|
||||
|
||||
//remember that the USI is in a valid i2c transaction
|
||||
in_transaction = 1;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// a Stop Condition did occur
|
||||
|
||||
USICR =
|
||||
// enable Start Condition Interrupt
|
||||
( 1 << USISIE ) |
|
||||
// disable Overflow Interrupt
|
||||
( 0 << USIOIE ) |
|
||||
// set USI in Two-wire mode, no USI Counter overflow hold
|
||||
( 1 << USIWM1 ) | ( 0 << USIWM0 ) |
|
||||
// Shift Register Clock Source = external, positive edge
|
||||
// 4-Bit Counter Source = external, both edges
|
||||
( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) |
|
||||
// no toggle clock-port pin
|
||||
( 0 << USITC );
|
||||
|
||||
//no longer in valid i2c transaction
|
||||
in_transaction = 0;
|
||||
// restore the sleep enable bit
|
||||
MCUCR |= sleep_enable_bit;
|
||||
|
||||
} // end if
|
||||
|
||||
USISR =
|
||||
// clear interrupt flags - resetting the Start Condition Flag will
|
||||
// release SCL
|
||||
( 1 << USI_START_COND_INT ) | ( 1 << USIOIF ) |
|
||||
( 1 << USIPF ) |( 1 << USIDC ) |
|
||||
// set USI to sample 8 bits (count 16 external SCL pin toggles)
|
||||
( 0x0 << USICNT0);
|
||||
|
||||
// no need to restore the SREG. The compiler does this automatically when using the
|
||||
// ISR construct without modifying attributes.
|
||||
|
||||
// The compiler automatically uses an RETI instruction to return when using the
|
||||
// ISR construct without modifying attributes.
|
||||
|
||||
} // end ISR( USI_START_VECTOR )
|
||||
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
|
||||
USI Overflow ISR
|
||||
|
||||
Handles all the communication.
|
||||
|
||||
Only disabled when waiting for a new Start Condition.
|
||||
|
||||
********************************************************************************/
|
||||
|
||||
ISR( USI_OVERFLOW_VECTOR )
|
||||
{
|
||||
uint8_t finished;
|
||||
uint8_t usi_pins;
|
||||
|
||||
// http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__avr__interrupts.html
|
||||
|
||||
// Notes about ISR. The compiler in the Arduino IDE handles some of the
|
||||
// basic ISR plumbing.
|
||||
// * The AVR processor resets the SREG.I bit when jumping into an ISR
|
||||
// * The compiler automatically adds code to save the SREG
|
||||
// * < user's ISR code goes here >
|
||||
// * The compiler automatically adds code to restore the SREG
|
||||
// * The compiler automatically uses the RETI instruction to return from the ISR.
|
||||
// The RETI insturction enables interrupts after the return from ISR.
|
||||
// The compiler behavior can be altered with attributes into the ISR declaration;
|
||||
// however, the description above is the default.
|
||||
|
||||
// cli() call is not necessary. Processor disables interrupts when
|
||||
// jumping to an ISR
|
||||
|
||||
// no need to save the SREG. The compiler does this automatically when using the
|
||||
// ISR construct without modifying attributes.
|
||||
|
||||
// The ISR is only ever entered because the ISR(USI_START_VECTOR) interrupt
|
||||
// routine ran first. That routine saved the sleep mode and disabled sleep.
|
||||
|
||||
// Most of the time this routine exits, it has setup the USI to shift in/out bits
|
||||
// and is expected to re-entered because of the USI overflow interrupt. Track whether or
|
||||
// not the transaction is completely finished.
|
||||
finished = 0;
|
||||
|
||||
|
||||
switch ( overflowState )
|
||||
{
|
||||
|
||||
// Address mode: check address and send ACK (and next USI_SLAVE_SEND_DATA) if OK,
|
||||
// else reset USI
|
||||
case USI_SLAVE_CHECK_ADDRESS:
|
||||
if ( ( USIDR == 0 ) || ( ( USIDR >> 1 ) == slaveAddress) )
|
||||
{
|
||||
if ( USIDR & 0x01 )
|
||||
{
|
||||
overflowState = USI_SLAVE_SEND_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
overflowState = USI_SLAVE_REQUEST_DATA;
|
||||
} // end if
|
||||
|
||||
// ack the start frame
|
||||
// sets up the USI to pull SDA low and clock one bit (two edges)
|
||||
SET_USI_TO_SEND_ACK( );
|
||||
}
|
||||
else
|
||||
{
|
||||
SET_USI_TO_TWI_START_CONDITION_MODE( );
|
||||
finished = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
// master-read / slave-send: check reply and goto USI_SLAVE_SEND_DATA if OK,
|
||||
// else reset USI
|
||||
case USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA:
|
||||
// Execute request callback for each byte requested, as this is the intended
|
||||
// behavior of this library
|
||||
USI_REQUEST_CALLBACK();
|
||||
if ( USIDR )
|
||||
{
|
||||
// if NACK, the master does not want more data
|
||||
SET_USI_TO_TWI_START_CONDITION_MODE( );
|
||||
finished = 1;
|
||||
break;
|
||||
}
|
||||
// from here we just drop straight into USI_SLAVE_SEND_DATA if the
|
||||
// master sent an ACK
|
||||
|
||||
// copy data from buffer to USIDR and set USI to shift byte
|
||||
// next USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA
|
||||
case USI_SLAVE_SEND_DATA:
|
||||
// Get data from Buffer
|
||||
if ( txCount )
|
||||
{
|
||||
USIDR = txBuf[ txTail ];
|
||||
txTail = ( txTail + 1 ) & TWI_TX_BUFFER_MASK;
|
||||
txCount--;
|
||||
|
||||
overflowState = USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA;
|
||||
SET_USI_TO_SEND_DATA( );
|
||||
}
|
||||
else
|
||||
{
|
||||
// the buffer is empty
|
||||
SET_USI_TO_READ_ACK( ); // This might be neccessary sometimes see http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=805227#805227
|
||||
SET_USI_TO_TWI_START_CONDITION_MODE( );
|
||||
} // end if
|
||||
break;
|
||||
|
||||
// set USI to sample reply from master
|
||||
// next USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA
|
||||
case USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA:
|
||||
overflowState = USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA;
|
||||
SET_USI_TO_READ_ACK( );
|
||||
break;
|
||||
|
||||
// master-send / slave-receive: set USI to sample data from master, next
|
||||
// USI_SLAVE_GET_DATA_AND_SEND_ACK
|
||||
case USI_SLAVE_REQUEST_DATA:
|
||||
overflowState = USI_SLAVE_GET_DATA_AND_SEND_ACK;
|
||||
SET_USI_TO_READ_DATA( );
|
||||
|
||||
// with the SET_USI_TO_READ_DATA() macro call above, the USI has
|
||||
// been setup to catch the next byte if the master sends one.
|
||||
// while that's going on, look for a stop condition here which
|
||||
// is when the SDA line goes high after the SCL line;
|
||||
|
||||
// wait until SCL goes high
|
||||
while ( ! ( ( usi_pins = PIN_USI & USI_PINS_SCL_SDA ) & USI_PINS_SCL ) );
|
||||
|
||||
// if SDA line was high at SCL edge, then not a stop condition
|
||||
if ( usi_pins & USI_PINS_SDA )
|
||||
break;
|
||||
|
||||
// wait until SCL goes low or SDA goes high
|
||||
while ( ( usi_pins = PIN_USI & USI_PINS_SCL_SDA ) == USI_PINS_SCL );
|
||||
|
||||
// if both SCL and SDA are high, then stop condition occurred
|
||||
if ( usi_pins == USI_PINS_SCL_SDA )
|
||||
{
|
||||
USI_RECEIVE_CALLBACK();
|
||||
SET_USI_TO_TWI_START_CONDITION_MODE( );
|
||||
finished = 1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// copy data from USIDR and send ACK
|
||||
// next USI_SLAVE_REQUEST_DATA
|
||||
case USI_SLAVE_GET_DATA_AND_SEND_ACK:
|
||||
// put data into buffer
|
||||
// check buffer size
|
||||
if ( rxCount < TWI_RX_BUFFER_SIZE )
|
||||
{
|
||||
rxBuf[ rxHead ] = USIDR;
|
||||
rxHead = ( rxHead + 1 ) & TWI_RX_BUFFER_MASK;
|
||||
rxCount++;
|
||||
} else {
|
||||
// overrun
|
||||
// drop data
|
||||
}
|
||||
// next USI_SLAVE_REQUEST_DATA
|
||||
overflowState = USI_SLAVE_REQUEST_DATA;
|
||||
SET_USI_TO_SEND_ACK( );
|
||||
break;
|
||||
|
||||
} // end switch
|
||||
|
||||
if (finished)
|
||||
{
|
||||
//no longer in valid i2c transaction
|
||||
in_transaction = 0;
|
||||
// restore the sleep enable bit
|
||||
// note that this allows sleep -- it does not cause sleep
|
||||
MCUCR |= sleep_enable_bit;
|
||||
}
|
||||
|
||||
// no need to restore the SREG. The compiler does this automatically when using the
|
||||
// ISR construct without modifying attributes.
|
||||
|
||||
// The compiler automatically uses an RETI instruction to return when using the
|
||||
// ISR construct without modifying attributes.
|
||||
|
||||
} // end ISR( USI_OVERFLOW_VECTOR )
|
96
att/usiTwiSlave.h
Executable file
96
att/usiTwiSlave.h
Executable file
|
@ -0,0 +1,96 @@
|
|||
/********************************************************************************
|
||||
|
||||
Header file for the USI TWI Slave driver.
|
||||
|
||||
Created by Donald R. Blake
|
||||
donblake at worldnet.att.net
|
||||
|
||||
---------------------------------------------------------------------------------
|
||||
|
||||
Created from Atmel source files for Application Note AVR312: Using the USI Module
|
||||
as an I2C slave.
|
||||
|
||||
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.
|
||||
|
||||
---------------------------------------------------------------------------------
|
||||
|
||||
Change Activity:
|
||||
|
||||
Date Description
|
||||
------ -------------
|
||||
15 Mar 2007 Created.
|
||||
|
||||
********************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef _USI_TWI_SLAVE_H_
|
||||
#define _USI_TWI_SLAVE_H_
|
||||
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
|
||||
includes
|
||||
|
||||
********************************************************************************/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <avr/sleep.h>
|
||||
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
|
||||
prototypes
|
||||
|
||||
********************************************************************************/
|
||||
|
||||
void usiTwiSlaveInit( uint8_t );
|
||||
void usiTwiTransmitByte( uint8_t );
|
||||
uint8_t usiTwiReceiveByte( void );
|
||||
bool usiTwiDataInTransmitBuffer(void);
|
||||
uint8_t usiTwiAmountDataInReceiveBuffer(void);
|
||||
// on_XXX handler pointers
|
||||
void (*usi_onRequestPtr)(void);
|
||||
void (*usi_onReceiverPtr)(uint8_t);
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
|
||||
driver buffer definitions
|
||||
|
||||
********************************************************************************/
|
||||
|
||||
// permitted RX buffer sizes: 1, 2, 4, 8, 16, 32, 64, 128 or 256
|
||||
|
||||
#ifndef TWI_RX_BUFFER_SIZE
|
||||
#define TWI_RX_BUFFER_SIZE ( 16 )
|
||||
#endif
|
||||
#define TWI_RX_BUFFER_MASK ( TWI_RX_BUFFER_SIZE - 1 )
|
||||
|
||||
#if ( TWI_RX_BUFFER_SIZE & TWI_RX_BUFFER_MASK )
|
||||
# error TWI RX buffer size is not a power of 2
|
||||
#endif
|
||||
|
||||
// permitted TX buffer sizes: 1, 2, 4, 8, 16, 32, 64, 128 or 256
|
||||
|
||||
#ifndef TWI_TX_BUFFER_SIZE
|
||||
#define TWI_TX_BUFFER_SIZE ( 16 )
|
||||
#endif
|
||||
#define TWI_TX_BUFFER_MASK ( TWI_TX_BUFFER_SIZE - 1 )
|
||||
|
||||
#if ( TWI_TX_BUFFER_SIZE & TWI_TX_BUFFER_MASK )
|
||||
# error TWI TX buffer size is not a power of 2
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif // ifndef _USI_TWI_SLAVE_H_
|
|
@ -20,9 +20,15 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#if __GNUC__
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#else
|
||||
#include <inavr.h>
|
||||
#include <ioavr.h>
|
||||
#endif
|
||||
#include "USI_TWI_Slave.h"
|
||||
#include "led_receptor.h"
|
||||
|
||||
/*! Static Variables
|
||||
*/
|
||||
|
@ -64,7 +70,8 @@ void USI_TWI_Slave_Initialise( unsigned char TWI_ownAddress )
|
|||
|
||||
PORT_USI |= (1<<PORT_USI_SCL); // Set SCL high
|
||||
PORT_USI |= (1<<PORT_USI_SDA); // Set SDA high
|
||||
DDR_USI &= ~(1<<PORT_USI_SCL); //modified // Set SCL as input
|
||||
//DDR_USI |= (1<<PORT_USI_SCL); // Set SCL as output
|
||||
DDR_USI &= ~(1<<PORT_USI_SCL); // MODIF ::::::::::::::::: Set SCL as input
|
||||
DDR_USI &= ~(1<<PORT_USI_SDA); // Set SDA as input
|
||||
USICR = (1<<USISIE)|(0<<USIOIE)| // Enable Start Condition Interrupt. Disable Overflow Interrupt.
|
||||
(1<<USIWM1)|(0<<USIWM0)| // Set USI in Two-wire mode. No USI Counter overflow prior
|
||||
|
@ -114,10 +121,13 @@ unsigned char USI_TWI_Data_In_Receive_Buffer( void )
|
|||
* for reception of the "TWI Address" packet.
|
||||
*/
|
||||
|
||||
|
||||
/*#pragma vector=USI_START_VECTOR
|
||||
__interrupt void USI_Start_Condition_ISR(void)*/
|
||||
ISR(USI_START_VECTOR)
|
||||
{
|
||||
unsigned char tmpUSISR; // Temporary variable to store volatile
|
||||
//********************************************************************************************************************************************************
|
||||
//********************************************************************************************************************************************************
|
||||
unsigned char tmpUSISR; // Temporary variable to store volatile
|
||||
tmpUSISR = USISR; // Not necessary, but prevents warnings
|
||||
// Set default starting conditions for new TWI package
|
||||
USI_TWI_Overflow_State = USI_SLAVE_CHECK_ADDRESS;
|
||||
|
@ -130,7 +140,6 @@ ISR(USI_START_VECTOR)
|
|||
(0<<USITC);
|
||||
USISR = (1<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Clear flags
|
||||
(0x0<<USICNT0); // Set USI to sample 8 bits i.e. count 16 external pin toggles.
|
||||
// RGB_DDR |= RED_LED_MASK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -138,13 +147,13 @@ ISR(USI_START_VECTOR)
|
|||
* Handels all the comunication. Is disabled only when waiting
|
||||
* for new Start Condition.
|
||||
*/
|
||||
|
||||
/*#pragma vector=USI_OVERFLOW_VECTOR
|
||||
__interrupt void USI_Counter_Overflow_ISR(void)*/
|
||||
ISR(USI_OVERFLOW_VECTOR)
|
||||
{
|
||||
unsigned char tmpTxTail; // Temporary variables to store volatiles
|
||||
unsigned char tmpUSIDR;
|
||||
|
||||
|
||||
switch (USI_TWI_Overflow_State)
|
||||
{
|
||||
// ---------- Address mode ----------
|
||||
|
@ -152,15 +161,16 @@ ISR(USI_OVERFLOW_VECTOR)
|
|||
case USI_SLAVE_CHECK_ADDRESS:
|
||||
if ((USIDR == 0) || (( USIDR>>1 ) == TWI_slaveAddress))
|
||||
{
|
||||
if ( USIDR & 0x01 )
|
||||
USI_TWI_Overflow_State = USI_SLAVE_SEND_DATA;
|
||||
else
|
||||
USI_TWI_Overflow_State = USI_SLAVE_REQUEST_DATA;
|
||||
if ( USIDR & 0x01 ){ // R/W
|
||||
USI_TWI_Overflow_State = USI_SLAVE_SEND_DATA; //Read => L'esclave doit envoyer une donn?e
|
||||
}else{
|
||||
USI_TWI_Overflow_State = USI_SLAVE_REQUEST_DATA; //Write => L'esclave doit lire la demande
|
||||
}
|
||||
SET_USI_TO_SEND_ACK();
|
||||
}
|
||||
else
|
||||
{
|
||||
SET_USI_TO_TWI_START_CONDITION_MODE();
|
||||
SET_USI_TO_TWI_START_CONDITION_MODE();
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -63,9 +63,26 @@ typedef unsigned char uint8_t;
|
|||
#define USI_SLAVE_REQUEST_DATA (0x04)
|
||||
#define USI_SLAVE_GET_DATA_AND_SEND_ACK (0x05)
|
||||
|
||||
// AJOUT ########################################################################"
|
||||
#if defined (__AVR_ATtiny24__) | \
|
||||
defined (__AVR_ATtiny44__) | \
|
||||
defined (__AVR_ATtiny84__)
|
||||
#define DDR_USI DDRA
|
||||
#define PORT_USI PORTA
|
||||
#define PIN_USI PINA
|
||||
#define PORT_USI_SDA PA6
|
||||
#define PORT_USI_SCL PA4
|
||||
#define PIN_USI_SDA PINA6
|
||||
#define PIN_USI_SCL PINA4
|
||||
#define USI_START_COND_INT USISIF
|
||||
#define USI_START_VECTOR USI_STR_vect
|
||||
#define USI_OVERFLOW_VECTOR USI_OVF_vect
|
||||
#endif
|
||||
//###############################################################################
|
||||
|
||||
|
||||
//! Device dependent defines
|
||||
/*#if defined(__AT90tiny26__) | defined(__ATtiny26__)
|
||||
#if defined(__AT90tiny26__) | defined(__ATtiny26__)
|
||||
#define DDR_USI DDRB
|
||||
#define PORT_USI PORTB
|
||||
#define PIN_USI PINB
|
||||
|
@ -76,9 +93,9 @@ typedef unsigned char uint8_t;
|
|||
#define USI_START_COND_INT USISIF
|
||||
#define USI_START_VECTOR USI_STRT_vect
|
||||
#define USI_OVERFLOW_VECTOR USI_OVF_vect
|
||||
#endif*/
|
||||
#endif
|
||||
|
||||
/*#if defined(__AT90Tiny2313__) | defined(__ATtiny2313__)
|
||||
#if defined(__AT90Tiny2313__) | defined(__ATtiny2313__)
|
||||
#define DDR_USI DDRB
|
||||
#define PORT_USI PORTB
|
||||
#define PIN_USI PINB
|
||||
|
@ -87,11 +104,13 @@ typedef unsigned char uint8_t;
|
|||
#define PIN_USI_SDA PINB5
|
||||
#define PIN_USI_SCL PINB7
|
||||
#define USI_START_COND_INT USISIF
|
||||
#define USI_START_VECTOR USI_START_vect
|
||||
#define USI_OVERFLOW_VECTOR USI_OVERFLOW_vect
|
||||
#endif*/
|
||||
#define USI_START_VECTOR USI_STRT_vect
|
||||
#define USI_OVERFLOW_VECTOR USI_OVF_vect
|
||||
#endif
|
||||
|
||||
/*#if defined(__ATtiny25__) | defined(__ATtiny45__) | defined(__ATtiny85__)*/
|
||||
#if defined( __AVR_ATtiny25__ ) | \
|
||||
defined( __AVR_ATtiny45__ ) | \
|
||||
defined( __AVR_ATtiny85__ )
|
||||
#define DDR_USI DDRB
|
||||
#define PORT_USI PORTB
|
||||
#define PIN_USI PINB
|
||||
|
@ -99,12 +118,12 @@ typedef unsigned char uint8_t;
|
|||
#define PORT_USI_SCL PB2
|
||||
#define PIN_USI_SDA PINB0
|
||||
#define PIN_USI_SCL PINB2
|
||||
#define USI_START_COND_INT USISIF //soit USISIF ou USISIE
|
||||
#define USI_START_COND_INT USISIF
|
||||
#define USI_START_VECTOR USI_START_vect
|
||||
#define USI_OVERFLOW_VECTOR USI_OVF_vect
|
||||
/*#endif*/
|
||||
#endif
|
||||
|
||||
/*#if defined(__AT90Mega165__) | defined(__ATmega165__) | \
|
||||
#if defined(__AT90Mega165__) | defined(__ATmega165__) | \
|
||||
defined(__ATmega325__) | defined(__ATmega3250__) | \
|
||||
defined(__ATmega645__) | defined(__ATmega6450__) | \
|
||||
defined(__ATmega329__) | defined(__ATmega3290__) | \
|
||||
|
@ -119,9 +138,10 @@ typedef unsigned char uint8_t;
|
|||
#define USI_START_COND_INT USISIF
|
||||
#define USI_START_VECTOR USI_START_vect
|
||||
#define USI_OVERFLOW_VECTOR USI_OVERFLOW_vect
|
||||
#endif*/
|
||||
#endif
|
||||
|
||||
/*#if defined(__AT90Mega169__) | defined(__ATmega169__)
|
||||
//#if defined(__AT90Mega169__) | defined(__ATmega169__)
|
||||
#if defined(__AT90Mega169__) | defined(__AVR_ATmega169PA__)
|
||||
#define DDR_USI DDRE
|
||||
#define PORT_USI PORTE
|
||||
#define PIN_USI PINE
|
||||
|
@ -132,7 +152,7 @@ typedef unsigned char uint8_t;
|
|||
#define USI_START_COND_INT USISIF
|
||||
#define USI_START_VECTOR USI_STRT_vect
|
||||
#define USI_OVERFLOW_VECTOR USI_OVF_vect
|
||||
#endif*/
|
||||
#endif
|
||||
|
||||
//! Functions implemented as macros
|
||||
#define SET_USI_TO_SEND_ACK() \
|
||||
|
@ -153,14 +173,16 @@ typedef unsigned char uint8_t;
|
|||
|
||||
#define SET_USI_TO_TWI_START_CONDITION_MODE() \
|
||||
{ \
|
||||
USICR = (1<<USISIE)|(0<<USIOIE)| /* Enable Start Condition Interrupt. Disable Overflow Interrupt.*/ \
|
||||
(1<<USIWM1)|(0<<USIWM0)| /* Set USI in Two-wire mode. No USI Counter overflow hold. */ \
|
||||
(1<<USICS1)|(0<<USICS0)|(0<<USICLK)| /* Shift Register Clock Source = External, positive edge */ \
|
||||
(0<<USITC); \
|
||||
USISR = (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| /* Clear all flags, except Start Cond */ \
|
||||
(0x0<<USICNT0); \
|
||||
USICR = (1<<USISIE)|(0<<USIOIE)| /* Enable Start Condition Interrupt. Disable Overflow Interrupt.*/ \
|
||||
(1<<USIWM1)|(0<<USIWM0)| /* Set USI in Two-wire mode. No USI Counter overflow hold. */ \
|
||||
(1<<USICS1)|(0<<USICS0)|(0<<USICLK)| /* Shift Register Clock Source = External, positive edge */ \
|
||||
(0<<USITC); \
|
||||
USISR = (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| /* Clear all flags, except Start Cond */ \
|
||||
(0x0<<USICNT0); \
|
||||
ADCSRA |= (1<<ADEN)|(1<<ADIE)|(1<<ADSC); \
|
||||
}
|
||||
|
||||
|
||||
#define SET_USI_TO_SEND_DATA() \
|
||||
{ \
|
||||
DDR_USI |= (1<<PORT_USI_SDA); /* Set SDA as output */ \
|
||||
|
|
|
@ -9,57 +9,57 @@
|
|||
<CSub></CSub>
|
||||
<CVariant></CVariant>
|
||||
<CVendor>Atmel</CVendor>
|
||||
<CVersion>1.2.0</CVersion>
|
||||
<DefaultRepoPath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs</DefaultRepoPath>
|
||||
<CVersion>1.8.0</CVersion>
|
||||
<DefaultRepoPath>D:/Programs\Atmelstudio\7.0\Packs</DefaultRepoPath>
|
||||
<DependentComponents xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
|
||||
<Description></Description>
|
||||
<Files xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
|
||||
<d4p1:anyType i:type="FileInfo">
|
||||
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.2.118\include</AbsolutePath>
|
||||
<AbsolutePath>D:/Programs\Atmelstudio\7.0\Packs\atmel\ATtiny_DFP\1.8.332\include\</AbsolutePath>
|
||||
<Attribute></Attribute>
|
||||
<Category>include</Category>
|
||||
<Condition>C</Condition>
|
||||
<FileContentHash i:nil="true" />
|
||||
<FileVersion></FileVersion>
|
||||
<Name>include</Name>
|
||||
<Name>include/</Name>
|
||||
<SelectString></SelectString>
|
||||
<SourcePath></SourcePath>
|
||||
</d4p1:anyType>
|
||||
<d4p1:anyType i:type="FileInfo">
|
||||
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.2.118\include\avr\iotn85.h</AbsolutePath>
|
||||
<AbsolutePath>D:/Programs\Atmelstudio\7.0\Packs\atmel\ATtiny_DFP\1.8.332\include\avr\iotn85.h</AbsolutePath>
|
||||
<Attribute></Attribute>
|
||||
<Category>header</Category>
|
||||
<Condition>C</Condition>
|
||||
<FileContentHash>RcYmivGpgsCGGCzeWAIjcA==</FileContentHash>
|
||||
<FileContentHash>T0lnJZ6iliUJCzU7ZHCMPQ==</FileContentHash>
|
||||
<FileVersion></FileVersion>
|
||||
<Name>include/avr/iotn85.h</Name>
|
||||
<SelectString></SelectString>
|
||||
<SourcePath></SourcePath>
|
||||
</d4p1:anyType>
|
||||
<d4p1:anyType i:type="FileInfo">
|
||||
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.2.118\templates\main.c</AbsolutePath>
|
||||
<AbsolutePath>D:/Programs\Atmelstudio\7.0\Packs\atmel\ATtiny_DFP\1.8.332\templates\main.c</AbsolutePath>
|
||||
<Attribute>template</Attribute>
|
||||
<Category>source</Category>
|
||||
<Condition>C Exe</Condition>
|
||||
<FileContentHash>T6Fj/fIqJcOx0GrpJU4zHA==</FileContentHash>
|
||||
<FileContentHash>KjvOcFWd++tbnsEMfVPd/w==</FileContentHash>
|
||||
<FileVersion></FileVersion>
|
||||
<Name>templates/main.c</Name>
|
||||
<SelectString>Main file (.c)</SelectString>
|
||||
<SourcePath></SourcePath>
|
||||
</d4p1:anyType>
|
||||
<d4p1:anyType i:type="FileInfo">
|
||||
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.2.118\templates\main.cpp</AbsolutePath>
|
||||
<AbsolutePath>D:/Programs\Atmelstudio\7.0\Packs\atmel\ATtiny_DFP\1.8.332\templates\main.cpp</AbsolutePath>
|
||||
<Attribute>template</Attribute>
|
||||
<Category>source</Category>
|
||||
<Condition>C Exe</Condition>
|
||||
<FileContentHash>YXFphlh0CtZJU+ebktABgQ==</FileContentHash>
|
||||
<FileContentHash>mkKaE95TOoATsuBGv6jmxg==</FileContentHash>
|
||||
<FileVersion></FileVersion>
|
||||
<Name>templates/main.cpp</Name>
|
||||
<SelectString>Main file (.cpp)</SelectString>
|
||||
<SourcePath></SourcePath>
|
||||
</d4p1:anyType>
|
||||
<d4p1:anyType i:type="FileInfo">
|
||||
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.2.118\gcc\dev\attiny85</AbsolutePath>
|
||||
<AbsolutePath>D:/Programs\Atmelstudio\7.0\Packs\atmel\ATtiny_DFP\1.8.332\gcc\dev\attiny85</AbsolutePath>
|
||||
<Attribute></Attribute>
|
||||
<Category>libraryPrefix</Category>
|
||||
<Condition>GCC</Condition>
|
||||
|
@ -71,8 +71,8 @@
|
|||
</d4p1:anyType>
|
||||
</Files>
|
||||
<PackName>ATtiny_DFP</PackName>
|
||||
<PackPath>C:/Program Files (x86)/Atmel/Studio/7.0/Packs/atmel/ATtiny_DFP/1.2.118/Atmel.ATtiny_DFP.pdsc</PackPath>
|
||||
<PackVersion>1.2.118</PackVersion>
|
||||
<PackPath>D:/Programs/Atmelstudio/7.0/Packs/atmel/ATtiny_DFP/1.8.332/Atmel.ATtiny_DFP.pdsc</PackPath>
|
||||
<PackVersion>1.8.332</PackVersion>
|
||||
<PresentInProject>true</PresentInProject>
|
||||
<ReferenceConditionId>ATtiny85</ReferenceConditionId>
|
||||
<RteComponents xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
|
||||
|
|
|
@ -27,24 +27,24 @@
|
|||
<BootSegment>2</BootSegment>
|
||||
<eraseonlaunchrule>0</eraseonlaunchrule>
|
||||
<AsfFrameworkConfig>
|
||||
<framework-data xmlns="">
|
||||
<framework-data>
|
||||
<options />
|
||||
<configurations />
|
||||
<files />
|
||||
<documentation help="" />
|
||||
<offline-documentation help="" />
|
||||
<dependencies>
|
||||
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.34.1" />
|
||||
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.42.0" />
|
||||
</dependencies>
|
||||
</framework-data>
|
||||
</AsfFrameworkConfig>
|
||||
<avrtool>com.atmel.avrdbg.tool.stk500</avrtool>
|
||||
<avrtool>com.atmel.avrdbg.tool.simulator</avrtool>
|
||||
<avrtoolserialnumber />
|
||||
<avrdeviceexpectedsignature>0x1E930B</avrdeviceexpectedsignature>
|
||||
<com_atmel_avrdbg_tool_stk500>
|
||||
<ToolOptions>
|
||||
<InterfaceProperties>
|
||||
<IspClock>125000</IspClock>
|
||||
<IspClock>0</IspClock>
|
||||
</InterfaceProperties>
|
||||
<InterfaceName>ISP</InterfaceName>
|
||||
</ToolOptions>
|
||||
|
@ -54,12 +54,25 @@
|
|||
<ToolName>STK500</ToolName>
|
||||
</com_atmel_avrdbg_tool_stk500>
|
||||
<avrtoolinterface>ISP</avrtoolinterface>
|
||||
<avrtoolinterfaceclock>125000</avrtoolinterfaceclock>
|
||||
<avrtoolinterfaceclock>0</avrtoolinterfaceclock>
|
||||
<ResetRule>0</ResetRule>
|
||||
<EraseKey />
|
||||
<com_atmel_avrdbg_tool_simulator>
|
||||
<ToolOptions xmlns="">
|
||||
<InterfaceProperties>
|
||||
</InterfaceProperties>
|
||||
<InterfaceName>ISP</InterfaceName>
|
||||
</ToolOptions>
|
||||
<ToolType xmlns="">com.atmel.avrdbg.tool.simulator</ToolType>
|
||||
<ToolNumber xmlns="">
|
||||
</ToolNumber>
|
||||
<ToolName xmlns="">Simulator</ToolName>
|
||||
</com_atmel_avrdbg_tool_simulator>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<ToolchainSettings>
|
||||
<AvrGcc>
|
||||
<avrgcc.common.Device>-mmcu=attiny85 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\gcc\dev\attiny85"</avrgcc.common.Device>
|
||||
<avrgcc.common.Device>-mmcu=attiny85 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.8.332\gcc\dev\attiny85"</avrgcc.common.Device>
|
||||
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
|
||||
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
|
||||
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
|
||||
|
@ -74,7 +87,7 @@
|
|||
</avrgcc.compiler.symbols.DefSymbols>
|
||||
<avrgcc.compiler.directories.IncludePaths>
|
||||
<ListValues>
|
||||
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\include</Value>
|
||||
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.8.332\include\</Value>
|
||||
</ListValues>
|
||||
</avrgcc.compiler.directories.IncludePaths>
|
||||
<avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
|
||||
|
@ -88,7 +101,7 @@
|
|||
</avrgcc.linker.libraries.Libraries>
|
||||
<avrgcc.assembler.general.IncludePaths>
|
||||
<ListValues>
|
||||
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\include</Value>
|
||||
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.8.332\include\</Value>
|
||||
</ListValues>
|
||||
</avrgcc.assembler.general.IncludePaths>
|
||||
</AvrGcc>
|
||||
|
@ -97,7 +110,7 @@
|
|||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||
<ToolchainSettings>
|
||||
<AvrGcc>
|
||||
<avrgcc.common.Device>-mmcu=attiny85 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\gcc\dev\attiny85"</avrgcc.common.Device>
|
||||
<avrgcc.common.Device>-mmcu=attiny85 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.8.332\gcc\dev\attiny85"</avrgcc.common.Device>
|
||||
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
|
||||
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
|
||||
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
|
||||
|
@ -112,7 +125,7 @@
|
|||
</avrgcc.compiler.symbols.DefSymbols>
|
||||
<avrgcc.compiler.directories.IncludePaths>
|
||||
<ListValues>
|
||||
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\include</Value>
|
||||
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.8.332\include\</Value>
|
||||
</ListValues>
|
||||
</avrgcc.compiler.directories.IncludePaths>
|
||||
<avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level>
|
||||
|
@ -127,7 +140,7 @@
|
|||
</avrgcc.linker.libraries.Libraries>
|
||||
<avrgcc.assembler.general.IncludePaths>
|
||||
<ListValues>
|
||||
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.2.118\include</Value>
|
||||
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.8.332\include\</Value>
|
||||
</ListValues>
|
||||
</avrgcc.assembler.general.IncludePaths>
|
||||
<avrgcc.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcc.assembler.debugging.DebugLevel>
|
||||
|
|
|
@ -25,10 +25,12 @@ void led2_init(void)
|
|||
|
||||
void led1_stop(void)
|
||||
{
|
||||
DDRB &= ~(1<<PB1);
|
||||
TCCR1 &= ~(1<<COM1A0);
|
||||
}
|
||||
|
||||
void led2_stop(void)
|
||||
{
|
||||
DDRB &= ~(1<<PB4);
|
||||
GTCCR &= ~(1<<COM1B0);
|
||||
}
|
|
@ -11,7 +11,17 @@ void ADC_init(void)
|
|||
{
|
||||
DDRB &=~(1<<PB3); //Pin B3 en entree
|
||||
ADMUX |= (1<<MUX1)|(1<<MUX0)|(1<<ADLAR); //MUX = 0010 donc sortie PB4 et ADLAR a 1 pour avoir les bits de poids fort en premier
|
||||
ADCSRA |= (1<<ADEN)|(1<<ADPS2); //On divise 1Mhz par 16 (62.5 KHz) < 200 KHz, ADEN conversion autorisee
|
||||
ADCSRA|= (1<<ADEN)|(1<<ADPS2)|(1<<ADIE)|(1<<ADATE); //ADEN conversion autorisee
|
||||
//On divise 1Mhz par 16 (62.5 KHz) < 200 KHz
|
||||
//Interruptions autorisees
|
||||
//Auto-Trigger autorise
|
||||
ADCSRB &= ~(0b111<<ADTS0); //free-running mode
|
||||
sei();
|
||||
};
|
||||
|
||||
void ADC_start_conversion(void)
|
||||
{
|
||||
ADCSRA|=(1<<ADEN)|(1<<ADIE)|(1<<ADSC);
|
||||
};
|
||||
|
||||
char ADC_read_value(void)
|
||||
|
@ -21,13 +31,13 @@ char ADC_read_value(void)
|
|||
return ADCH;
|
||||
};
|
||||
|
||||
float ADC_averaging(void)
|
||||
float ADC_averaging(unsigned char val_ana)
|
||||
{
|
||||
float valeur_finale=0;
|
||||
char precision;
|
||||
for(precision = 75; precision > 0 ; precision --)
|
||||
{
|
||||
valeur_finale = valeur_finale +(((ADC_read_value() * 0.01961) - valeur_finale) / 15);
|
||||
valeur_finale = valeur_finale +(((val_ana * 0.01961) - valeur_finale) / 15);
|
||||
}
|
||||
return valeur_finale;
|
||||
};
|
||||
|
@ -35,30 +45,30 @@ float ADC_averaging(void)
|
|||
float measureLed1(void)
|
||||
{
|
||||
float adcLed;
|
||||
led2_stop();
|
||||
led1_init();
|
||||
_delay_ms(TIMING);
|
||||
adcLed=ADC_averaging();
|
||||
_delay_ms(TIMING);
|
||||
_delay_us(TIMING);
|
||||
adcLed=ADC_averaging(ADCH);
|
||||
_delay_us(TIMING);
|
||||
led1_stop();
|
||||
return adcLed;
|
||||
};
|
||||
|
||||
float measureLed2(void)
|
||||
{
|
||||
float adcLed;
|
||||
led1_stop();
|
||||
led2_init();
|
||||
_delay_ms(TIMING);
|
||||
adcLed=ADC_averaging();
|
||||
_delay_ms(TIMING);
|
||||
_delay_us(TIMING);
|
||||
adcLed=ADC_averaging(ADCH);
|
||||
_delay_us(TIMING);
|
||||
led2_stop();
|
||||
return adcLed;
|
||||
};
|
||||
|
||||
char compareLed(void)
|
||||
unsigned char compareLed(float led1,float led2)
|
||||
{
|
||||
float adcLed1 = measureLed1();
|
||||
float adcLed2 = measureLed2();
|
||||
float adcCompare = adcLed1 - adcLed2;
|
||||
float adcLed1 = led1;
|
||||
float adcLed2 = led2;
|
||||
float adcCompare = led1 - led2;
|
||||
if (adcCompare < -VOLTMIN) // adcLed2 > adcLed1
|
||||
{
|
||||
return LEFT;
|
||||
|
|
|
@ -10,8 +10,10 @@
|
|||
#define LED_RECEPTOR_H_
|
||||
|
||||
#include "led_gen.h"
|
||||
#define F_CPU 1000000
|
||||
#include "USI_TWI_Slave.h"
|
||||
#define F_CPU 8000000UL
|
||||
#include <util/delay.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#define FRONT 0x51
|
||||
#define RIGHT 0x52
|
||||
|
@ -19,13 +21,14 @@
|
|||
#define NOTHING 0x54
|
||||
#define ERROR 0xF0
|
||||
#define VOLTMIN 1
|
||||
#define TIMING 250
|
||||
#define TIMING 500
|
||||
|
||||
void ADC_init(void);
|
||||
void ADC_start_conversion(void);
|
||||
char ADC_read_value(void);
|
||||
float ADC_averaging(void);
|
||||
float ADC_averaging(unsigned char val_ana);
|
||||
float measureLed1(void);
|
||||
float measureLed2(void);
|
||||
char compareLed(void);
|
||||
unsigned char compareLed(float led1,float led2);
|
||||
|
||||
#endif /* LED_RECEPTOR_H_ */
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
void testLed(void)
|
||||
{
|
||||
char sendingData = compareLed();
|
||||
char sendingData = compareLed(5,5);
|
||||
switch(sendingData)
|
||||
{
|
||||
case NOTHING:
|
||||
|
|
|
@ -3,63 +3,78 @@
|
|||
*
|
||||
* Created: 12/11/2021 15:26:38
|
||||
* Author : 40008304
|
||||
*/
|
||||
*/
|
||||
|
||||
#if __GNUC__
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#else
|
||||
#include <inavr.h>
|
||||
#include <ioavr.h>
|
||||
#endif
|
||||
|
||||
#include "led_gen.h"
|
||||
#include "led_gen.h"
|
||||
#include "led_receptor.h"
|
||||
#include "led_test.h"
|
||||
#include "USI_TWI_Slave.h"
|
||||
|
||||
#define MSTR_TEST_WR 0x31
|
||||
#define MSTR_TEST_RE 0x32
|
||||
|
||||
#define SLAVE_ADRESS 0x01
|
||||
#define NOM_CONSTRUC 0x08
|
||||
#define NOM_CAPTEUR 0x10
|
||||
#define VALEUR_DEMAN 0x49
|
||||
#define BASIC_MODE 0x42
|
||||
|
||||
int main(void)
|
||||
volatile unsigned char rawVal;
|
||||
volatile float adcled1;
|
||||
volatile float adcled2;
|
||||
volatile unsigned char recVal;
|
||||
|
||||
ISR (ADC_vect){//On récupère les données à chaque fin de conversion Analogique/Numérique
|
||||
adcled1=measureLed1();
|
||||
adcled2=measureLed2();
|
||||
recVal=compareLed(adcled1,adcled2);
|
||||
}
|
||||
|
||||
int main( void )
|
||||
{
|
||||
unsigned char cmd, i, val;
|
||||
unsigned char nom_capteur[9]={'I','U','T','V','i','D','A','v'};
|
||||
unsigned char sensor_type[9]={'S','u','m','o','E','y','e','s'};
|
||||
USI_TWI_Slave_Initialise(SLAVE_ADRESS);
|
||||
led2_init();
|
||||
led1_init();
|
||||
unsigned char slaveAdress, cmd,i=0;
|
||||
unsigned char nom_capteur[8]= {'T','u','r','k','i','s','h','Z'};
|
||||
unsigned char sensor_type[8]= {'C','a','t','c','h','E','y','e'};
|
||||
slaveAdress = 0x01;
|
||||
|
||||
USI_TWI_Slave_Initialise(slaveAdress);
|
||||
sei();
|
||||
ADC_init();
|
||||
while (1)
|
||||
ADC_start_conversion();
|
||||
|
||||
while(1)
|
||||
{
|
||||
if( USI_TWI_Data_In_Receive_Buffer() )
|
||||
{
|
||||
cmd = USI_TWI_Receive_Byte();
|
||||
|
||||
switch(cmd){
|
||||
case MSTR_TEST_WR :
|
||||
val=USI_TWI_Receive_Byte();
|
||||
break;
|
||||
|
||||
case MSTR_TEST_RE :
|
||||
USI_TWI_Transmit_Byte(0x0F);
|
||||
break;
|
||||
|
||||
case NOM_CONSTRUC :
|
||||
for (i=0;i<8;i++){USI_TWI_Transmit_Byte(nom_capteur[i]);}
|
||||
break;
|
||||
case NOM_CAPTEUR :
|
||||
for (i=0;i<8;i++){USI_TWI_Transmit_Byte(sensor_type[i]);}
|
||||
break;
|
||||
|
||||
case VALEUR_DEMAN :
|
||||
USI_TWI_Transmit_Byte(0x45);
|
||||
break;
|
||||
case BASIC_MODE :
|
||||
USI_TWI_Transmit_Byte(0x46);
|
||||
break;
|
||||
};
|
||||
};
|
||||
};
|
||||
val++;
|
||||
}
|
||||
if( USI_TWI_Data_In_Receive_Buffer() )
|
||||
{
|
||||
cmd = USI_TWI_Receive_Byte();
|
||||
switch(cmd)
|
||||
{
|
||||
case NOM_CONSTRUC :
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
USI_TWI_Transmit_Byte(nom_capteur[i]);
|
||||
}
|
||||
break;
|
||||
|
||||
case NOM_CAPTEUR :
|
||||
for (i=0; i<8; i++)
|
||||
{
|
||||
USI_TWI_Transmit_Byte(sensor_type[i]);
|
||||
}
|
||||
break;
|
||||
|
||||
case VALEUR_DEMAN :
|
||||
USI_TWI_Transmit_Byte(recVal);
|
||||
break;
|
||||
|
||||
case BASIC_MODE :
|
||||
USI_TWI_Transmit_Byte(0x46);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue