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

📄 cc1000_tdma.c

📁 MANTIS是由科罗拉多大学开发的传感器网络嵌入式操作系统。 这是mantis的0.9.5版本的源码。
💻 C
字号:
//  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)/**   Project Mantis   File:   cc1000_tdma.c   Authors: Brian Shucker   Date:   03-18-04     This is a derivative of cc1000_raw.**//*TODO: This driver uses the SPI bus.  It is NOT compatible with the spi.c that's already  in the AVR kernel--they can't both be active at the same time.*//*TODO: we're still using cc1000.c that's in the share directory...that's bad!  There should  be a cc1000 low-level file that's bundled with this driver*/#include "mos.h"#include "com.h"#ifdef CC1000_TDMA#if defined(PLATFORM_MICA2) || defined(PLATFORM_MICA2DOT)#include "msched.h"#include "sem.h"#include "cc1000.h"#include "cc1000_tdma.h"#include "crc.h"#include "led.h"#include "clock.h"  //provides us usleep/** @brief seeing frame number */#define STATE_RECV_FRAMENO 20/** @brief Sending frame number */#define STATE_SEND_FRAMENO 21 //needed to edit the state machineextern uint8_t spi_data;extern uint8_t prev_data;extern uint8_t offset; //recv bit offsetextern uint8_t cc1000_com_mode;extern uint8_t cc1000_state;extern comBuf *cc1000_sendBuf;extern uint8_t preamble_count; //preamble bytes received//tdma-related#define FRAME_UNKNOWN 255 //id for an invalid frame#ifdef PLATFORM_MICA2 //clock at 7.3728MHz#define FRAME_COUNTS 5760 //frame length in clocks/64 (set to 50ms)#define FRAME_SYNC_OFFSET 900 //how far into frame 0 the sync strobe is located#endif#ifdef PLATFORM_NYMPH //clock at 4.0000MHz#define FRAME_COUNTS 3125 //frame length in clocks/64 (set to 50ms)#define FRAME_SYNC_OFFSET 488 //how far into frame 0 the sync strobe is located#endif#define FRAME_SYNC_OFFSET_US 7813extern mos_sem_t cc1000_sem;//tdma-relatedstatic uint8_t myFrame; //my frame numberstatic uint8_t curFrame; //current frame numberstatic uint8_t waiting; //true if waiting to sendstatic uint8_t strobing; //true if sending a strobe packetstatic uint8_t tmp;//alarm for timing#define FRAME_SIZE_US 50000static mos_alarm_t frame_alarm;static void frame_alarm_func(void *p);inline void tdma_state_machine();static mos_sem_t cc1000_sem;static uint8_t preamble_count;static uint8_t prev_data;static uint8_t offset;static uint8_t spi_data;static uint16_t sync_error_count;/*com layer required functions*//** Sends out a com buffer using this driver (blocking). * @param buf Buffer * @return Always returns 0*/uint8_t com_send_IFACE_RADIO (comBuf* buf){   uint8_t int_handle;   mos_mutex_lock (&if_send_mutexes[IFACE_RADIO]);      //if size is zero, we're done   if(buf->size == 0)      return 0;  //TODO: we could indicate an error here...   cc1000_init_ec(buf);//initialize error correction/checking      waiting = TRUE;//we have to wait until our frame   cc1000_mode(CC1000_MODE_RX);//we need to see strobe before sending   SPCR |= (1 << SPIE);//enable the spi device   //suspend thread until it is our turn (slot)   mos_sem_wait (&cc1000_sem);      cc1000_mode(CC1000_MODE_TX);//go to transmit mode to send the packet   int_handle = mos_disable_ints();         cc1000_state = state_send_pre; //init send state machine   SPDR = PREAMBLE_BYTE; //start sending first preamble byte   preamble_count = 1;   //INTERRUPT DRIVEN I/O//   SPCR |= (1 << SPIE); //turn on spi interrupt //   mos_enable_ints (int_handle);//   mos_sem_wait (&cc1000_sem);   //POLLING METHOD:   SPCR &= ~(1 << SPIE); //turn off spi interrupt   while (cc1000_state != STATE_RECV_IDLE) {      while (!(SPSR & (1 << SPIF)))	 ;      tdma_state_machine ();   }   mos_enable_ints (int_handle);      if(cc1000_com_mode == IF_LISTEN) { //turn back off if necessary      cc1000_mode(CC1000_MODE_RX);      SPCR |= (1 << SPIE);//enable the spi device   } else if (cc1000_com_mode == IF_OFF) {      cc1000_mode(CC1000_MODE_PD);   }   mos_mutex_unlock (&if_send_mutexes[IFACE_RADIO]);    return 0;}void cc1000_tdma_init(uint8_t id){   //set frame number   //TODO: should actually get this from base station, not count on app to have it   myFrame = id;   curFrame = FRAME_UNKNOWN;   waiting = FALSE;   strobing = FALSE;   //register with the com layer   //com_register_iface(IFACE_RADIO, cc1000_tdma_send,   //	      cc1000_cmode, cc1000_ioctl);      cc1000_default_init();   mos_sem_init (&cc1000_sem, 0);      //set up the frame clock   frame_alarm.func = frame_alarm_func;   if(id == 0) { //we are the base station, start the clock      curFrame = MAX_FRAMES - 1; //define our frame to be next      mos_alarm(&frame_alarm, 0, FRAME_SIZE_US);      //base station has to send the strobe even if it's mode is off,      //because other nodes might be on and need to sync.   }}static void frame_alarm_func(void *p){   boolean reset_alarm = true;   curFrame++;//advance to next frame number   if(curFrame == MAX_FRAMES) {      if(myFrame == 0) //I am the base station, just keep going	 curFrame = 0;      else {	 curFrame = FRAME_UNKNOWN; //past the maximum, wait for strobe	 reset_alarm = false;      }   }   //if I'm the base station and not sending in my frame, send a strobe   if(curFrame == 0 && myFrame == 0 && !waiting) {      mos_led_toggle (0);      strobing = TRUE;   }   if(curFrame == myFrame) {//could be our turn to do something      if(waiting) {	 waiting = FALSE;//reset waiting flag	 mos_sem_post (&cc1000_sem);      } else if(strobing){	 SPCR &= ~(1 << SPIE);//disable the spi device	 cc1000_mode(CC1000_MODE_TX);	 cc1000_state = state_send_pre; //init send state machine	 preamble_count = 1;	 //need to send out strobe, start the send here	 SPDR = PREAMBLE_BYTE; //start sending first preamble byte	 SPCR |= (1 << SPIE);//enable the spi device      }   }   if(reset_alarm)      mos_alarm(&frame_alarm, 0, FRAME_SIZE_US);}inline void tdma_state_machine(){   switch(cc1000_state)   {//SEND STATES   case STATE_SEND_SYNC:      SPDR = 0x33; //send sync byte      cc1000_state = STATE_SEND_FRAMENO;      break;   case STATE_SEND_FRAMENO:      SPDR = myFrame; //send id byte      cc1000_state = STATE_SEND_SIZE;      break;   case STATE_SEND_SIZE:      if(strobing){ //if this is a strobe, we can skip the actual packet	 SPDR = 0; //send zero size, to indicate strobe	 cc1000_state = STATE_SEND_FLUSH;      } else {	 cc1000_state_machine();      }      break;   case STATE_SEND_DONE:      //go back to recv mode      cc1000_state = STATE_RECV_IDLE;      //resume sending thread      if(strobing){	 cc1000_mode(CC1000_MODE_RX); //put back in receive mode	 strobing = FALSE; //clear strobing flag      }      //else      //mos_thread_resume(sendThread);      break;//RECV STATES         case STATE_RECV_FRAMENO:      spi_data = SPDR;      //look for frame 0 (base station) to sync up      tmp = (prev_data << offset) | (spi_data >> (8-offset));      if (tmp == 0){	 curFrame = 0; //we're in the middle of frame 0	 mos_remove_alarm(&frame_alarm);//remove pending alarms	 mos_alarm(&frame_alarm, 0, FRAME_SYNC_OFFSET_US);      }      cc1000_state = STATE_RECV_SIZE;      prev_data = spi_data;      break;   case STATE_RECV_SYNC:      spi_data = SPDR;      // Figure out the bit offset by shifting until we find sync byte      while(prev_data != 0x33){	 prev_data = (prev_data << 1) | (spi_data >> (7-offset));	 offset++;	 if(offset >= 8){ //didn't get sync byte... Something is wrong	    sync_error_count++; //log the error	    cc1000_state = STATE_RECV_IDLE;	    return;	 }      }      cc1000_state = STATE_RECV_FRAMENO;//synced and ready to get the packet.      prev_data = spi_data;      break;   default:      cc1000_state_machine();   }}/** @brief Interrupt handler is called when a byte is received or sent. */SIGNAL(SIG_SPI){   tdma_state_machine();}#endif#endif

⌨️ 快捷键说明

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