📄 txworwithack.c
字号:
/*******************************************************************************************************
* *
* ********** *
* ************ *
* *** *** *
* *** +++ *** This file contains all functions related to the transmitting unit * *
* *** + + *** (remote control). *
* *** + *
* *** + + *** *
* *** +++ *** TxWorWithAck.c *
* *** *** *
* ************ *
* ********** *
* *
*******************************************************************************************************
* Compiler: Keil C51 V7.50 *
* Target platform: Chipcon CCxxx0 (Silabs F320) *
* Author: ESY *
*******************************************************************************************************
* Revision history: See end of file *
*******************************************************************************************************/
#include <Chipcon\srf04\regssrf04.h>
#include <Chipcon\srf04\halsrf04.h>
#include <Chipcon\srf04\ebsrf04.h>
#include <WorWithAck.h>
//-------------------------------------------------------------------------------------------------------
// Defines
#define MAX_PACKET_BURST_TIMEOUT 950 // Maximum number of packets to send without receiving an
// ACK. Used as burst timeout to avoid endless packet
// bursting without getting any response.
#define RX_BYTES 0x7F
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
// Global Variables
// Variables to control the outgoing packet burst
UINT32 xdata packetsSent = 0;
UINT16 xdata packetCount = 0;
UINT8 xdata txBuffer[1]; // Fixed packet length: 1B data payload
BOOL xdata burstDone = FALSE;
BOOL xdata timeout = FALSE;
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
// Function declarations
void initTransmitter(); // internal function
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
// void initTransmitter(void)
//
// DESCRIPTION:
// This function is configuring some specific radio register settings and initiating interrupt
// timers for the transmitter unit.
//-------------------------------------------------------------------------------------------------------
void initTransmitter(void) {
// Enable automatic switching after packet has been sent to listen for incoming ACK.
// TXOFF_MODE = RX (TX->RX switch: 21.5 us), RXOFF_MODE = IDLE (RX->IDLE, no FS calib: 0.1 us)
halSpiWriteReg(CCxxx0_MCSM1, 0x33);
// Set RX timeout (timeout for sync word search)) to 325 us.
// WOR_RES = 0, (default value; Gives high time resolution/short periods)
// Enable RC oscillator calibration.
halSpiWriteReg(CCxxx0_WORCTRL, 0x78);
halSpiWriteReg(CCxxx0_MCSM2, 0x05); // RX_TIME = 101b
// T_rxtime = EVENT0 * C = 325 us
// If RX_TIEM is set to 5, C = 0.1127
// => EVENT0 = 2884 = 0x0B44 , Assuming f_xosc = 26 MHz
halSpiWriteReg(CCxxx0_WOREVT1, 0x0B);
halSpiWriteReg(CCxxx0_WOREVT0, 0x44);
// Setup TIMER1 to overflow every 1000 us (TX packet interval)
// 1/6000000 Hz * x = 1000 us, , SYSCLK_DIV_4 = 24 MHz/4 = 6 MHz
// => x = 6000
// 2^16 - 6000 = 59536 = 0xE890 , 16 bits timer register
// => TH1 = 0xE8
// => TL1 = 0x90
TH1 = 0xE8; // Timer1 high byte
TL1 = 0x90; // Timer1 low byte
// Clock source: 6 MHz, Mode: 16-bits timer; Initiated with interrupts off.
halSetupTimer01(TIMER_1, SYSCLK_DIV_4, MODE_1, INT_OFF);
// Enable EXTERNAL0 interrupt on low edge of GDO2 pin (used for incoming packets)
// CCxxx0_IOCFG1 == 0x06 => GDO0 asserts on sync word detection and de-asserts on packet end.
ENABLE_GLOBAL_INT(INT_OFF); // Got to globally disable interrupts because ...
SETUP_GDO0_INT(EDGE, LOW); // <-- this macro enables the new interrupt upon initialization ...
INT_ENABLE(INUM_EXTERNAL0, INT_OFF);// and then got to disable it ...
ENABLE_GLOBAL_INT(INT_ON); // before interrupts can be globally re-enabled again
} // initTransmitter
//-------------------------------------------------------------------------------------------------------
// void runTransmitter(void)
//
// DESCRIPTION:
// This function loops forever and transmits packet bursts upon joystick movements:
// Identical packet will be transmitted until an ACK packet has been received.
//-------------------------------------------------------------------------------------------------------
void runTransmitter(void) {
// Perform initalization specific for transmitting unit.
initTransmitter();
SET_YLED(LED_ON); // Turn on yellow LED to indicate unit is running
// Loops forever, sending packets upon joystick movement. Press S1 to abort.
while(!ebButtonPushed()) {
// Get current joystick position
joystickPosition = ebGetJoystickPosition();
//If joystick is moved, start burst of packets
if (joystickPosition != prevJoystickPosition) {
// Save joystick position for next iteration
prevJoystickPosition = joystickPosition;
// Temporary disable interrupts while updating LCD + calibrating
INT_ENABLE(INUM_TIMER1, INT_OFF);
// Calibrates the RC osc manually (721 us) in case of long time since last
// calibration/joystick movement
halSpiStrobe(CCxxx0_SCAL);
// Update LCD and reset packet counter
ebLcdUpdate("Bursting...", NULL);
packetCount = 0; // Reset counter before stating a new burst
halWait(800); // Wait for calibration to finish before packet burst can start
// Update payload with current joystick position
txBuffer[0] = joystickPosition;
// Start packet transmit interval timer
INT_ENABLE(INUM_TIMER1, INT_ON);
SET_BLED(LED_ON); // Blue LED on; Start burst
}
// NOTE! If the receiver receives one of the first packets in the burst and hence the burtDone
// flag is set not long after the ebLcdUpdate("Bursting...", NULL); function was called, the LCD
// will not be updated with the message below as the previous message is still being written to
// the display.
if (burstDone) {
burstDone = FALSE;
intToAscii(packetCount);
ebLcdUpdate("# pkts in burst:", asciiString);
}
if (timeout) {
timeout = FALSE;
//Update LCD with notice
ebLcdUpdate("No ACK->timeout.", "Burst stopped!");
}
}
SET_YLED(LED_OFF); // Turn off yellow LED to indicate unit has stopped.
}// runTransmitter
//-------------------------------------------------------------------------------------------------------
// void TIMER1_ISR(void)
//
// DESCRIPTION:
// This interrupt occurs every 1000 us, when timer1 overflows. The timer registers are reloaded and
// a packet is sent. This is a HIGH priority interrupt.
//-------------------------------------------------------------------------------------------------------
void TIMER1_ISR(void) interrupt INUM_TIMER1 {
// Reload timer1 registers (see initTransmitter() for calculation)
TH1 = 0xE8;
TL1 = 0x90; // this gives interval of 1000 us
// Check if more packets should be sent
if (packetCount < MAX_PACKET_BURST_TIMEOUT) {
// Send packet
halRfSendPacket(txBuffer, sizeof(txBuffer));
// The radio should now automatically switch to RX waiting for an ACK (TXOFF_MODE = RX).
// Increase the number of packets sent in the burst
packetCount++;
// Enable interrupts upon incoming ACK when radio is in RX in between TX periods
INT_SETFLAG(INUM_EXTERNAL0, INT_CLR); // Clear the interrupt flag
INT_ENABLE(INUM_EXTERNAL0, INT_ON); // Enable the interrupt
//Stop packet transmission (timeout) since no one is answering (No ACK is being received)
} else {
INT_ENABLE(INUM_TIMER1, INT_OFF);
SET_BLED(LED_OFF); // Blue LED off; Burst is over
timeout = TRUE;
}
}// TIMER1_ISR
//-------------------------------------------------------------------------------------------------------
// void EXTERNAL0_ISR(void)
//
// DESCRIPTION:
// This ISR runs whenever CCxx00 has received a packet.
//-------------------------------------------------------------------------------------------------------
void EXTERNAL0_ISR(void) interrupt INUM_EXTERNAL0 {
BYTE packetLength;
// Disable new interrupts while running ISR
ENABLE_GLOBAL_INT(INT_OFF);
// Check if we got any packets in the RX FIFO
// This status register is safe to read since it will not be updated after
// the packet has been received (See the CC1100 or 2500 Errata Note)
packetLength = halSpiReadStatus(CCxxx0_RXBYTES) & RX_BYTES;
if (packetLength != 0) { // The RX FIFO got some packet content
// Read out of RX FIFO into rxBuffer array.
rxBuffer[0] = halSpiReadReg(CCxxx0_RXFIFO);
// Check ACK
if ((rxBuffer[0] ^ 0xFF) == joystickPosition) { // ACK received?
// Stop packet burst
INT_ENABLE(INUM_TIMER1, INT_OFF);
SET_BLED(LED_OFF); // Blue LED off; burst is over
burstDone = TRUE;
P_LED1 = ~P_LED1; // Toggle green LED for ACK received
}
} else {
// Detected sync word, but got no packet in RX FIFO
// Possible reasons: packet had wrong length or contained CRC errors.
P_LED2 = ~P_LED2; // Toggle red LED for packet error
}
ENABLE_GLOBAL_INT(INT_ON); // Re-enable interrupts globally
// The radio is now in IDLE state (RXOFF_MODE = IDLE)
// The state transition happens automatically after end of received packet.
// RX->IDLE (no FS calibration) : 0.1 us
}// EXTERNAL0_ISR
/******************************************************************************************************
* Revision history: *
*
* $Log: TxWorWithAck.c,v $
* Revision 1.2 2006/04/25 15:04:07 a0190596
* Comments added
*
* Revision 1.1 2005/10/06 12:13:45 sna
* Initial version in CVS.
*
*
*
******************************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -