Stm32 support (#12)
* 1st version for STM32 bit detection and EEPROM changed to support STM32 * added STM32F1 support updated files: library.properties. NmraDcc.cpp, NmraDcc.h * switch off debug output * missing #endif added Testports for esp8266 defined
This commit is contained in:
committed by
Alex Shepherd
parent
dafa1c9964
commit
f8f106962f
117
NmraDcc.cpp
117
NmraDcc.cpp
@@ -21,7 +21,8 @@
|
|||||||
// and new signature of notifyDccSpeed and notifyDccFunc
|
// and new signature of notifyDccSpeed and notifyDccFunc
|
||||||
// 2015-12-16 Version without use of Timer0 by Franz-Peter Müller
|
// 2015-12-16 Version without use of Timer0 by Franz-Peter Müller
|
||||||
// 2016-07-16 handle glitches on DCC line
|
// 2016-07-16 handle glitches on DCC line
|
||||||
// 2016-08-20 added ESP8266 support by Sven (littleyoda)
|
// 2016-08-20 added ESP8266 support by Sven (littleyoda)
|
||||||
|
// 2017-01-19 added STM32F1 support by Franz-Peter
|
||||||
//
|
//
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
@@ -32,12 +33,6 @@
|
|||||||
|
|
||||||
#include "NmraDcc.h"
|
#include "NmraDcc.h"
|
||||||
|
|
||||||
#if defined(ESP8266)
|
|
||||||
#include <EEPROM.h>
|
|
||||||
#else
|
|
||||||
#include <avr/eeprom.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// DCC Receive Routine
|
// DCC Receive Routine
|
||||||
//
|
//
|
||||||
@@ -146,20 +141,34 @@
|
|||||||
#define MODE_TP4 pinMode( A4,OUTPUT ) // A4 = PortB Bit3
|
#define MODE_TP4 pinMode( A4,OUTPUT ) // A4 = PortB Bit3
|
||||||
#define SET_TP4 GPIOB_PSOR = 0x08
|
#define SET_TP4 GPIOB_PSOR = 0x08
|
||||||
#define CLR_TP4 GPIOB_PCOR = 0x08
|
#define CLR_TP4 GPIOB_PCOR = 0x08
|
||||||
#elif defined (__SAM3X8E__)
|
#elif defined (__STM32F1__)
|
||||||
// Arduino Due
|
// STM32F103...
|
||||||
#define MODE_TP1 pinMode( A1,OUTPUT ) // A1= PA24
|
#define MODE_TP1 pinMode( PB12,OUTPUT ) // TP1= PB12
|
||||||
#define SET_TP1 REG_PIOA_SODR = (1<<24)
|
#define SET_TP1 gpio_write_bit( GPIOB,12, HIGH );
|
||||||
#define CLR_TP1 REG_PIOA_CODR = (1<<24)
|
#define CLR_TP1 gpio_write_bit( GPIOB,12, LOW );
|
||||||
#define MODE_TP2 pinMode( A2,OUTPUT ) // A2= PA23
|
#define MODE_TP2 pinMode( PB13,OUTPUT ) // TP2= PB13
|
||||||
#define SET_TP2 REG_PIOA_SODR = (1<<23)
|
#define SET_TP2 gpio_write_bit( GPIOB,13, HIGH );
|
||||||
#define CLR_TP2 REG_PIOA_CODR = (1<<23)
|
#define CLR_TP2 gpio_write_bit( GPIOB,13, LOW );
|
||||||
#define MODE_TP3 pinMode( A3,OUTPUT ) // A3 = PA22
|
#define MODE_TP3 pinMode( PB14,OUTPUT ) // TP3 = PB14
|
||||||
#define SET_TP3 REG_PIOA_SODR = (1<<22)
|
#define SET_TP3 gpio_write_bit( GPIOB,14, HIGH );
|
||||||
#define CLR_TP3 REG_PIOA_CODR = (1<<22)
|
#define CLR_TP3 gpio_write_bit( GPIOB,14, LOW );
|
||||||
#define MODE_TP4 pinMode( A4,OUTPUT ) // A4 = PA6
|
#define MODE_TP4 pinMode( PB15,OUTPUT ) // TP4 = PB15
|
||||||
#define SET_TP4 REG_PIOA_SODR = (1<<6)
|
#define SET_TP4 gpio_write_bit( GPIOB,15, HIGH );
|
||||||
#define CLR_TP4 REG_PIOA_CODR = (1<<6)
|
#define CLR_TP4 gpio_write_bit( GPIOB,15, LOW );
|
||||||
|
#elif defined(ESP8266)
|
||||||
|
#define MODE_TP1 pinMode( D5,OUTPUT ) ; // GPIO 14
|
||||||
|
#define SET_TP1 GPOS = (1 << D5);
|
||||||
|
#define CLR_TP1 GPOC = (1 << D5);
|
||||||
|
#define MODE_TP2 pinMode( D6,OUTPUT ) ; // GPIO 12
|
||||||
|
#define SET_TP2 GPOS = (1 << D6);
|
||||||
|
#define CLR_TP2 GPOC = (1 << D6);
|
||||||
|
#define MODE_TP3 pinMode( D7,OUTPUT ) ; // GPIO 13
|
||||||
|
#define SET_TP3 GPOS = (1 << D7);
|
||||||
|
#define CLR_TP3 GPOC = (1 << D7);
|
||||||
|
#define MODE_TP4 pinMode( D7,OUTPUT ); // GPIO 15
|
||||||
|
#define SET_TP4 GPOC = (1 << D8);
|
||||||
|
#define CLR_TP4 GPOC = (1 << D8);
|
||||||
|
|
||||||
|
|
||||||
//#elif defined(__AVR_ATmega128__) ||defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
|
//#elif defined(__AVR_ATmega128__) ||defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
|
||||||
#else
|
#else
|
||||||
@@ -202,7 +211,11 @@
|
|||||||
struct countOf_t countOf;
|
struct countOf_t countOf;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined ( __STM32F1__ )
|
||||||
|
static ExtIntTriggerMode ISREdge;
|
||||||
|
#else
|
||||||
static byte ISREdge; // RISING or FALLING
|
static byte ISREdge; // RISING or FALLING
|
||||||
|
#endif
|
||||||
static word bitMax, bitMin;
|
static word bitMax, bitMin;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
@@ -270,9 +283,7 @@ void ExternalInterruptHandler(void)
|
|||||||
if ( bitMicros < bitMin ) {
|
if ( bitMicros < bitMin ) {
|
||||||
// too short - my be false interrupt due to glitch or false protocol -> ignore
|
// too short - my be false interrupt due to glitch or false protocol -> ignore
|
||||||
CLR_TP3;
|
CLR_TP3;
|
||||||
SET_TP4;
|
SET_TP4; CLR_TP4;
|
||||||
SET_TP4;
|
|
||||||
CLR_TP4;
|
|
||||||
return; //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> abort IRQ
|
return; //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> abort IRQ
|
||||||
}
|
}
|
||||||
DccBitVal = ( bitMicros < bitMax );
|
DccBitVal = ( bitMicros < bitMax );
|
||||||
@@ -281,7 +292,7 @@ void ExternalInterruptHandler(void)
|
|||||||
if(DccBitVal) {SET_TP2;} else {CLR_TP2;};
|
if(DccBitVal) {SET_TP2;} else {CLR_TP2;};
|
||||||
//#endif
|
//#endif
|
||||||
DCC_IrqRunning = true;
|
DCC_IrqRunning = true;
|
||||||
sei(); // time critical is only the micros() command,so allow nested irq's
|
interrupts(); // time critical is only the micros() command,so allow nested irq's
|
||||||
#ifdef DCC_DEBUG
|
#ifdef DCC_DEBUG
|
||||||
DccProcState.TickCount++;
|
DccProcState.TickCount++;
|
||||||
#endif
|
#endif
|
||||||
@@ -297,6 +308,9 @@ void ExternalInterruptHandler(void)
|
|||||||
DccRx.State = WAIT_START_BIT ;
|
DccRx.State = WAIT_START_BIT ;
|
||||||
// While waiting for the start bit, detect halfbit lengths. We will detect the correct
|
// While waiting for the start bit, detect halfbit lengths. We will detect the correct
|
||||||
// sync and detect whether we see a false (e.g. motorola) protocol
|
// sync and detect whether we see a false (e.g. motorola) protocol
|
||||||
|
#if defined ( __STM32F1__ )
|
||||||
|
detachInterrupt( DccProcState.ExtIntNum );
|
||||||
|
#endif
|
||||||
attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, CHANGE);
|
attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, CHANGE);
|
||||||
halfBit = 0;
|
halfBit = 0;
|
||||||
bitMax = MAX_ONEBITHALF;
|
bitMax = MAX_ONEBITHALF;
|
||||||
@@ -321,12 +335,13 @@ void ExternalInterruptHandler(void)
|
|||||||
bit1=bitMicros;
|
bit1=bitMicros;
|
||||||
} else {
|
} else {
|
||||||
// was "0" half bit, maybe the startbit
|
// was "0" half bit, maybe the startbit
|
||||||
|
SET_TP1;
|
||||||
halfBit = 4;
|
halfBit = 4;
|
||||||
|
CLR_TP1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1: //SET_TP1; // previous halfbit was '1'
|
case 1: //SET_TP1; // previous halfbit was '1'
|
||||||
if ( DccBitVal ) {
|
if ( DccBitVal ) {
|
||||||
CLR_TP1;
|
|
||||||
// its a '1' halfBit -> we are still in the preamble
|
// its a '1' halfBit -> we are still in the preamble
|
||||||
halfBit = 0;
|
halfBit = 0;
|
||||||
bit2=bitMicros;
|
bit2=bitMicros;
|
||||||
@@ -339,13 +354,20 @@ void ExternalInterruptHandler(void)
|
|||||||
bitMax = MAX_PRAEAMBEL;
|
bitMax = MAX_PRAEAMBEL;
|
||||||
bitMin = MIN_ONEBITFULL;
|
bitMin = MIN_ONEBITFULL;
|
||||||
DccRx.BitCount = 0;
|
DccRx.BitCount = 0;
|
||||||
|
SET_TP4;
|
||||||
|
#if defined ( __STM32F1__ )
|
||||||
|
detachInterrupt( DccProcState.ExtIntNum );
|
||||||
|
#endif
|
||||||
attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge );
|
attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge );
|
||||||
SET_TP3;
|
SET_TP3;
|
||||||
|
CLR_TP4;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// first '0' half detected in second halfBit
|
// first '0' half detected in second halfBit
|
||||||
// wrong sync or not a DCC protokoll
|
// wrong sync or not a DCC protokoll
|
||||||
|
CLR_TP3;
|
||||||
halfBit = 3;
|
halfBit = 3;
|
||||||
|
SET_TP3;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3: //SET_TP1; // previous halfbit was '0' in second halfbit
|
case 3: //SET_TP1; // previous halfbit was '0' in second halfbit
|
||||||
@@ -371,8 +393,13 @@ void ExternalInterruptHandler(void)
|
|||||||
DccRx.BitCount = 0 ;
|
DccRx.BitCount = 0 ;
|
||||||
DccRx.TempByte = 0 ;
|
DccRx.TempByte = 0 ;
|
||||||
}
|
}
|
||||||
attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge );
|
SET_TP4;
|
||||||
|
#if defined ( __STM32F1__ )
|
||||||
|
detachInterrupt( DccProcState.ExtIntNum );
|
||||||
|
#endif
|
||||||
|
attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge );
|
||||||
CLR_TP1;
|
CLR_TP1;
|
||||||
|
CLR_TP4;
|
||||||
break;
|
break;
|
||||||
case 4: SET_TP1; // previous (first) halfbit was 0
|
case 4: SET_TP1; // previous (first) halfbit was 0
|
||||||
// if this halfbit is 0 too, we got the startbit
|
// if this halfbit is 0 too, we got the startbit
|
||||||
@@ -396,8 +423,14 @@ void ExternalInterruptHandler(void)
|
|||||||
DccRx.BitCount = 0 ;
|
DccRx.BitCount = 0 ;
|
||||||
DccRx.TempByte = 0 ;
|
DccRx.TempByte = 0 ;
|
||||||
}
|
}
|
||||||
attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge );
|
|
||||||
CLR_TP1;
|
CLR_TP1;
|
||||||
|
SET_TP4;
|
||||||
|
#if defined ( __STM32F1__ )
|
||||||
|
detachInterrupt( DccProcState.ExtIntNum );
|
||||||
|
#endif
|
||||||
|
attachInterrupt( DccProcState.ExtIntNum, ExternalInterruptHandler, ISREdge );
|
||||||
|
CLR_TP4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -456,28 +489,18 @@ void ackCV(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t readEEPROM( unsigned int CV ) {
|
uint8_t readEEPROM( unsigned int CV ) {
|
||||||
#if defined(ESP8266)
|
|
||||||
return EEPROM.read(CV) ;
|
return EEPROM.read(CV) ;
|
||||||
#else
|
|
||||||
return eeprom_read_byte( (uint8_t*) CV );
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeEEPROM( unsigned int CV, uint8_t Value ) {
|
void writeEEPROM( unsigned int CV, uint8_t Value ) {
|
||||||
#if defined(ESP8266)
|
|
||||||
EEPROM.write(CV, Value) ;
|
EEPROM.write(CV, Value) ;
|
||||||
|
#if defined(ESP8266)
|
||||||
EEPROM.commit();
|
EEPROM.commit();
|
||||||
#else
|
|
||||||
eeprom_write_byte( (uint8_t*) CV, Value ) ;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool readyEEPROM() {
|
bool readyEEPROM() {
|
||||||
#if defined(ESP8266)
|
|
||||||
return true;
|
return true;
|
||||||
#else
|
|
||||||
return eeprom_is_ready();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -996,7 +1019,12 @@ NmraDcc::NmraDcc()
|
|||||||
|
|
||||||
void NmraDcc::pin( uint8_t ExtIntNum, uint8_t ExtIntPinNum, uint8_t EnablePullup)
|
void NmraDcc::pin( uint8_t ExtIntNum, uint8_t ExtIntPinNum, uint8_t EnablePullup)
|
||||||
{
|
{
|
||||||
|
#if defined ( __STM32F1__ )
|
||||||
|
// with STM32F1 the interuptnumber is equal the pin number
|
||||||
|
DccProcState.ExtIntNum = ExtIntPinNum;
|
||||||
|
#else
|
||||||
DccProcState.ExtIntNum = ExtIntNum;
|
DccProcState.ExtIntNum = ExtIntNum;
|
||||||
|
#endif
|
||||||
DccProcState.ExtIntPinNum = ExtIntPinNum;
|
DccProcState.ExtIntPinNum = ExtIntPinNum;
|
||||||
|
|
||||||
pinMode( ExtIntPinNum, INPUT );
|
pinMode( ExtIntPinNum, INPUT );
|
||||||
@@ -1103,10 +1131,10 @@ uint8_t NmraDcc::process()
|
|||||||
{
|
{
|
||||||
// We need to do this check with interrupts disabled
|
// We need to do this check with interrupts disabled
|
||||||
//SET_TP4;
|
//SET_TP4;
|
||||||
cli();
|
noInterrupts();
|
||||||
Msg = DccRx.PacketCopy ;
|
Msg = DccRx.PacketCopy ;
|
||||||
DccRx.DataReady = 0 ;
|
DccRx.DataReady = 0 ;
|
||||||
sei();
|
interrupts();
|
||||||
#ifdef DCC_DBGVAR
|
#ifdef DCC_DBGVAR
|
||||||
countOf.Tel++;
|
countOf.Tel++;
|
||||||
#endif
|
#endif
|
||||||
@@ -1115,20 +1143,15 @@ uint8_t NmraDcc::process()
|
|||||||
|
|
||||||
for(uint8_t i = 0; i < DccRx.PacketCopy.Size; i++)
|
for(uint8_t i = 0; i < DccRx.PacketCopy.Size; i++)
|
||||||
xorValue ^= DccRx.PacketCopy.Data[i];
|
xorValue ^= DccRx.PacketCopy.Data[i];
|
||||||
//CLR_TP4;
|
|
||||||
if(xorValue) {
|
if(xorValue) {
|
||||||
SET_TP4;
|
|
||||||
#ifdef DCC_DBGVAR
|
#ifdef DCC_DBGVAR
|
||||||
countOf.Err++;
|
countOf.Err++;
|
||||||
#endif
|
#endif
|
||||||
CLR_TP4;
|
|
||||||
return 0 ;
|
return 0 ;
|
||||||
} else {
|
} else {
|
||||||
//SET_TP4;
|
|
||||||
if( notifyDccMsg ) notifyDccMsg( &Msg );
|
if( notifyDccMsg ) notifyDccMsg( &Msg );
|
||||||
|
|
||||||
execDccProcessor( &Msg );
|
execDccProcessor( &Msg );
|
||||||
//CLR_TP4;
|
|
||||||
}
|
}
|
||||||
return 1 ;
|
return 1 ;
|
||||||
}
|
}
|
||||||
|
@@ -42,6 +42,8 @@
|
|||||||
#include "WProgram.h"
|
#include "WProgram.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "EEPROM.h"
|
||||||
|
|
||||||
#ifndef NMRADCC_IS_IN
|
#ifndef NMRADCC_IS_IN
|
||||||
#define NMRADCC_IS_IN
|
#define NMRADCC_IS_IN
|
||||||
|
|
||||||
@@ -93,8 +95,11 @@ typedef struct
|
|||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
#include <spi_flash.h>
|
#include <spi_flash.h>
|
||||||
#define MAXCV SPI_FLASH_SEC_SIZE
|
#define MAXCV SPI_FLASH_SEC_SIZE
|
||||||
|
#elif defined( __STM32F1__)
|
||||||
|
#define MAXCV (EEPROM_PAGE_SIZE/4 - 1) // number of storage places (CV address could be larger
|
||||||
|
// because STM32 uses virtual adresses)
|
||||||
#else
|
#else
|
||||||
#define MAXCV E2END // the upper limit of the CV value currently defined to max memory.
|
#define MAXCV E2END // the upper limit of the CV value currently defined to max memory.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@@ -6,4 +6,4 @@ sentence=Enables NMRA DCC Communication
|
|||||||
paragraph=This library allows you to interface to a NMRA DCC track signal and receive DCC commands. The library currently supports the AVR ATTiny84/85 & ATMega88/168/328/32u4 and Teensy 3.x using the INT0/1 Hardware Interrupt and micros() ONLY and no longer uses Timer0 Compare Match B, which makes it much more portable to other platforms
|
paragraph=This library allows you to interface to a NMRA DCC track signal and receive DCC commands. The library currently supports the AVR ATTiny84/85 & ATMega88/168/328/32u4 and Teensy 3.x using the INT0/1 Hardware Interrupt and micros() ONLY and no longer uses Timer0 Compare Match B, which makes it much more portable to other platforms
|
||||||
category=Communication
|
category=Communication
|
||||||
url=http://mrrwa.org/dcc-decoder-interface/
|
url=http://mrrwa.org/dcc-decoder-interface/
|
||||||
architectures=avr,esp8266
|
architectures=avr,esp8266,STM32F1
|
||||||
|
Reference in New Issue
Block a user