⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cc1000.c

📁 MANTIS是由科罗拉多大学开发的传感器网络嵌入式操作系统。 这是mantis的0.9.5版本的源码。
💻 C
📖 第 1 页 / 共 2 页
字号:
//  This file is part of MANTIS OS, Operating System//  See http://mantis.cs.colorado.edu/////  Copyright (C) 2003,2004,2005 University of Colorado, Boulder////  This program is free software; you can redistribute it and/or//  modify it under the terms of the mos license (see file LICENSE)/** @file cc1000.c * @brief Driver provides: use of cc1000 state machine, generic to most MACs * * Driver requires: AVR architecture with cc1000 connected via SPI bus. * @authors Jeff Rose, Brian Shucker, Hui Dai * @date 03/03/2004 * * This is a conglomeration of cc1000.c and cc1000_defaults.c.  We now integrate the SPI * code related to the radio data interface with the configuration code for the radio. [rosejn] */#define INTERRUPT_DRIVEN_SEND 1#include "mos.h"#include "com.h"#if defined(PLATFORM_MICA2) || defined(PLATFORM_MICA2DOT)#include "led.h"#include "sem.h"#include "crc.h"#include "cc1000.h"#include "cc1000_params.h"#include "clock.h"#include "msched.h"#include "mutex.h"#include "stdarg.h"#include "node_id.h"#include "avr-rssi.h"#include "uart.h"#if defined(CC1000) || !defined(SCONS)#ifdef RADIO_USE_FEC#include "fec.h"#endifstatic uint8_t int_handle;/*driver state info*/static comBuf *cc1000_recv_buf;  //receive bufferstatic comBuf *cc1000_send_buf;  //send buffervoid (*cc1000_state)(void);           //current sync state of receiveruint8_t cc1000_com_mode;        //current modestatic uint8_t spi_data;        //byte pulled off of SPI busstatic uint8_t prev_data;       //previous byte pulled off bus (for bit shift)static uint8_t offset;          //recv bit offsetstatic uint8_t preamble_count;  //preamble bytes receivedstatic uint8_t data_count;      //bytes already received or sentstatic uint8_t cc1000_crc_low, cc1000_crc_high; //crc storagestatic uint8_t actual_byte;//error trackinguint16_t cc1000_success_count;    //completed packetsuint16_t cc1000_crc_error_count;  //dropped packets due to crc erroruint16_t cc1000_mem_error_count;  //dropped packets due to out of memoryuint16_t cc1000_sync_error_count; //dropped packets due to sync failureuint16_t cc1000_size_error_count; //dropped packets due to size out of range#ifdef RADIO_USE_FECuint16_t cc1000_fec_error_count;  //dropped packets due to fec errors#endif//Enable the GET_RSSI and TS_PACKET switches from com.h//ANS hack:#ifdef GET_RSSIuint16_t rssival;#endif//ANS hack ends#ifdef INTERRUPT_DRIVEN_SENDstatic mos_sem_t cc1000_sem;          //to synchronize blocking on send#endif#ifdef RADIO_REDUNDANT_SIZEstatic uint8_t size_bytes[3];#endif#ifdef RADIO_USE_FECuint8_t data_fec[FEC_DATA_PARITY_COUNT];static void state_send_data_fec(void);static void state_recv_data_fec(void);#endifstatic void state_send_pre(void);static void state_send_sync(void);static void state_send_size(void);static void state_send_data(void);static void state_send_flush(void);static void state_send_crc_h(void);static void state_send_crc_l(void);static void state_send_done(void);static void state_recv_data(void);static void state_recv_crc_h(void);static void state_recv_crc_l(void);static void state_recv_size(void);// need reference to this for mac layersvoid state_recv_idle(void);static void state_recv_pre(void);/** @brief this initializes the error checking/correcting bytes * to be used in the mac layer. */inline void cc1000_init_ec (comBuf * sendPkt){   cc1000_send_buf = sendPkt;#ifdef RADIO_USE_FEC   fec_init (FEC_DATA_PARITY_COUNT);   fec_encode (sendPkt->data, sendPkt->size, data_fec);#else   //CRC Code   uint16_t crc;   //compute crc now, so we don't have to do it in interrupt handler   crc = crc_compute (sendPkt->data, sendPkt->size);   cc1000_crc_low = crc & 0x00FF;   cc1000_crc_high = (crc & 0xFF00) >> 8;#endif}/** @brief routine to start transmission */inline void cc1000_start_transmit(comBuf * sendPkt){   cc1000_init_ec(sendPkt);   cc1000_mode(CC1000_MODE_TX); //go to transmit mode   int_handle = mos_disable_ints();   cc1000_state = state_send_pre;       //init send state machine   preamble_count = 1;   SPDR = PREAMBLE_BYTE;        //start sending first preamble byte#ifdef INTERRUPT_DRIVEN_SEND   //INTERRUPT DRIVEN I/O   mos_single_threaded();   SPCR |= (1 << SPIE);         //turn on spi interrupt   //mos_led_display(1);   mos_enable_ints(int_handle);   mos_sem_wait(&cc1000_sem);   mos_multi_threaded();#else   //POLLING METHOD:   SPCR &= ~(1 << SPIE);        //turn off spi interrupt   while(cc1000_state != state_recv_idle) {      while(!(SPSR & (1 << SPIF)))         ;      cc1000_state();   }   mos_enable_ints(int_handle);#endif   if(cc1000_com_mode == IF_LISTEN) {      SPCR |= (1 << SPIE);      cc1000_mode(CC1000_MODE_RX);   }}/** @brief Sets mode for this driver. * @param md Mode * @return New mode set*/void com_mode_IFACE_RADIO (uint8_t md){   switch (md) {   case IF_OFF:      SPCR &= ~((1 << SPIE));     //disable spi interrupt      cc1000_mode (CC1000_MODE_PD);      cc1000_com_mode = md;      //TODO: could turn off radio here      break;   case IF_STANDBY:      break;   case IF_IDLE:      break;   case IF_LISTEN:      cc1000_state = state_recv_idle;   // Start recving in the idle state      cc1000_com_mode = md;      cc1000_mode (CC1000_MODE_RX);      SPCR |= (1 << SPIE);      //turn on spi interrupt      //TODO: might have to turn on radio here (see above)      break;   }}/** @brief Generic io control for this driver. * @param request i/o request * @param ap Arguements * @return Always returns 0*/void com_ioctl_IFACE_RADIO (uint8_t request, ...){   int arg;   uint8_t new_freq;   va_list ap;   va_start (ap, request);   switch (request) {   case CC1000_TX_POWER:       // Adjust transmit power      arg = va_arg (ap, int);      cc1000_set_power (arg);      break;   case CC1000_GET_TX_POWER: {      uint8_t* argp = va_arg (ap, uint8_t*);      *argp = cc1000_get_power();      break;   }   case CC1000_FREQ:           //set frequency      new_freq = va_arg (ap, int);      cc1000_change_freq(new_freq);      break;   case CC1000_RSSI:           // Get the received signal strength      // TODO: Get signal strength from dev layer, not as an ioctl      break;   }   va_end (ap);}void cc1000_default_init (void){   uint8_t int_handle;   int_handle = mos_disable_ints();      //get initial receive buffer   com_swap_bufs(IFACE_RADIO, NULL, &cc1000_recv_buf);#ifdef GET_RSSI   cc1000_recv_buf->signal = 0;#endif#ifdef TS_PACKET   cc1000_recv_buf->ts = 0;#endif   #ifdef INTERRUPT_DRIVEN_SEND   mos_sem_init(&cc1000_sem, 0);#endif      //init radio   cc1000_init(FREQ);   //now init the SPI bus   DDRB &= ~((1 << DDB0) | (1 << DDB1)); // clock pin to input   SPCR &= ~((1 << CPOL) | (1 << CPHA)); // Set proper polarity and phase   DDRB |= (1 << DDB3);                  //miso to output   DDRB &= ~((1 << DDB0) | (1 << DDB2)); //mosi to input   cc1000_mode(CC1000_MODE_RX);          //go to recv mode   SPCR &= ~(1 << SPIE); //disable SPI interrupt   SPCR |= (1 << SPE);      cc1000_state = state_recv_idle;   //initially in off mode   cc1000_com_mode = IF_OFF;   mos_enable_ints(int_handle);}static void state_send_pre(void){   SPDR = PREAMBLE_BYTE;   preamble_count++;   if(preamble_count == PREAMBLE_LEN)      cc1000_state = state_send_sync;}static void state_send_sync(void){     SPDR = 0x33;              //send sync byte   cc1000_state = state_send_size;   data_count = 0;}static void state_send_size(void){   SPDR = cc1000_send_buf->size;   #ifdef RADIO_REDUNDANT_SIZE   // Send redundant size bytes   if (data_count++ < 2)   	return;   #endif   data_count = 0;#ifdef RADIO_USE_FEC   //cc1000_state = STATE_SEND_SIZE_FEC;   cc1000_state = state_send_data;#else   cc1000_state = state_send_data;#endif   }static void state_send_data(void){   SPDR = cc1000_send_buf->data[data_count++];   if(data_count == cc1000_send_buf->size) {      //done with data      data_count = 0;#ifdef RADIO_USE_FEC      cc1000_state = state_send_data_fec;#else      cc1000_state = state_send_crc_h;#endif   }}#ifdef RADIO_USE_FECstatic void state_send_data_fec(void){   SPDR = data_fec[data_count++];   if(data_count == FEC_DATA_PARITY_COUNT)      cc1000_state = state_send_flush;}#endifstatic void state_send_crc_h(void){   SPDR = cc1000_crc_high;   cc1000_state = state_send_crc_l;}static void state_send_crc_l(void){   SPDR = cc1000_crc_low;   cc1000_state = state_send_flush;}static void state_send_flush(void){   SPDR = FLUSH_BYTE;   cc1000_state = state_send_done;}static void state_send_done(void){   //go back to recv mode   cc1000_state = state_recv_idle;#ifdef INTERRUPT_DRIVEN_SEND   mos_sem_post(&cc1000_sem);#endif}#ifdef RADIO_USE_FECstatic void state_recv_data_fec(void){   spi_data = SPDR;   data_fec[data_count++] = (prev_data << offset) | (spi_data >> (8 - offset));   if(data_count == FEC_DATA_PARITY_COUNT) {      cc1000_state = state_recv_idle;      com_swap_bufs(IFACE_RADIO, cc1000_recv_buf, &cc1000_recv_buf);   }   prev_data = spi_data;}#endifstatic void state_recv_crc_l(void){   //read low byte and assemble full crc   spi_data = SPDR;   cc1000_crc_low = (prev_data << offset) | (spi_data >> (8 - offset));   //if crc checks out, swap buffer up to com layer   if(crc_compute(cc1000_recv_buf->data, cc1000_recv_buf->size) ==      ((((uint16_t) cc1000_crc_high) << 8) | cc1000_crc_low)) {      //cc1000_state = state_recv_idle;      com_swap_bufs(IFACE_RADIO, cc1000_recv_buf, &cc1000_recv_buf);      cc1000_success_count++;   } else { //if it's bad, record the error      //mos_led_toggle(2);      cc1000_crc_error_count++;   }   //either way, we're done and back in idle mode   cc1000_state = state_recv_idle;}static void state_recv_crc_h(void){   spi_data = SPDR;   cc1000_crc_high = (prev_data << offset) | (spi_data >> (8 - offset));   //ready to recv low byte   cc1000_state = state_recv_crc_l;   prev_data = spi_data;}static void state_recv_data(void){   spi_data = SPDR;   actual_byte = (prev_data << offset) | (spi_data >> (8 - offset));   cc1000_recv_buf->data[data_count++] = actual_byte;      if (data_count == cc1000_recv_buf->size) {#ifdef RADIO_USE_FEC      data_count = 0;      cc1000_state = state_recv_data_fec;#else      cc1000_state = state_recv_crc_h;#endif   }      prev_data = spi_data;}static void state_recv_size(void){   spi_data = SPDR;   actual_byte = (prev_data << offset) | (spi_data >> (8 - offset));#ifdef RADIO_REDUNDANT_SIZE   // Received redundant size bytes   size_bytes[data_count] = actual_byte;   if (data_count++ < 2)      return;   // Majority rules   actual_byte = (size_bytes[0] & size_bytes[1]) |      (size_bytes[0] & size_bytes[2]) |      (size_bytes[1] & size_bytes[2]);#endif   if (actual_byte > COM_DATA_SIZE || actual_byte == 0) {      cc1000_size_error_count++;      cc1000_state = state_recv_idle;      return;   } else {      if (!cc1000_recv_buf) {	 com_swap_bufs (IFACE_RADIO, NULL, &cc1000_recv_buf);	 if (!cc1000_recv_buf) {	    cc1000_mem_error_count++;	    cc1000_state = state_recv_idle;	    return;	 }      }   }   data_count = 0;   cc1000_recv_buf->size = actual_byte;   cc1000_state = state_recv_data;   prev_data = spi_data;}static void state_recv_sync(void){   spi_data = SPDR;   // Figure out the bit offset by shifting until we find the sync byte   while (prev_data != 0x33) {      prev_data = (prev_data << 1) | (spi_data >> (7 - offset));      offset++;      if (offset >= 8) { //didn't get the sync byte... Something is wrong	 cc1000_sync_error_count++;	 cc1000_state = state_recv_idle;	 return;      }   }      // We are synced and ready to start getting the packet   cc1000_state = state_recv_size;   prev_data = spi_data;   data_count = 0;}static void state_recv_pre(void){   spi_data = SPDR;   if (spi_data != PREAMBLE_BYTE && spi_data != 0x55) {      // not in preamble anymore      if (preamble_count > PREAMBLE_THRESH) {	 // reached end of preamble	 cc1000_state = state_recv_sync;	 offset = 0;      } else {	 // looking at noise	 cc1000_state = state_recv_idle;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -