Sunday, May 26, 2013

IR remote emulator with Attiny45, C source code


This code is from project: IR remote emulator with attiny45

USI_TWI_Slave.h

// This file has been prepared for Doxygen automatic documentation generation.
/*! \file ********************************************************************
*
* Atmel Corporation
*
* File              : USI_TWI_Slave.h
* Compiler          : IAR EWAAVR 4.11A
* Revision          : $Revision: 1.14 $
* Date              : $Date: Friday, December 09, 2005 17:25:38 UTC $
* Updated by        : $Author: jtyssoe $
*
* Support mail      : avr@atmel.com
*
* Supported devices : All device with USI module can be used.
*                     The example is written for the ATmega169, ATtiny26 & ATtiny2313
*
* AppNote           : AVR312 - Using the USI module as a TWI slave
*
* Description       : Header file for USI_TWI driver
*
*
*
****************************************************************************/
#include <avr/io.h>        // HC-ADDED
#include <avr/interrupt.h> // HC-ADDED
//! Prototypes
void          USI_TWI_Slave_Initialise( unsigned char );
void          USI_TWI_Transmit_Byte( unsigned char );
unsigned char USI_TWI_Receive_Byte( void );
unsigned char USI_TWI_Data_In_Receive_Buffer( void );
void          Timer_Init(void);

#define TRUE                1
#define FALSE               0

typedef     unsigned char       uint8_t;

//////////////////////////////////////////////////////////////////
///////////////// Driver Buffer Definitions //////////////////////
//////////////////////////////////////////////////////////////////
// 1,2,4,8,16,32,64,128 or 256 bytes are allowed buffer sizes

#define TWI_RX_BUFFER_SIZE  (16)
#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

// 1,2,4,8,16,32,64,128 or 256 bytes are allowed buffer sizes

#define TWI_TX_BUFFER_SIZE  (16)
#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



#define USI_SLAVE_CHECK_ADDRESS                (0x00)
#define USI_SLAVE_SEND_DATA                    (0x01)
#define USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA (0x02)
#define USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA   (0x03)
#define USI_SLAVE_REQUEST_DATA                 (0x04)
#define USI_SLAVE_GET_DATA_AND_SEND_ACK        (0x05)


//! Device dependent defines
#if defined(__AT90tiny26__) | defined(__ATtiny26__)
    #define DDR_USI             DDRB
    #define PORT_USI            PORTB
    #define PIN_USI             PINB
    #define PORT_USI_SDA        PORTB0
    #define PORT_USI_SCL        PORTB2
    #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(__AT90Tiny2313__) | defined(__ATtiny2313__)
    #define DDR_USI             DDRB
    #define PORT_USI            PORTB
    #define PIN_USI             PINB
    #define PORT_USI_SDA        PORTB5
    #define PORT_USI_SCL        PORTB7
    #define PIN_USI_SDA         PINB5
    #define PIN_USI_SCL         PINB7
    #define USI_START_COND_INT  USISIF
    #define USI_START_VECTOR    USI_STRT_vect
    #define USI_OVERFLOW_VECTOR USI_OVF_vect
#endif

#if defined(__ATtiny25__) | defined(__ATtiny45__) | defined(__ATtiny85__)
    #define DDR_USI             DDRB
    #define PORT_USI            PORTB
    #define PIN_USI             PINB
    #define PORT_USI_SDA        PORTB0
    #define PORT_USI_SCL        PORTB2
    #define PIN_USI_SDA         PINB0
    #define PIN_USI_SCL         PINB2
//     #define USI_START_COND_INT  USICIF
    #define USI_START_COND_INT  USISIF   // HC-CHANGED

    #define USI_START_VECTOR    USI_START_vect
    #define USI_OVERFLOW_VECTOR USI_OVF_vect
#endif

