Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
LocoNet/examples/LocoLinx32U4/LocoLinx32U4.ino
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
197 lines (153 sloc)
5.45 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Arduino - AVR ATmega32U4 based USB LocoNet PC Interface Demo | |
#if !defined(ARDUINO_ARCH_AVR) and !defined(ARDUINO_MEGA_32U4) | |
#error "This sketch only supports the AVR ATmega32U4 processor as it relies on specific USB Port functionality" | |
#endif | |
#include <LocoNet.h> | |
// There are a number of ATmega32U4 boards available but each may have different pin numbers for on-baord LEDs. | |
// | |
// This example sketch was developed using the Sparkfun Arduino Pro Mico (see: https://www.sparkfun.com/products/12640) | |
// and a small LocoNet interface shield designed by John Plocher specifically to match up with the Arduino Pro Micro footprint | |
// that can be found here: http://www.spcoast.com/wiki/index.php/Core-Locobuffer | |
// The LocoNet Tx/Rx traffic can be indicated using some LEDs. The default values below are for the Sparkfun Arduino Pro Micro board. | |
// If your board doesn't have LEDs or you don't want to use them, comment out the two #define lines below | |
#define TX_LED 30 | |
#define RX_LED 17 | |
#if defined(TX_LED) or defined(RX_LED) | |
// If you're using LEDs to indicate LocoNet traffic then define the HIGH/LOW state to turn the LEDs ON/OFF in the two lines below | |
#define LED_ON LOW | |
#define LED_OFF HIGH | |
// These elapsedMillis timers are used to turn off the Tx/Rx LEDs after a short delay, so they're only needed when the LEDs are used | |
#include <elapsedMillis.h> // See http://playground.arduino.cc/Code/ElapsedMillis | |
elapsedMillis txElapsedMillis; | |
elapsedMillis rxElapsedMillis; | |
#endif | |
#define VERSION 2 | |
// The Rx Pin on the ATmega32U4 always uses the ICP input so that is fixed and enabled in the Library. | |
// However the Tx pin can be any other available pin on the board. | |
// For the Sparkfun Arduino Pro Micro and the Core-Locobuffer shield it uses Digital pin 7 | |
#define TX_PIN 7 | |
static LnBuf LnTxBuffer ; | |
static lnMsg *LnTxPacket; | |
static lnMsg *LnRxPacket; | |
static lnMsg *LnStatsPacket; | |
static lnMsg myStats; | |
// Format a LocoBuffer II Status Response | |
void updateStats() | |
{ | |
memset(&myStats, 0, sizeof(peerXferMsg)); | |
myStats.data[ 0] = OPC_PEER_XFER; | |
myStats.data[ 1] = 0x10; | |
myStats.data[ 2] = 0x50; | |
myStats.data[ 3] = 0x50; | |
myStats.data[ 4] = 0x01; | |
LnBufStats* pLnStats = LocoNet.getStats(); | |
long Errors = pLnStats->RxErrors + pLnStats->TxErrors; | |
uint8_t myStatsData[8]; | |
myStatsData[0] = 0x00; | |
myStatsData[1] = (Errors >> 16) & 0xFF; | |
myStatsData[2] = (Errors >> 8) & 0xFF; | |
myStatsData[3] = Errors & 0xFF; | |
myStatsData[4] = VERSION; | |
myStatsData[5] = 0x00; | |
myStatsData[6] = (pLnStats->Collisions >> 8) & 0xFF ; | |
myStatsData[7] = pLnStats->Collisions & 0xFF; | |
encodePeerData(&myStats.px, myStatsData); | |
uint8_t CheckSum = 0xFF ; | |
for( uint8_t lnTxIndex = 0; lnTxIndex < sizeof(peerXferMsg) - 1; lnTxIndex++ ) { | |
CheckSum ^= myStats.data[ lnTxIndex ] ; | |
} | |
myStats.data[sizeof(peerXferMsg) - 1] = CheckSum ; | |
LnStatsPacket = &myStats; | |
} | |
void setup() | |
{ | |
// Configure the serial port for 57600 baud, even though the baud rate is ignored for USB interfaces | |
Serial.begin(57600); | |
while (!Serial); // Wait for USB Serial port to connect - needed for native USB | |
// First initialize the LocoNet interface, specifying the TX Pin | |
LocoNet.init(TX_PIN); | |
// Initialize a LocoNet packet buffer to buffer bytes from the PC | |
initLnBuf(&LnTxBuffer) ; | |
// Set this to NULL so we know we don't have an unsent LocoNet packet | |
LnRxPacket = NULL; | |
LnTxPacket = NULL; | |
LnStatsPacket = NULL; | |
#ifdef RX_LED | |
pinMode(RX_LED, OUTPUT); | |
digitalWrite(RX_LED, LED_OFF); | |
#endif | |
#ifdef TX_LED | |
pinMode(TX_LED, OUTPUT); | |
digitalWrite(TX_LED, LED_OFF); | |
#endif | |
} | |
void loop() | |
{ | |
// Before we check for a new LocoNet packet, make sure we haven't already got a previously unset packet | |
if(LnRxPacket == NULL) | |
{ | |
if(LnStatsPacket) | |
{ | |
LnRxPacket = LnStatsPacket; | |
LnStatsPacket = NULL; | |
} | |
else | |
LnRxPacket = LocoNet.receive() ; | |
} | |
if( LnRxPacket ) | |
{ | |
#ifdef RX_LED | |
digitalWrite(RX_LED, LED_ON); | |
rxElapsedMillis = 0; | |
#endif | |
// Get the length of the received packet | |
uint8_t Length = getLnMsgSize( LnRxPacket ) ; | |
uint8_t USBWriteBufferFree = Serial.availableForWrite(); | |
if( USBWriteBufferFree >= Length) | |
{ | |
Serial.write((uint8_t*)LnRxPacket, Length); | |
LnRxPacket = NULL; | |
} | |
} | |
// Before we check for a new LocoNet TX packet, make sure we haven't already got a previously unset packet | |
if(LnTxPacket == NULL) | |
{ | |
int charWaiting; | |
// Check to see if there are any bytes from the PC | |
while( (charWaiting = Serial.available()) && (LnTxPacket == NULL) ) | |
{ | |
// Read the byte | |
uint8_t inByte = Serial.read() & 0xFF; | |
// Add it to the buffer | |
addByteLnBuf( &LnTxBuffer, inByte ) ; | |
// Check to see if we have received a complete packet yet | |
LnTxPacket = recvLnMsg( &LnTxBuffer ) ; | |
} | |
} | |
// Send the received packet from the PC to the LocoNet | |
if(LnTxPacket ) | |
{ | |
// Check for a Request for LocoNet Stats | |
if(LnTxPacket->data[0] == OPC_BUSY) | |
{ | |
LnTxPacket = NULL; | |
updateStats(); | |
} | |
else if(LocoNet.send( LnTxPacket ) == LN_DONE) | |
{ | |
LnTxPacket = NULL; | |
#ifdef TX_LED | |
digitalWrite(TX_LED, LED_ON); | |
txElapsedMillis = 0; | |
#endif | |
} | |
} | |
#ifdef RX_LED | |
if(rxElapsedMillis > 50) | |
digitalWrite(RX_LED, LED_OFF); | |
#endif | |
#ifdef TX_LED | |
if(txElapsedMillis > 50) | |
digitalWrite(TX_LED, LED_OFF); | |
#endif | |
} |