Rose-Hulman Robotics Team

Changeset 573 for trunk/electronics/avr

Show
Ignore:
Timestamp:
10/15/09 23:45:44 (2 years ago)
Author:
kleinjt
Message:

updated i2c slave code, added distance corrections, eeprom address settings, other fun feature-bloat

Location:
trunk/electronics/avr/i2c_irboard/i2c_slave
Files:
1 added
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/electronics/avr/i2c_irboard/i2c_slave/I2C_Slave.c

    r559 r573  
    3232 
    3333#include <avr/io.h> 
     34#include <avr/eeprom.h> 
    3435#include <avr/interrupt.h> 
    3536#include <avr/pgmspace.h> 
     
    3940#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) 
    4041 
     42// i2c commands 
     43#define RAW_ADC         ( 1 ) 
     44#define DISTANCE        ( 2 ) 
     45#define SETADDR         ( 3 ) 
     46#define READADDR        ( 4 ) 
     47#define SET_CORR        ( 5 ) 
     48#define ERROR           ( 0 )  
     49 
    4150uint16_t ADCIN(void); 
    42 uint16_t value; 
    43 uint16_t analog; 
     51uint8_t EEMEM slaveaddr = 0x26; 
     52uint16_t EEMEM EE_m = 6787; 
     53uint8_t EEMEM EE_b = 3; 
     54uint8_t EEMEM EE_k = 4; 
    4455 
    45  
    46 /* Brief: This section determines what format to return the value in. */ 
    47  
    48 enum { DATA1, DATA2, RAW }; 
    49  
    50 //----------------------------------------------------------------------------- 
    51  
    52 /* This section allows you to select between three different modes. In this sample 
    53 each return the value of the analog at different levels just to give an idea of how 
    54 it can be used. */ 
    55  
    56 void mode(uint8_t mode, uint8_t on) 
    57 { 
    58   analog = ADCIN(); 
    59   switch (mode) 
    60   { 
    61     case DATA1: if (on) (value = analog * 2); break; 
    62     case DATA2: if (on) (value = analog / 10); break; 
    63     case RAW:   if (on) (value = analog); break; 
    64   } 
     56uint8_t distance(uint16_t k, uint8_t m, uint8_t b) { 
     57  uint16_t analog = ADCIN(); 
     58  uint16_t distance = (m / (analog - b)) - k; 
     59  if(distance > 255) distance = 255; 
     60  if(distance < 0) distance = 0; 
     61  // http://www.acroname.com/robotics/info/articles/irlinear/irlinear.html  
     62  return analog; 
    6563} 
    6664 
    67 /* Brief: The main function. 
    68  * The program entry point. Initates TWI and enters eternal loop, waiting for data. 
    69  */ 
    7065int main(void) 
    7166{ 
    72   unsigned char slaveAddress, temp; 
    73  
     67  uint8_t temp; 
     68  uint16_t value; 
    7469  sei(); 
    7570 
     
    8378        cbi(DDRB, DDB1);        // pb1 set up as input 
    8479        cbi(DDRB, DDB3);        // pb3 set up as input 
    85 //   cbi(DDRB, DDB5);           // pb5 set up as input (use only in production, wipes out reset pin) 
    8680        sbi(PORTB, PB1);                // Set pb1 internal pullup 
    8781        sbi(PORTB, PB3);                // Set pb3 internal pullup 
    88 //       sbi(PORTB, PB5);               // (use only in production, wipes out reset pin) 
    89  
    90   slaveAddress = 0x26;          // This can be change to your own address 
    9182 
    9283 
    93   usiTwiSlaveInit(slaveAddress); 
     84  uint16_t m = eeprom_read_word(&EE_m);   
     85  uint8_t b = eeprom_read_byte(&EE_b); 
     86  uint8_t k = eeprom_read_byte(&EE_k); 
    9487 
    95   // This loop runs forever. If the TWI Transceiver is busy the execution will 
    96   // just continue doing other operations. 
     88  usiTwiSlaveInit(eeprom_read_byte(&slaveaddr)); 
     89 
    9790  for(;;) 
    9891  { 
    99  
    100  
    10192    if(usiTwiDataInReceiveBuffer()) 
    10293    { 
     94     value = 1; 
    10395         temp = usiTwiReceiveByte(); 
    10496      switch (temp) 
    105        { 
    106            case 1: mode(DATA1, 1);   break;             // the case is selected by a single 
    107        case 2: mode(DATA2, 1);   break;         // digit in the master code. (1,2 or 3) 
    108        case 3: mode(RAW, 1);     break; 
    109        } 
     97      { 
     98           case RAW_ADC: 
     99             value = ADCIN() << 2; 
     100             break; 
     101       case SETADDR: 
     102         eeprom_write_byte(&slaveaddr, usiTwiReceiveByte()); 
     103         value = eeprom_read_byte(&slaveaddr); 
     104         break; 
     105       case DISTANCE: 
     106         value = distance(k, m, b); 
     107         break; 
     108       case READADDR: 
     109         value = eeprom_read_byte(&slaveaddr);       
     110         break; 
     111       case SET_CORR: 
     112         while(!usiTwiDataInReceiveBuffer()); 
     113         m = usiTwiReceiveByte(); 
     114         m = m << 8; 
     115         while(!usiTwiDataInReceiveBuffer()); 
     116         m = m | usiTwiReceiveByte(); 
     117         eeprom_write_word(&EE_m, m); 
     118         while(!usiTwiDataInReceiveBuffer()); 
     119         b = usiTwiReceiveByte(); 
     120         eeprom_write_byte(&EE_b, b); 
     121         while(!usiTwiDataInReceiveBuffer()); 
     122         k = usiTwiReceiveByte(); 
     123         eeprom_write_byte(&EE_k, k); 
     124       default: 
     125         value = ERROR; 
     126         break; 
     127      } 
    110128 
    111129     usiTwiTransmitByte(value); 
    112130    } 
    113131 
    114     // Do something else while waiting for the TWI transceiver to complete. 
     132    asm volatile ("NOP" ::); // stall while waiting for the TWI transceiver to complete 
    115133 
    116     asm volatile ("NOP" ::); 
    117134  } 
    118135} 
    119  
    120 /* 
    121  *  ADCIN 
    122  * 
    123  *  Read the specified Analog to Digital Conversion channel 
    124  * 
    125  */ 
    126136 
    127137uint16_t ADCIN(void)