Microcontroller Wireless Solutions


pal_board.c
Go to the documentation of this file.
00001 
00011 /*
00012  * Copyright (c) 2009, Atmel Corporation All rights reserved.
00013  *
00014  * Licensed under Atmel's Limited License Agreement --> EULA.txt
00015  */
00016 
00017 /* === Includes ============================================================ */
00018 
00019 #include <stdbool.h>
00020 #include <stdlib.h>
00021 #include "pal.h"
00022 #include "pal_boardtypes.h"
00023 #include "pal_config.h"
00024 
00025 #if (BOARD_TYPE == RCB_6_3_PLAIN)
00026 
00032 /* === Macros ============================================================== */
00033 
00034 /* EEPROM command bytes */
00035 #define AT25010_CMD_WREN  0x06  
00036 #define AT25010_CMD_WRDI  0x04  
00037 #define AT25010_CMD_RDSR  0x05  
00038 #define AT25010_CMD_WRSR  0x01  
00039 #define AT25010_CMD_READ  0x03  
00040 #define AT25010_CMD_WRITE 0x02  
00042 /* EEPROM status register bits */
00043 #define AT25010_STATUS_NRDY 0x01 
00044 #define AT25010_STATUS_WE   0x02 
00045 #define AT25010_BP0         0x04 
00046 #define AT25010_BP1         0x08 
00048 /* Values for Feature Byte 1: RF frontend features */
00049 
00051 #define CFG_FEATURE1_RFCONN             0x01
00052 
00054 #define CFG_FEATURE1_ANTENNA            0x02
00055 
00057 #define CFG_FEATURE1_EXDIV              0x04
00058 
00060 #define CFG_FEATURE1_RESV3              0x08
00061 
00063 #define CFG_FEATURE1_PA                 0x10
00064 
00066 #define CFG_FEATURE1_LNA                0x20
00067 
00069 #define CFG_FEATURE1_RESV6              0x40
00070 
00072 #define CFG_FEATURE1_RESV7              0x80
00073 
00074 
00076 #define CFG_NAMELEN             (32 - sizeof(uint16_t))
00077 
00079 #define CFG_BINARYLEN           32
00080 
00081 #if (EXTERN_EEPROM_AVAILABLE == 1)
00082 #if defined(__GNUC__)
00083 #include <util/crc16.h>
00084 #define CRC_CCITT_UPDATE(crc, data) _crc_ccitt_update(crc, data)
00085 #endif /* defined(__GNUC__) */
00086 
00087 #if defined(__ICCAVR__)
00088 #define CRC_CCITT_UPDATE(crc, data) crc_ccitt_update(crc, data)
00089 /* Internal helper function for CRC_CCITT_UPDATE. */
00090 uint16_t crc_ccitt_update(uint16_t crc, uint8_t data);
00091 #endif /* __ICCAVR__ */
00092 #endif /* EXTERN_EEPROM_AVAILABLE */
00093 
00094 
00095 /* === Types =============================================================== */
00096 
00101 enum boardfamilycode
00102 {
00103     CFG_BFAMILY_RADIO_EXTENDER, 
00104     CFG_BFAMILY_RCB             
00105 } SHORTENUM;
00106 
00122 struct cfg_eeprom_data
00123 {
00124     union
00125     {
00127         uint8_t raw_binary[CFG_BINARYLEN];
00128 
00129         /* Structured access to binary configuration data. */
00130         struct
00131         {
00133             uint64_t mac_address;
00134 
00136             uint64_t serial_number;
00137 
00139             enum boardfamilycode board_family;
00140 
00142             uint8_t board_id[3];
00143 
00145             uint8_t feature1;
00146 
00148             uint8_t cal_16mhz;
00149 
00151             uint8_t cal_rc_36;
00152 
00154             uint8_t cal_rc_20;
00155 
00157             int8_t antenna_gain;
00158 
00159             /* 7 bytes reserved, leave as 0xFF */
00160         }
00161         struct_binary;
00162     }
00163     binary_data;
00164 
00166     char board_name[CFG_NAMELEN];
00167 
00169     uint16_t crc;
00170 };
00171 
00172 /* === Globals ============================================================= */
00173 
00174 
00175 /* === Prototypes ========================================================== */
00176 
00177 #if (EXTERN_EEPROM_AVAILABLE == 1) || defined(DOXYGEN)
00178 static uint8_t at25010_read_byte(uint8_t addr);
00179 static void at25010_spi_setup(void);
00180 static void at25010_spi_cleanup(void);
00181 static void extern_eeprom_init(void);
00182 #endif  /* #if (EXTERN_EEPROM_AVAILABLE == 1) || defined(DOXYGEN) */
00183 
00184 /* === Implementation ======================================================= */
00185 
00194 bool pal_calibrate_rc_osc(void)
00195 {
00196     /* Nothing to be done. */
00197     return true;
00198 }
00199 
00200 
00201 
00202 #if (EXTERN_EEPROM_AVAILABLE == 1) || defined(DOXYGEN)
00203 
00215 static void at25010_spi_setup(void)
00216 {
00217     /* Ensure /SS, SCK and MOSI become outputs. */
00218     DDRB |= _BV(PB0) | _BV(PB1) | _BV(PB2);
00219     /*
00220      * Set SPI speed very low to allow proper EEPROM reading
00221      * even with large capacitors on pins (e.g. for debugging
00222      * on Breakout Board light.
00223      * Here the SPI speed is put to fosc/128 by setting
00224      * SPR1 and SPR0 bit.
00225      */
00226     SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR1) | _BV(SPR0);
00227 }
00228 #endif  /* #if (EXTERN_EEPROM_AVAILABLE == 1) || defined(DOXYGEN) */
00229 
00230 
00231 
00232 #if (EXTERN_EEPROM_AVAILABLE == 1) || defined(DOXYGEN)
00233 
00239 static void at25010_spi_cleanup(void)
00240 {
00241     SPCR = 0;
00242     DDRB &= ~_BV(PB0);
00243 }
00244 #endif  /* #if (EXTERN_EEPROM_AVAILABLE == 1) || defined(DOXYGEN) */
00245 
00246 
00247 
00248 #if (EXTERN_EEPROM_AVAILABLE == 1) || defined(DOXYGEN)
00249 
00260 static uint8_t at25010_read_byte(uint8_t addr)
00261 {
00262     uint8_t read_value;
00263 
00264     EXT_EE_CS_PORT &= ~EXT_EE_CS_PIN;
00265 
00266     PAL_WAIT_1_US();
00267 
00268     SPDR = AT25010_CMD_READ;
00269     while ((SPSR & _BV(SPIF)) == 0)
00270         /* wait */;
00271     SPDR = addr & 0x7F; // mask out Bit 7 for 128x8 EEPROM
00272     while ((SPSR & _BV(SPIF)) == 0)
00273         /* wait */;
00274 
00275     SPDR = 0;   // dummy value to start SPI transfer
00276     while ((SPSR & _BV(SPIF)) == 0)
00277         /* wait */;
00278     read_value = SPDR;
00279 
00280     EXT_EE_CS_PORT |= EXT_EE_CS_PIN;
00281 
00282     return read_value;
00283 }
00284 #endif  /* #if (EXTERN_EEPROM_AVAILABLE == 1) || defined(DOXYGEN) */
00285 
00286 
00287 
00288 #if (EXTERN_EEPROM_AVAILABLE == 1) || defined(DOXYGEN)
00289 
00299 retval_t extern_eeprom_get(uint8_t start_offset, uint8_t length, void *value)
00300 {
00301     uint8_t i;
00302     struct cfg_eeprom_data cfg;
00303     uint8_t *up;
00304     uint16_t crc;
00305 
00306     // Read data from external EEPROM.
00307     at25010_spi_setup();
00308     for (i = 0, up = (uint8_t *)&cfg; i < sizeof(cfg); i++, up++)
00309     {
00310         *up = at25010_read_byte(i);
00311     }
00312     at25010_spi_cleanup();
00313 
00314     // Calcute CRC to validate data correctness
00315     for (i = 0, crc = 0, up = (uint8_t *)&cfg; i < sizeof(cfg); i++, up++)
00316     {
00317         crc = CRC_CCITT_UPDATE(crc, *up);
00318     }
00319     if (crc != 0)
00320     {
00321         return FAILURE;
00322     }
00323 
00324     /* Copy data from local cfg structure variable to target storage location */
00325     memcpy(value, ((uint8_t *)&cfg) + start_offset, length);
00326 
00327     return MAC_SUCCESS;
00328 }
00329 #endif  /* #if (EXTERN_EEPROM_AVAILABLE == 1) || defined(DOXYGEN) */
00330 
00331 
00332 
00333 #if defined(__ICCAVR__) || defined(DOXYGEN)
00334 /* This function is available in WINAVR library */
00347 #if (EXTERN_EEPROM_AVAILABLE == 1) || defined(DOXYGEN)
00348 uint16_t crc_ccitt_update(uint16_t crc, uint8_t data)
00349 {
00350     data ^= crc & 0xFF;
00351     data ^= data << 4;
00352 
00353     return ((((uint16_t)data << 8) | ((crc & 0xFF00) >> 8)) ^ \
00354             (uint8_t)(data >> 4) ^ \
00355             ((uint16_t)data << 3));
00356 }
00357 #endif /* #if (EXTERN_EEPROM_AVAILABLE == 1) || defined(DOXYGEN) */
00358 #endif /* __ICCAVR__ || defined(DOXYGEN) */
00359 
00360 
00361 
00365 void pal_led_init(void)
00366 {
00367     LED_PORT |= (1 << LED_PIN_0);
00368     LED_PORT_DIR |= (1 << LED_PIN_0);
00369     LED_PORT |= (1 << LED_PIN_1);
00370     LED_PORT_DIR |= (1 << LED_PIN_1);
00371     LED_PORT |= (1 << LED_PIN_2);
00372     LED_PORT_DIR |= (1 << LED_PIN_2);
00373 }
00374 
00375 
00376 
00383 void pal_led(led_id_t led_no, led_action_t led_setting)
00384 {
00385     switch (led_no)
00386     {
00387         default:
00388         case 0:
00389             switch (led_setting)
00390             {
00391                 case LED_ON:
00392                     LED_PORT &= ~(1 << LED_PIN_0);
00393                     break;
00394                 case LED_OFF:
00395                     LED_PORT |= (1 << LED_PIN_0);
00396                     break;
00397                 case LED_TOGGLE:
00398                     LED_PORT ^= (1 << LED_PIN_0);
00399                     break;
00400             }
00401             break;
00402 
00403         case 1:
00404             switch (led_setting)
00405             {
00406                 case LED_ON:
00407                     LED_PORT &= ~(1 << LED_PIN_1);
00408                     break;
00409                 case LED_OFF:
00410                     LED_PORT |= (1 << LED_PIN_1);
00411                     break;
00412                 case LED_TOGGLE:
00413                     LED_PORT ^= (1 << LED_PIN_1);
00414                     break;
00415             }
00416             break;
00417 
00418         case 2:
00419             switch (led_setting)
00420             {
00421                 case LED_ON:
00422                     LED_PORT &= ~(1 << LED_PIN_2);
00423                     break;
00424                 case LED_OFF:
00425                     LED_PORT |= (1 << LED_PIN_2);
00426                     break;
00427                 case LED_TOGGLE:
00428                     LED_PORT ^= (1 << LED_PIN_2);
00429                     break;
00430             }
00431             break;
00432     }
00433 }
00434 
00435 
00439 void pal_button_init(void)
00440 {
00441     BUTTON_PORT |= (1 << BUTTON_PIN_0);
00442     BUTTON_PORT_DIR &= ~(1 << BUTTON_PIN_0);
00443 }
00444 
00445 
00446 
00452 button_state_t pal_button_read(button_id_t button_no)
00453 {
00454     /* Keep compiler happy. */
00455     button_no = button_no;
00456 
00457     if ((BUTTON_INPUT_PINS & (1 << BUTTON_PIN_0)) == 0x00)
00458     {
00459         return BUTTON_PRESSED;
00460     }
00461     else
00462     {
00463         return BUTTON_OFF;
00464     }
00465 }
00466 
00467 
00471 void gpio_init(void)
00472 {
00473 #if (EXTERN_EEPROM_AVAILABLE == 1)
00474     extern_eeprom_init();
00475 #endif
00476 }
00477 
00478 
00479 #if (EXTERN_EEPROM_AVAILABLE == 1) || (defined DOXYGEN)
00480 
00486 static void extern_eeprom_init(void)
00487 {
00488     EXT_EE_CS_PORT |= EXT_EE_CS_PIN;
00489     EXT_EE_CS_DDR |= EXT_EE_CS_PIN;
00490 }
00491 #endif  /* #if (EXTERN_EEPROM_AVAILABLE == 1) || defined(DOXYGEN) */
00492 
00493 
00503 void pal_sleep_mode(uint8_t sleep_mode)
00504 {
00505     // Clear interrupt flag
00506     EIFR = (1 << INTF5);
00507     // Enable external interrupt
00508     EIMSK |= (1 << INT5);
00509 
00510 #ifdef WATCHDOG
00511     /* Switch watchdog system reset off while being in sleep mode */
00512     WDT_DISABLE();
00513 #endif
00514 
00515     /* Enter MCU sleep mode */
00516     SET_SLEEP_MODE(sleep_mode);
00517     SLEEP_MODE();
00518 
00519     /* Continue after wakeup */
00520 
00521 #ifdef WATCHDOG
00522     /* Enable the Watchdog system reset mode */
00523 #ifdef __ICCAVR__
00524     WDT_RESET();
00525     WDT_SYSTEM_RESET_MODE(WDT_TIMEOUT_PERIOD);
00526 #endif /* __ICCAVR__ */
00527 #ifdef __GNUC__
00528     wdt_disable();
00529     WDT_RESET();
00530     wdt_enable(WDT_TIMEOUT_PERIOD);
00531 #endif /* __GNUC__ */
00532 #endif
00533 }
00534 
00535 
00539 ISR(INT5_vect)
00540 {
00541     /* MCU wakeup */
00542     // Disable external interrupt
00543     EIMSK &= ~(1 << INT5);
00544 }
00545 
00546 
00549 #endif /* RCB_6_3_PLAIN */
00550 
00551 /* EOF */