//DCC_Probe.ino --application or client code#include "DCC_Probe.h"DCC_Probe DCC; void setup() { DCC.begin();}void loop() { DCC.DCC_Dump();}-----------------------------//DCC_Probe.cpp Implementation file
#include "DCC_Probe.h"DCC_Probe::DCC_Probe( ){ };enum dcc_state { look4preamble, look4preambleEnd, look4zero, buildpkt1, getzero2,alldone} state;volatile int preamble_count;volatile int byte_count;volatile int _count = 0; volatile int byte_pk[8];volatile int byte_val;volatile int byte_ptr; volatile int the_bytes[9]; volatile bool one_mess_done;
void DCC_Probe::begin() { Serial.begin(115200); Serial.println("\nDCC Capture: "); //optional attachInterrupt(digitalPinToInterrupt(IRQ_PIN), _DCC_ISR, MODE); state = look4preamble; preamble_count = 0; #if LTA pinMode(4,OUTPUT); pinMode(5,OUTPUT); pinMode(6,OUTPUT); #endif };
void DCC_Probe::DCC_Dump( ){ #if LTA digitalWrite(6,HIGH); #endif if (one_mess_done) //synchronise to complete message { if (the_bytes[1] != 255) { //ignore idle command for (int i = 1; i <= the_bytes[0]; i++){ Serial.print(the_bytes[i]); Serial.print(' '); } Serial.println(); one_mess_done = false; //message used } } #if LTA digitalWrite(6,LOW); #endif }
void save_bytes( ){ the_bytes[0] = byte_ptr; #if LTA digitalWrite(5,HIGH); //to time transfer #endif for (int i = 0 ; i < byte_ptr ; i++) //for (int i = 0 ; i < 8 ; i++) //worst case timing { //Serial.print(the_bytes[i]); the_bytes[i+1] = byte_pk[i]; }//Serial.print(the_bytes[byte_ptr]); #if LTA digitalWrite(5,LOW); #endif}#define DEBUG 0
void handle_bit(int the_bit){ if (_count<SAMPLE_SIZE) { #if DEBUG Serial.print(the_bit); _count++; #endif; switch(state){ case look4preamble : #if DEBUG Serial.print('F'); #endif if (the_bit == 1 ) { preamble_count = 1; state = look4preambleEnd; } else preamble_count = 0;//should be 0 anyway? break; case look4preambleEnd : #if DEBUG Serial.print('E'); #endif if (the_bit == 1 ) { preamble_count++; if (preamble_count > PREAMBLE_SIZE) {state = look4zero; byte_ptr = 0; } } else if (the_bit ==0){ state = look4preamble; preamble_count = 0; } break; case look4zero : #if DEBUG Serial.print('Z'); #endif if (the_bit == 0) { state = buildpkt1; byte_count = 0; byte_val = 0; } break; case buildpkt1 : #if DEBUG Serial.print('P'); #endif byte_count++; byte_val = 2*byte_val + the_bit; if (byte_count == 8){ byte_pk[byte_ptr++] = byte_val; state = getzero2; #if DEBUG Serial.print(byte_val); Serial.print(','); #endif } break; case getzero2 : #if DEBUG Serial.print('G'); #endif if (the_bit) { state=alldone; } if (!the_bit) { byte_val = 0; byte_count = 0; state = buildpkt1; } break; case alldone : #if LTA digitalWrite(5,HIGH); //Time will be critical #endif #if DEBUG Serial.println('#'); #endif if (the_bit) { //message should terminate with a 1. save_bytes( ); state = look4preamble; one_mess_done = true; } else Serial.print(" Error"); //should never happen #if LTA digitalWrite(5,LOW); #endif break; }} }volatile long int _start_time = 0;
static void DCC_Probe::_DCC_ISR( ){ int bit_found; #if LTA digitalWrite(4,HIGH); //time interrupt service routine #endif volatile unsigned long _end_time = micros( ); if ((_end_time -_start_time)> DCC_TIME ) bit_found = 0; else bit_found = 1; handle_bit(bit_found); _start_time = _end_time; #if LTA digitalWrite(4,LOW); #endif };---------------------------------//DCC_Probe.h header file#ifndef DCC_Probe_H#define DCC_Probe_H#include "Arduino.h"#define IRQ_PIN 2#define MODE RISING#define DCC_TIME 160#define SAMPLE_SIZE 80#define PREAMBLE_SIZE 10#define LTA 1class DCC_Probe { public : DCC_Probe( ); void begin( ); void DCC_Dump( ); private : static void _DCC_ISR( ); }; //don't forget this semi colon#endif----------------------------------