/** test_radio_multi app: This app lets you test the radio_multi library. Each device takes turns being the "leader device", instructing the other devices to flash their LEDs, and then passing leadership to the next device. Assumes that all active devices are numbered sequentially from 1 to N <= 255 at all times. */ #include #include #include #include #include #include #include #include #include #define SERIAL_MODE_AUTO 0 #define SERIAL_MODE_USB_RADIO 1 #define SERIAL_MODE_UART_RADIO 2 int32 CODE param_serial_mode = SERIAL_MODE_AUTO; int32 CODE param_baud_rate = 9600; int32 CODE param_nDTR_pin = 10; int32 CODE param_nRTS_pin = 11; int32 CODE param_nDSR_pin = 12; int32 CODE param_nCD_pin = 13; int32 CODE param_DTR_pin = -1; int32 CODE param_RTS_pin = -1; int32 CODE param_DSR_pin = -1; int32 CODE param_CD_pin = -1; int32 CODE param_arduino_DTR_pin = 0; // This bit is 1 if the UART's receiver has been disabled due to a framing error. // This bit should be equal to !U1CSR.RE, but we need this variable because we // don't want to be reading U1CSR in the main loop, because reading it might // cause the FE or ERR bits to be cleared and then the ISR // would not receive notice of those errors. BIT uartRxDisabled = 0; uint8 DATA currentSerialMode; #define LED_FLASH_TIME 50 // how many milliseconds an LED flash should be #define COMMAND_PAUSE 250 // how long to wait between wireless commands (should be > LED_FLASH_TIME) BIT isLeader = 0; // is this the device in charge of the others? /* Returns the logical values of the input control signal pins. Bit 0 is DSR. Bit 1 is CD. */ uint8 ioRxSignals() { uint8 signals = 0; if ((param_CD_pin >= 0 && isPinHigh(param_CD_pin)) || (param_nCD_pin >= 0 && !isPinHigh(param_nCD_pin))) { signals |= 2; } if ((param_DSR_pin >= 0 && isPinHigh(param_DSR_pin)) || (param_nDSR_pin >= 0 && !isPinHigh(param_nDSR_pin))) { signals |= 1; } return signals; } /* Sets the logical values of the output control signal pins. This should be called frequently (not just when the values change). Bit 0 is DTR. Bit 1 is RTS. */ void ioTxSignals(uint8 signals) { static uint8 nTrstPulseStartTime; static uint8 lastSignals; // Inverted outputs setDigitalOutput(param_nDTR_pin, (signals & ACM_CONTROL_LINE_DTR) ? 0 : 1); setDigitalOutput(param_nRTS_pin, (signals & ACM_CONTROL_LINE_RTS) ? 0 : 1); // Non-inverted outputs. setDigitalOutput(param_DTR_pin, (signals & ACM_CONTROL_LINE_DTR) ? 1 : 0); setDigitalOutput(param_RTS_pin, (signals & ACM_CONTROL_LINE_RTS) ? 1 : 0); // Arduino DTR pin. if (!(lastSignals & ACM_CONTROL_LINE_DTR) && (signals & ACM_CONTROL_LINE_DTR)) { // We just made a falling edge on the nDTR line, so start a 1-2ms high pulse // on the nTRST line. setDigitalOutput(param_arduino_DTR_pin, HIGH); nTrstPulseStartTime = getMs(); } else if ((uint8)(getMs() - nTrstPulseStartTime) >= 2) { setDigitalOutput(param_arduino_DTR_pin, LOW); } lastSignals = signals; } void uartToRadioService() { while(radioComRxAvailable() && uart1TxAvailable()) { uart1TxSendByte(radioComRxReceiveByte()); } // Control Signals. ioTxSignals(radioComRxControlSignals()); radioComTxControlSignals(ioRxSignals()); } void handleCommunications() { // the different 1-byte commands that the devices can send to each other const uint8 MSG_FLASH_GREEN = 0; const uint8 MSG_FLASH_RED = 1; const uint8 MSG_BECOME_LEADER = 2; uint8 sender; // who sent us the current message uint8 message; // this app uses 1-byte messages, although we're not limited to this uint8 i; BIT doneSearching = 0; // set to true when we've reached the maximum device ID that will respond to us uint8 maxIDFound = 1; // we record the highest device ID who has responded to us // the leader in this app is responsible for sending instructions to all other devices if(isLeader) { // instruct each device to flash its green LED individually i = 1; while(!doneSearching && i != 0) // we use != 0 because with enough devices we will wrap around to the broadcast ID, indicating completion { // don't send it to ourselves, because that would be dumb if(i != param_device_id) { // this is a transmission that requires an ACK in response to be considered successful; we // try several times before giving up without receiving an ACK from the other device if(radioMultiTxDataBlocking(i, &MSG_FLASH_GREEN, 1, 5)) { // record a new highest ID if(i > maxIDFound) maxIDFound = i; delayMs(COMMAND_PAUSE); } else { // indicate we're done searching for other devices doneSearching = 1; } } // move to the next device i ++; } // now tell everyone to flash the red LED at the same time (0 is the broadcast ID); does not require an ACK radioMultiTxData(0, &MSG_FLASH_RED, 1); delayMs(COMMAND_PAUSE); } else { // has someone contacted us? if(radioMultiRxAvailable()) { // read one byte of it, which should be all of the message we expect in this app radioMultiRxData(&sender, &message, 1); if(message == MSG_FLASH_GREEN) { LED_GREEN(1); delayMs(LED_FLASH_TIME); LED_GREEN(0); } else if(message == MSG_FLASH_RED) { LED_RED(1); delayMs(LED_FLASH_TIME); LED_RED(0); } } } } void main() { uint8 i; systemInit(); setDigitalOutput(param_arduino_DTR_pin, LOW); ioTxSignals(0); usbInit(); radioMultiInit(); randomSeedFromAdc(); uart1Init(); uart1SetBaudRate(param_baud_rate); // flash to indicate a reset for(i = 0; i < 3; i ++) { LED_YELLOW(1); delayMs(LED_FLASH_TIME); LED_YELLOW(0); delayMs(LED_FLASH_TIME); } // initially, the device with ID 1 is the leader isLeader = param_device_id == 1; LED_YELLOW(isLeader); while(1) { updateSerialMode(); boardService(); usbComService(); usbToRadioService(); uartToRadioService(); // handles leader and client logic handleCommunications(); switch(currentSerialMode) { case SERIAL_MODE_USB_RADIO: usbToRadioService(); break; case SERIAL_MODE_UART_RADIO: uartToRadioService(); break; } } }