#if defined(__AT90Mega165__) | defined(__ATmega165__) | \
    defined(__ATmega325__) | defined(__ATmega3250__) | \
    defined(__ATmega645__) | defined(__ATmega6450__) | \
    defined(__ATmega329__) | defined(__ATmega3290__) | \
    defined(__ATmega649__) | defined(__ATmega6490__)
    #define DDR_USI             DDRE
    #define PORT_USI            PORTE
    #define PIN_USI             PINE
    #define PORT_USI_SDA        PORTE5
    #define PORT_USI_SCL        PORTE4
    #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(__AT90Mega169__) | defined(__ATmega169__)
    #define DDR_USI             DDRE
    #define PORT_USI            PORTE
    #define PIN_USI             PINE
    #define PORT_USI_SDA        PORTE5
    #define PORT_USI_SCL        PORTE4
    #define PIN_USI_SDA         PINE5
    #define PIN_USI_SCL         PINE4
    #define USI_START_COND_INT  USISIF
    #define USI_START_VECTOR    USI_STRT_vect
    #define USI_OVERFLOW_VECTOR USI_OVF_vect
#endif

//! Functions implemented as macros
#define SET_USI_TO_SEND_ACK()                                                                                 \
{                                                                                                             \
        USIDR    =  0;                                              /* Prepare ACK                         */ \
        DDR_USI |=  (1<<PORT_USI_SDA);                              /* Set SDA as output                   */ \
        USISR    =  (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|  /* Clear all flags, except Start Cond  */ \
                    (0x0E<<USICNT0);                                /* set USI counter to shift 1 bit. */ \
}

#define SET_USI_TO_READ_ACK()                                                                                 \
{                                                                                                             \
        DDR_USI &=  ~(1<<PORT_USI_SDA);                             /* Set SDA as intput */                   \
        USIDR    =  0;                                              /* Prepare ACK        */                  \
        USISR    =  (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|  /* Clear all flags, except Start Cond  */ \
                    (0x0E<<USICNT0);                                /* set USI counter to shift 1 bit. */ \
}

#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);                                                                                                     \
}

#define SET_USI_TO_SEND_DATA()                                                                               \
{                                                                                                            \
    DDR_USI |=  (1<<PORT_USI_SDA);                                  /* Set SDA as output                  */ \
    USISR    =  (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|      /* Clear all flags, except Start Cond */ \
                (0x0<<USICNT0);                                     /* set USI to shift out 8 bits        */ \
}

#define SET_USI_TO_READ_DATA()                                                                               \
{                                                                                                            \
    DDR_USI &= ~(1<<PORT_USI_SDA);                                  /* Set SDA as input                   */ \
    USISR    =  (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|      /* Clear all flags, except Start Cond */ \
                (0x0<<USICNT0);                                     /* set USI to shift out 8 bits        */ \
}

USI_TWI_Slave.c

// This file has been prepared for Doxygen automatic documentation generation.
/*! \file ********************************************************************
*
* Atmel Corporation
*
* File              : USI_TWI_Slave.c
* Compiler          : IAR EWAAVR 4.11A
* Revision          : $Revision: 1.14 $
* Date              : $Date: Friday, December 09, 2005 17:25:38 UTC $
* Updated by        : $Author: jtyssoe $
*
* Support mail      : avr@atmel.com
*
* Supported devices : All device with USI module can be used.
*
* AppNote           : AVR312 - Using the USI module as a I2C slave
*
* Description       : Functions for USI_TWI_receiver and USI_TWI_transmitter.
*
*
****************************************************************************/

// #include <ioavr.h>      // HC-REMOVED
// #include <inavr.h>      // HC-REMOVED
#include "USI_TWI_Slave.h"

/*! Static Variables
 */

static unsigned char TWI_slaveAddress;
static volatile unsigned char USI_TWI_Overflow_State;


/*! Local variables
 */
static uint8_t TWI_RxBuf[TWI_RX_BUFFER_SIZE];
static volatile uint8_t TWI_RxHead;
static volatile uint8_t TWI_RxTail;

static uint8_t TWI_TxBuf[TWI_TX_BUFFER_SIZE];
static volatile uint8_t TWI_TxHead;
static volatile uint8_t TWI_TxTail;

/*! \brief Flushes the TWI buffers
 */
void Flush_TWI_Buffers(void)
{
    TWI_RxTail = 0;
    TWI_RxHead = 0;
    TWI_TxTail = 0;
    TWI_TxHead = 0;
}

//********** USI_TWI functions **********//

/*! \brief
 * Initialise USI for TWI Slave mode.
 */
void USI_TWI_Slave_Initialise( unsigned char TWI_ownAddress )
{
  Flush_TWI_Buffers();

  TWI_slaveAddress = 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);                                 // Set SCL as output
  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
                                                                  // to first Start Condition (potentail failure)
              (1<<USICS1)|(0<<USICS0)|(0<<USICLK)|                // Shift Register Clock Source = External, positive edge
              (0<<USITC);
  USISR    = 0xF0;                                                // Clear all flags and reset overflow counter
}


/*! \brief Puts data in the transmission buffer, Waits if buffer is full.
*/
void USI_TWI_Transmit_Byte( unsigned char data )
{
    unsigned char tmphead;

    tmphead = ( TWI_TxHead + 1 ) & TWI_TX_BUFFER_MASK;         // Calculate buffer index.
    while ( tmphead == TWI_TxTail );                           // Wait for free space in buffer.
    TWI_TxBuf[tmphead] = data;                                 // Store data in buffer.
    TWI_TxHead = tmphead;                                      // Store new index.
}

/*! \brief Returns a byte from the receive buffer. Waits if buffer is empty.
 */
unsigned char USI_TWI_Receive_Byte( void )
{
    unsigned char tmptail;
    unsigned char tmpRxTail;                                  // Temporary variable to store volatile
    tmpRxTail = TWI_RxTail;                                   // Not necessary, but prevents warnings
    while ( TWI_RxHead == tmpRxTail );
    tmptail = ( TWI_RxTail + 1 ) & TWI_RX_BUFFER_MASK;        // Calculate buffer index
    TWI_RxTail = tmptail;                                     // Store new index
    return TWI_RxBuf[tmptail];                                // Return data from the buffer.
}

/*! \brief Check if there is data in the receive buffer.
 */
unsigned char USI_TWI_Data_In_Receive_Buffer( void )
{
    unsigned char tmpRxTail;                            // Temporary variable to store volatile
    tmpRxTail = TWI_RxTail;                             // Not necessary, but prevents warnings
    return ( TWI_RxHead != tmpRxTail );                 // Return 0 (FALSE) if the receive buffer is empty.
}

/*! \brief Usi start condition ISR
 * Detects the USI_TWI Start Condition and intialises the USI
 * for reception of the "TWI Address" packet.
 */


// HC-REMOVED
// #pragma vector=USI_START_VECTOR
// __interrupt void USI_Start_Condition_ISR(void)
SIGNAL(SIG_USI_START)
{
    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;
    DDR_USI  &= ~(1<<PORT_USI_SDA);                                 // Set SDA as input


    while ( (PIN_USI & (1<<PORT_USI_SCL)) & !(tmpUSISR & (1<<USIPF)) );   // Wait for SCL to go low to ensure the "Start Condition" has completed.
                                                                       // If a Stop condition arises then leave the interrupt to prevent waiting forever.
    USICR   =   (1<<USISIE)|(1<<USIOIE)|                            // Enable Overflow and Start Condition Interrupt. (Keep StartCondInt to detect RESTART)
                (1<<USIWM1)|(1<<USIWM0)|                            // Set USI in Two-wire mode.
                (1<<USICS1)|(0<<USICS0)|(0<<USICLK)|                // Shift Register Clock Source = External, positive edge
                (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.
}


/*! \brief USI counter overflow ISR
 * Handels all the comunication. Is disabled only when waiting
 * for new Start Condition.
 */

// HC-REMOVED
// #pragma vector=USI_OVERFLOW_VECTOR
// __interrupt void USI_Counter_Overflow_ISR(void)
SIGNAL(SIG_USI_OVERFLOW)
{
  unsigned char tmpTxTail;     // Temporary variables to store volatiles
  unsigned char tmpUSIDR;

  switch (USI_TWI_Overflow_State)
  {
    // ---------- 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 ) == TWI_slaveAddress))
      {
        if ( USIDR & 0x01 )
          USI_TWI_Overflow_State = USI_SLAVE_SEND_DATA;
        else
        {
          USI_TWI_Overflow_State = USI_SLAVE_REQUEST_DATA;
          SET_USI_TO_SEND_ACK();
        }
      }
      else
      {
        SET_USI_TO_TWI_START_CONDITION_MODE();
      }
      break;

    // ----- Master write data mode ------
    // Check reply and goto USI_SLAVE_SEND_DATA if OK, else reset USI.
    case USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA:
      if ( USIDR ) // If NACK, the master does not want more data.
      {
        SET_USI_TO_TWI_START_CONDITION_MODE();
        return;
      }
      // 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
      tmpTxTail = TWI_TxTail;           // Not necessary, but prevents warnings
      if ( TWI_TxHead != tmpTxTail )
      {
        TWI_TxTail = ( TWI_TxTail + 1 ) & TWI_TX_BUFFER_MASK;
        USIDR = TWI_TxBuf[TWI_TxTail];
      }
      else // If the buffer is empty then:
      {
          SET_USI_TO_TWI_START_CONDITION_MODE();
          return;
      }
      USI_TWI_Overflow_State = USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA;
      SET_USI_TO_SEND_DATA();
      break;

    // Set USI to sample reply from master. Next USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA
    case USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA:
      USI_TWI_Overflow_State = USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA;
      SET_USI_TO_READ_ACK();
      break;

    // ----- Master read data mode ------
    // Set USI to sample data from master. Next USI_SLAVE_GET_DATA_AND_SEND_ACK.
    case USI_SLAVE_REQUEST_DATA:
      USI_TWI_Overflow_State = USI_SLAVE_GET_DATA_AND_SEND_ACK;
      SET_USI_TO_READ_DATA();
      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
      tmpUSIDR = USIDR;             // Not necessary, but prevents warnings
      TWI_RxHead = ( TWI_RxHead + 1 ) & TWI_RX_BUFFER_MASK;
      TWI_RxBuf[TWI_RxHead] = tmpUSIDR;

      USI_TWI_Overflow_State = USI_SLAVE_REQUEST_DATA;
      SET_USI_TO_SEND_ACK();
      break;
  }
}

delay.h

#ifndef _H_DELAY_
#define _H_DELAY_

#define nop()  __asm__ __volatile__("nop")

void delay_ms(unsigned short ms);
void delay_us(unsigned short us);

#endif

delay.c

#include "main.h"
#include <util/delay.h>

#include "delay.h"

/****************************************************************************/
/* It is better to put a delay in the loop than provide high value to       */
/* standard function, because the code will be smaller,                     */
/****************************************************************************/
void delay_ms(unsigned short ms) {
    while ( ms ) {
      ms--;
      _delay_ms(1);
   }
}

void delay_us(unsigned short us) {
    while ( us ) {
      us--;
      _delay_us(1);
   }
}

main.h

#ifndef _H_MAIN_H
#define _H_MAIN_H

// define CPU speed
#define F_CPU 8000000L

// some usefeuul macros
#define H(a,b) a |=(1<<(b))
#define L(a,b) a &=~(1<<(b))
#define IS(a,b) bit_is_set(a,b)
#define BS(a,b) (a & (1<<(b)))

#endif

main.c

#include "main.h"

#include <avr/io.h>
#include <avr/interrupt.h>

#include "delay.h"
#include "USI_TWI_Slave.h"

// command array size
#define COMM_COUNT 18

// init data with device code
const unsigned char init[]       = { 0b11111111,  0b11111111,  0b00000000,  0b10101010,  0b00100010,  0b00100010,  0b10001000, 0b10001010, 0b10101000 };

// commands
const unsigned char on[]         = { 0b10001000,  0b10001000,  0b10101010,  0b10101010,  0b10001000,  0b10001000,  0b10000000 };
const unsigned char mute[]       = { 0b10101000,  0b10001000,  0b10101000,  0b10001000,  0b10101010,  0b00100010,  0b10000000 };
const unsigned char volUp[]      = { 0b10100010,  0b00100010,  0b00101010,  0b10001010,  0b10101000,  0b10001000,  0b10000000 };
const unsigned char volDown[]    = { 0b10001000,  0b10001000,  0b10001010,  0b10101010,  0b10101000,  0b10001000,  0b10000000 };
const unsigned char play[]       = { 0b10100010,  0b10101010,  0b10100010,  0b10001000,  0b10001000,  0b10001000,  0b10000000 };
const unsigned char next[]       = { 0b10001000,  0b10101010,  0b10101010,  0b10001000,  0b10001000,  0b10001000,  0b10000000 };
const unsigned char prev[]       = { 0b10101000,  0b10101010,  0b10100010,  0b00101000,  0b10001000,  0b10001000,  0b10000000 };
const unsigned char stop[]       = { 0b10001010,  0b10101010,  0b10101000,  0b10001000,  0b10001000,  0b10001000,  0b10000000 };
const unsigned char portable[]   = { 0b10001000,  0b10001000,  0b10001010,  0b00100010,  0b10101010,  0b10001010,  0b10000000 };
const unsigned char cd[]         = { 0b10100010,  0b10001010,  0b10001010,  0b00101000,  0b10100010,  0b00101000,  0b10000000 };
const unsigned char tuner[]      = { 0b10001000,  0b10100010,  0b10100010,  0b10101000,  0b10100010,  0b00101000,  0b10000000 };
const unsigned char usb[]        = { 0b10001010,  0b10001010,  0b00101010,  0b10001000,  0b10100010,  0b10001000,  0b10000000 };
const unsigned char pre_left[]   = { 0b10101000,  0b10001000,  0b10101010,  0b00100010,  0b10101000,  0b10001000,  0b10000000 };
const unsigned char pre_right[]  = { 0b10001000,  0b10100010,  0b00101010,  0b10101000,  0b10101000,  0b10001000,  0b10000000 };
const unsigned char fldr_up[]    = { 0b10001000,  0b10001010,  0b10001010,  0b10101010,  0b00100010,  0b10001000,  0b10000000 };
const unsigned char fldr_down[]  = { 0b10101010,  0b00101000,  0b10101000,  0b10001000,  0b10100010,  0b10001000,  0b10000000 };
const unsigned char shuffle[]    = { 0b10001000,  0b10001010,  0b10101010,  0b10101000,  0b10001000,  0b10001000,  0b10000000 };
const unsigned char repeat[]     = { 0b10101000,  0b10001010,  0b10101000,  0b10001010,  0b10001000,  0b10001000,  0b10000000 };

// commands array
// commands received by I2C are indexes from this table
const unsigned char *cmd_arr[COMM_COUNT] = { mute, volUp, volDown, on, play, next, prev, stop, portable, cd, usb, tuner, pre_left, pre_right, fldr_up, fldr_down, shuffle, repeat };


/****************************************************************************/
/* This function enables/disables interrupt generating ~36-38kHz square     */
/* wave on pin PB1. On/Off sequence is from byte (function parameter).      */
/****************************************************************************/
void sendOneByte(const unsigned char *byte) {
   unsigned char e = 7;

   do {
      if ( (*byte & (1<<e)) == (1<<e) ) {
         H(TIMSK, TOIE0);
      }
      else {
         L(TIMSK, TOIE0);
         L(PORTB, PB1);
      }
//       delay_us(410);
      delay_us(300); // time on my attiny45 runs slower, maybe
                     // I have broken crystal resonator, I don't know
                     // normally there should be 400-410 us
   } while(e--);
}


/****************************************************************************/
/* Function generate init sequence from init array.                         */
/****************************************************************************/
void initSequence() {
   unsigned char i = 0;

   for(i=0; i < 9; i++)
      sendOneByte(&init[i]);
}


/****************************************************************************/
/* Function sends IR command to device.                                     */
/****************************************************************************/
void command(const unsigned char *comm) {
   unsigned char i = 0;

   initSequence();

   for(i=0; i < 7; i++)
      sendOneByte(&comm[i]);
}


/****************************************************************************/
/* On every SIG_OVERFLOW0 there is a change on pin PB1. This generates      */
/* 36-38kHz square wave.                                                    */
/****************************************************************************/
SIGNAL(SIG_OVERFLOW0) {
   TCNT0 = 0xAC;
   PORTB^=(1<<PB1);
   return;
}


/****************************************************************************/
/* This is the main loop, it's not complicated, because we work on          */
/* interrupts.                                                              */
/****************************************************************************/
int main()
{
   unsigned char byte;

   // set device I2C address to 0x10
   USI_TWI_Slave_Initialise(0x10);

   // configure out pin for driving IR diode
   H(DDRB, PB1);
   L(PORTB, PB1);

   // configure timer
   L(TCCR0A, COM0A0);
   L(TCCR0A, COM0A1);
   H(TCCR0A, WGM01);
   H(TCCR0B, CS00);
   TCNT0 = 0xAC;

   // enable interrupts
   sei();

   while(1) {

      // something was received
      if( USI_TWI_Data_In_Receive_Buffer() ) {
         // get command code
         byte = USI_TWI_Receive_Byte();

        // check range (unsigned byte always > 0)
        if (byte < COMM_COUNT)
           command(cmd_arr[byte]);  // send IR command
      }
   }
}

Makefile

CPU=attiny45

GCC=avr-gcc
CFLAGS= -Os -mmcu=$(CPU) -Wall -fpack-struct -fshort-enums -funsigned-bitfields -Wl,--relax -fno-move-loop-invariants -funsigned-char -fno-inline-small-functions -fdata-sections -fno-tree-loop-optimize -lprintf_min 

INCLUDES=
LIBS=

OBJCPY=avr-objcopy
OBJECTS=main.o delay.o USI_TWI_Slave.o

PROJECT_NAME=infrared
HEX_FILE=$(PROJECT_NAME).hex
HEX_FILE_DUMP=$(PROJECT_NAME)_dump.hex

# this line shoud be replaced by your programmator
# I use simplest ISP by parallel port and bunch of 
# wires and resistors.
PROG=uisp
PROG_FLAGS=-dprog=dapa -dpart=attiny26

all: cls $(PROJECT_NAME) obj size #upload

$(PROJECT_NAME): $(OBJECTS)
  $(GCC) -o $(PROJECT_NAME) $(OBJECTS) $(CFLAGS) $(LIBS) $(INCLUDES)

main.o: main.c main.h 
  $(GCC) $(CFLAGS) $(INCLUDES) -c main.c

delay.o: delay.c delay.h
  $(GCC) $(CFLAGS) $(INCLUDES) -c delay.c

USI_TWI_Slave.o: USI_TWI_Slave.c USI_TWI_Slave.h
  $(GCC) $(CFLAGS) $(INCLUDES) -c USI_TWI_Slave.c -D__ATtiny45__

obj: $(OBJECTS)
  $(OBJCPY) -O ihex $(PROJECT_NAME) $(HEX_FILE)

clean:
  rm -f $(PROJECT_NAME) $(OBJECTS) $(HEX_FILE)

cls:
  clear

size:
  du -b $(HEX_FILE) 

upload: all $(HEX_FILE)
  $(PROG) $(PROG_FLAGS) --erase --upload if=$(HEX_FILE)

download:
  $(PROG) $(PROG_FLAGS) --download of=$(HEX_FILE_DUMP)

No comments:

Post a Comment