The main program talks to the ANT+ device, decides on a message and drives our display.
The code is found at RetroRunnerReadout.ino.
The program follows the standard Arduino/MCU setup then loop paradigm.
It sets up the hardware (display and ANT+) and following that displays a few setup messages on the LED 7-segment display.
The code is found at RetroRunnerReadout.ino.
The program follows the standard Arduino/MCU setup then loop paradigm.
It sets up the hardware (display and ANT+) and following that displays a few setup messages on the LED 7-segment display.
setup()
Setup enables the hardware for the ANT+ and MAX7219 chips and prints a few messages to the display.{ Serial.begin(CONSOLE_BAUD_RATE); SERIAL_INFO_PRINTLN("CanToo Runner!"); mydisplay.shutdown(0, false); // turns on display mydisplay.setIntensity(0, DISPLAY_INTENSITY); // 0..15 = brightest mydisplay.clearDisplay(0); mydisplay.shutdown(0, true); // turns off display //Print a few startup messages for(unsigned int counter_setup = 0; counter_setup < STARTUP_TEXTS_COUNT; counter_setup++) { const char * const* str_in_pm = &startup_texts[ counter_setup ]; char text[MAX_CHARS_TO_DISPLAY_STR]; CLEAR_STR(text, MAX_CHARS_TO_DISPLAY_STR); //Read from PROG_MEM strncpy_P(text, (char*)pgm_read_word( str_in_pm ), MAX_CHARS_TO_DISPLAY_STR); print_and_delay( text ); } SERIAL_DEBUG_PRINTLN_F("ANT+ Config..."); //We setup an interrupt to detect when the RTS is received from the ANT chip. //This is a 50 usec HIGH signal at the end of each valid ANT message received from the host at the chip attachInterrupt(0/*0==pin2==RTS_PIN*/, isr_ant, RISING); ant_serial.begin( ANTPLUS_BAUD_RATE ); antplus.begin( ant_serial ); //This should not be strictly necessary - the device should always come up by itself.... //But let's make sure we didn't miss the first RTS in a power-up race antplus.hardwareReset(); SERIAL_DEBUG_PRINTLN_F("ANT+ Config Finished"); }
Following that it drops into the processing loop. The loop alternates between servicing sending/receiving ANT+ messages and displaying messages to the screen.
loop()
The loop function repeats executing ANT+ code and displaying (). The ANT+ code is given priority at the start as it establishes an ANT+ channel.
{ loop_antplus(); //Get the ANT+ channels up quickly // then send some display messages if(ret_val_ce == ANT_CHANNEL_ESTABLISH_COMPLETE) { //This has blocking sleeps in it and so causes things to stop loop_display(); } }
loop_display()
The display messages are hard coded loops. The loops however have special keywords that are replaced dynamically updating distance travelled, heart rate, a random name or motivation quote etc.{ static int counter = 0; char text[MAX_CHARS_TO_DISPLAY_STR]; //Pull a string from the loop texts //These are one per loop and some of them get replaced if they are "magic" texts const char * const* str_in_pm = &loop_texts[ counter % LOOP_TEXTS_COUNT ]; CLEAR_STR(text, MAX_CHARS_TO_DISPLAY_STR); strncpy_P(text, (char*)pgm_read_word( str_in_pm ), MAX_CHARS_TO_DISPLAY_STR); //Replace, print and then delay. print_and_delay( text ); counter++; }
loop_antplus()
The ANT+ loop does two things. Firstly it sets up an ANT+ channel for receiving SDM/Footpod broadcasts and then it processes any messages coming in on that channel (updating variables that are read in the string replace function).
{
byte packet_buffer[MAXPACKETLEN];
ANT_Packet * packet = (ANT_Packet *) packet_buffer;
MESSAGE_READ ret_val = MESSAGE_READ_NONE;
//We received an interrupt on the nRF24AP2 RTS pin
if(state == 1)
{
antplus.rTSHighAssertion();
//Clear the ISR flag
state = 0;
}
ret_val = antplus.readPacket(packet, MAXPACKETLEN, 0 );
if((ret_val == MESSAGE_READ_EXPECTED) || (ret_val == MESSAGE_READ_OTHER))
{
//Some broadcast packets will update globals (like HRM and Footpod)
process_packet(packet);
}
//Only one channel gets setup in this version
if(ret_val_ce != ANT_CHANNEL_ESTABLISH_COMPLETE)
{
//This function will progress a state machine in
//the ANT+ library to establish a channel
ret_val_ce = antplus.progress_setup_channel( &sdm_channel );
if(ret_val_ce == ANT_CHANNEL_ESTABLISH_COMPLETE)
{
SERIAL_DEBUG_PRINTLN_F( "Channel established!" );
}
}
}
If you want to dig deeper, see the interrupt, string replacement code look at the code on github. RetroRunnerReadout.ino.The libraries created for the project are at MAX72xx_SPI_Arduino and ANTPlus_Arduino.
If you want to dig deeper, see the interrupt, string replacement code look at the code on github. RetroRunnerReadout.ino.The libraries created for the project are at MAX72xx_SPI_Arduino and ANTPlus_Arduino.