mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-12-24 13:21:23 +01:00
Merge pull request #139 from mjs513/Teensy-Revisions
Added support for Teensy 3.2, 3.5, 3.6, 4.0 and 4.1
This commit is contained in:
commit
44ca3bc7b9
12
DCC.cpp
12
DCC.cpp
@ -480,31 +480,31 @@ const ackOp FLASH LONG_LOCO_ID_PROG[] = {
|
|||||||
FAIL
|
FAIL
|
||||||
};
|
};
|
||||||
|
|
||||||
void DCC::writeCVByte(int cv, byte byteValue, ACK_CALLBACK callback) {
|
void DCC::writeCVByte(int16_t cv, byte byteValue, ACK_CALLBACK callback) {
|
||||||
ackManagerSetup(cv, byteValue, WRITE_BYTE_PROG, callback);
|
ackManagerSetup(cv, byteValue, WRITE_BYTE_PROG, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DCC::writeCVBit(int cv, byte bitNum, bool bitValue, ACK_CALLBACK callback) {
|
void DCC::writeCVBit(int16_t cv, byte bitNum, bool bitValue, ACK_CALLBACK callback) {
|
||||||
if (bitNum >= 8) callback(-1);
|
if (bitNum >= 8) callback(-1);
|
||||||
else ackManagerSetup(cv, bitNum, bitValue?WRITE_BIT1_PROG:WRITE_BIT0_PROG, callback);
|
else ackManagerSetup(cv, bitNum, bitValue?WRITE_BIT1_PROG:WRITE_BIT0_PROG, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DCC::verifyCVByte(int cv, byte byteValue, ACK_CALLBACK callback) {
|
void DCC::verifyCVByte(int16_t cv, byte byteValue, ACK_CALLBACK callback) {
|
||||||
ackManagerSetup(cv, byteValue, VERIFY_BYTE_PROG, callback);
|
ackManagerSetup(cv, byteValue, VERIFY_BYTE_PROG, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DCC::verifyCVBit(int cv, byte bitNum, bool bitValue, ACK_CALLBACK callback) {
|
void DCC::verifyCVBit(int16_t cv, byte bitNum, bool bitValue, ACK_CALLBACK callback) {
|
||||||
if (bitNum >= 8) callback(-1);
|
if (bitNum >= 8) callback(-1);
|
||||||
else ackManagerSetup(cv, bitNum, bitValue?VERIFY_BIT1_PROG:VERIFY_BIT0_PROG, callback);
|
else ackManagerSetup(cv, bitNum, bitValue?VERIFY_BIT1_PROG:VERIFY_BIT0_PROG, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DCC::readCVBit(int cv, byte bitNum, ACK_CALLBACK callback) {
|
void DCC::readCVBit(int16_t cv, byte bitNum, ACK_CALLBACK callback) {
|
||||||
if (bitNum >= 8) callback(-1);
|
if (bitNum >= 8) callback(-1);
|
||||||
else ackManagerSetup(cv, bitNum,READ_BIT_PROG, callback);
|
else ackManagerSetup(cv, bitNum,READ_BIT_PROG, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DCC::readCV(int cv, ACK_CALLBACK callback) {
|
void DCC::readCV(int16_t cv, ACK_CALLBACK callback) {
|
||||||
ackManagerSetup(cv, 0,READ_CV_PROG, callback);
|
ackManagerSetup(cv, 0,READ_CV_PROG, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
DCC.h
24
DCC.h
@ -23,7 +23,7 @@
|
|||||||
#include "MotorDrivers.h"
|
#include "MotorDrivers.h"
|
||||||
#include "FSH.h"
|
#include "FSH.h"
|
||||||
|
|
||||||
typedef void (*ACK_CALLBACK)(int result);
|
typedef void (*ACK_CALLBACK)(int16_t result);
|
||||||
|
|
||||||
enum ackOp : byte
|
enum ackOp : byte
|
||||||
{ // Program opcodes for the ack Manager
|
{ // Program opcodes for the ack Manager
|
||||||
@ -86,12 +86,12 @@ public:
|
|||||||
static void setProgTrackBoost(bool on); // when true, special prog track current limit does not apply
|
static void setProgTrackBoost(bool on); // when true, special prog track current limit does not apply
|
||||||
|
|
||||||
// ACKable progtrack calls bitresults callback 0,0 or -1, cv returns value or -1
|
// ACKable progtrack calls bitresults callback 0,0 or -1, cv returns value or -1
|
||||||
static void readCV(int cv, ACK_CALLBACK callback);
|
static void readCV(int16_t cv, ACK_CALLBACK callback);
|
||||||
static void readCVBit(int cv, byte bitNum, ACK_CALLBACK callback); // -1 for error
|
static void readCVBit(int16_t cv, byte bitNum, ACK_CALLBACK callback); // -1 for error
|
||||||
static void writeCVByte(int cv, byte byteValue, ACK_CALLBACK callback);
|
static void writeCVByte(int16_t cv, byte byteValue, ACK_CALLBACK callback);
|
||||||
static void writeCVBit(int cv, byte bitNum, bool bitValue, ACK_CALLBACK callback);
|
static void writeCVBit(int16_t cv, byte bitNum, bool bitValue, ACK_CALLBACK callback);
|
||||||
static void verifyCVByte(int cv, byte byteValue, ACK_CALLBACK callback);
|
static void verifyCVByte(int16_t cv, byte byteValue, ACK_CALLBACK callback);
|
||||||
static void verifyCVBit(int cv, byte bitNum, bool bitValue, ACK_CALLBACK callback);
|
static void verifyCVBit(int16_t cv, byte bitNum, bool bitValue, ACK_CALLBACK callback);
|
||||||
|
|
||||||
static void getLocoId(ACK_CALLBACK callback);
|
static void getLocoId(ACK_CALLBACK callback);
|
||||||
static void setLocoId(int id,ACK_CALLBACK callback);
|
static void setLocoId(int id,ACK_CALLBACK callback);
|
||||||
@ -168,6 +168,16 @@ private:
|
|||||||
#define ARDUINO_TYPE "MEGA"
|
#define ARDUINO_TYPE "MEGA"
|
||||||
#elif defined(ARDUINO_ARCH_MEGAAVR)
|
#elif defined(ARDUINO_ARCH_MEGAAVR)
|
||||||
#define ARDUINO_TYPE "MEGAAVR"
|
#define ARDUINO_TYPE "MEGAAVR"
|
||||||
|
#elif defined(ARDUINO_TEENSY32)
|
||||||
|
#define ARDUINO_TYPE "TEENSY32"
|
||||||
|
#elif defined(ARDUINO_TEENSY35)
|
||||||
|
#define ARDUINO_TYPE "TEENSY35"
|
||||||
|
#elif defined(ARDUINO_TEENSY36)
|
||||||
|
#define ARDUINO_TYPE "TEENSY36"
|
||||||
|
#elif defined(ARDUINO_TEENSY40)
|
||||||
|
#define ARDUINO_TYPE "TEENSY40"
|
||||||
|
#elif defined(ARDUINO_TEENSY41)
|
||||||
|
#define ARDUINO_TYPE "TEENSY41"
|
||||||
#else
|
#else
|
||||||
#error CANNOT COMPILE - DCC++ EX ONLY WORKS WITH AN ARDUINO UNO, NANO 328, OR ARDUINO MEGA 1280/2560
|
#error CANNOT COMPILE - DCC++ EX ONLY WORKS WITH AN ARDUINO UNO, NANO 328, OR ARDUINO MEGA 1280/2560
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,29 +34,28 @@
|
|||||||
|
|
||||||
// These keywords are used in the <1> command. The number is what you get if you use the keyword as a parameter.
|
// These keywords are used in the <1> command. The number is what you get if you use the keyword as a parameter.
|
||||||
// To discover new keyword numbers , use the <$ YOURKEYWORD> command
|
// To discover new keyword numbers , use the <$ YOURKEYWORD> command
|
||||||
const int HASH_KEYWORD_PROG = -29718;
|
const int16_t HASH_KEYWORD_PROG = -29718;
|
||||||
const int HASH_KEYWORD_MAIN = 11339;
|
const int16_t HASH_KEYWORD_MAIN = 11339;
|
||||||
const int HASH_KEYWORD_JOIN = -30750;
|
const int16_t HASH_KEYWORD_JOIN = -30750;
|
||||||
const int HASH_KEYWORD_CABS = -11981;
|
const int16_t HASH_KEYWORD_CABS = -11981;
|
||||||
const int HASH_KEYWORD_RAM = 25982;
|
const int16_t HASH_KEYWORD_RAM = 25982;
|
||||||
const int HASH_KEYWORD_CMD = 9962;
|
const int16_t HASH_KEYWORD_CMD = 9962;
|
||||||
const int HASH_KEYWORD_WIT = 31594;
|
const int16_t HASH_KEYWORD_WIT = 31594;
|
||||||
const int HASH_KEYWORD_WIFI = -5583;
|
const int16_t HASH_KEYWORD_WIFI = -5583;
|
||||||
const int HASH_KEYWORD_ACK = 3113;
|
const int16_t HASH_KEYWORD_ACK = 3113;
|
||||||
const int HASH_KEYWORD_ON = 2657;
|
const int16_t HASH_KEYWORD_ON = 2657;
|
||||||
const int HASH_KEYWORD_DCC = 6436;
|
const int16_t HASH_KEYWORD_DCC = 6436;
|
||||||
const int HASH_KEYWORD_SLOW = -17209;
|
const int16_t HASH_KEYWORD_SLOW = -17209;
|
||||||
const int HASH_KEYWORD_PROGBOOST = -6353;
|
const int16_t HASH_KEYWORD_PROGBOOST = -6353;
|
||||||
const int HASH_KEYWORD_EEPROM = -7168;
|
const int16_t HASH_KEYWORD_EEPROM = -7168;
|
||||||
const int HASH_KEYWORD_LIMIT = 27413;
|
const int16_t HASH_KEYWORD_LIMIT = 27413;
|
||||||
const int HASH_KEYWORD_ETHERNET = -30767;
|
const int16_t HASH_KEYWORD_ETHERNET = -30767;
|
||||||
const int HASH_KEYWORD_MAX = 16244;
|
const int16_t HASH_KEYWORD_MAX = 16244;
|
||||||
const int HASH_KEYWORD_MIN = 15978;
|
const int16_t HASH_KEYWORD_MIN = 15978;
|
||||||
const int HASH_KEYWORD_LCN = 15137;
|
const int16_t HASH_KEYWORD_LCN = 15137;
|
||||||
const int HASH_KEYWORD_RESET = 26133;
|
const int16_t HASH_KEYWORD_RESET = 26133;
|
||||||
|
|
||||||
|
int16_t DCCEXParser::stashP[MAX_COMMAND_PARAMS];
|
||||||
int DCCEXParser::stashP[MAX_COMMAND_PARAMS];
|
|
||||||
bool DCCEXParser::stashBusy;
|
bool DCCEXParser::stashBusy;
|
||||||
|
|
||||||
Print *DCCEXParser::stashStream = NULL;
|
Print *DCCEXParser::stashStream = NULL;
|
||||||
@ -108,16 +107,16 @@ void DCCEXParser::loop(Stream &stream)
|
|||||||
Sensor::checkAll(&stream); // Update and print changes
|
Sensor::checkAll(&stream); // Update and print changes
|
||||||
}
|
}
|
||||||
|
|
||||||
int DCCEXParser::splitValues(int result[MAX_COMMAND_PARAMS], const byte *cmd)
|
int16_t DCCEXParser::splitValues(int16_t result[MAX_COMMAND_PARAMS], const byte *cmd)
|
||||||
{
|
{
|
||||||
byte state = 1;
|
byte state = 1;
|
||||||
byte parameterCount = 0;
|
byte parameterCount = 0;
|
||||||
int runningValue = 0;
|
int16_t runningValue = 0;
|
||||||
const byte *remainingCmd = cmd + 1; // skips the opcode
|
const byte *remainingCmd = cmd + 1; // skips the opcode
|
||||||
bool signNegative = false;
|
bool signNegative = false;
|
||||||
|
|
||||||
// clear all parameters in case not enough found
|
// clear all parameters in case not enough found
|
||||||
for (int i = 0; i < MAX_COMMAND_PARAMS; i++)
|
for (int16_t i = 0; i < MAX_COMMAND_PARAMS; i++)
|
||||||
result[i] = 0;
|
result[i] = 0;
|
||||||
|
|
||||||
while (parameterCount < MAX_COMMAND_PARAMS)
|
while (parameterCount < MAX_COMMAND_PARAMS)
|
||||||
@ -167,15 +166,15 @@ int DCCEXParser::splitValues(int result[MAX_COMMAND_PARAMS], const byte *cmd)
|
|||||||
return parameterCount;
|
return parameterCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DCCEXParser::splitHexValues(int result[MAX_COMMAND_PARAMS], const byte *cmd)
|
int16_t DCCEXParser::splitHexValues(int16_t result[MAX_COMMAND_PARAMS], const byte *cmd)
|
||||||
{
|
{
|
||||||
byte state = 1;
|
byte state = 1;
|
||||||
byte parameterCount = 0;
|
byte parameterCount = 0;
|
||||||
int runningValue = 0;
|
int16_t runningValue = 0;
|
||||||
const byte *remainingCmd = cmd + 1; // skips the opcode
|
const byte *remainingCmd = cmd + 1; // skips the opcode
|
||||||
|
|
||||||
// clear all parameters in case not enough found
|
// clear all parameters in case not enough found
|
||||||
for (int i = 0; i < MAX_COMMAND_PARAMS; i++)
|
for (int16_t i = 0; i < MAX_COMMAND_PARAMS; i++)
|
||||||
result[i] = 0;
|
result[i] = 0;
|
||||||
|
|
||||||
while (parameterCount < MAX_COMMAND_PARAMS)
|
while (parameterCount < MAX_COMMAND_PARAMS)
|
||||||
@ -257,7 +256,7 @@ void DCCEXParser::parse(Print *stream, byte *com, RingStream * ringStream)
|
|||||||
(void)EEPROM; // tell compiler not to warn this is unused
|
(void)EEPROM; // tell compiler not to warn this is unused
|
||||||
if (Diag::CMD)
|
if (Diag::CMD)
|
||||||
DIAG(F("PARSING:%s"), com);
|
DIAG(F("PARSING:%s"), com);
|
||||||
int p[MAX_COMMAND_PARAMS];
|
int16_t p[MAX_COMMAND_PARAMS];
|
||||||
while (com[0] == '<' || com[0] == ' ')
|
while (com[0] == '<' || com[0] == ' ')
|
||||||
com++; // strip off any number of < or spaces
|
com++; // strip off any number of < or spaces
|
||||||
byte params = splitValues(p, com);
|
byte params = splitValues(p, com);
|
||||||
@ -275,9 +274,9 @@ void DCCEXParser::parse(Print *stream, byte *com, RingStream * ringStream)
|
|||||||
return; // filterCallback asked us to ignore
|
return; // filterCallback asked us to ignore
|
||||||
case 't': // THROTTLE <t [REGISTER] CAB SPEED DIRECTION>
|
case 't': // THROTTLE <t [REGISTER] CAB SPEED DIRECTION>
|
||||||
{
|
{
|
||||||
int cab;
|
int16_t cab;
|
||||||
int tspeed;
|
int16_t tspeed;
|
||||||
int direction;
|
int16_t direction;
|
||||||
|
|
||||||
if (params == 4)
|
if (params == 4)
|
||||||
{ // <t REGISTER CAB SPEED DIRECTION>
|
{ // <t REGISTER CAB SPEED DIRECTION>
|
||||||
@ -561,7 +560,7 @@ void DCCEXParser::parse(Print *stream, byte *com, RingStream * ringStream)
|
|||||||
StringFormatter::send(stream, F("<X>\n"));
|
StringFormatter::send(stream, F("<X>\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DCCEXParser::parseZ(Print *stream, int params, int p[])
|
bool DCCEXParser::parseZ(Print *stream, int16_t params, int16_t p[])
|
||||||
{
|
{
|
||||||
|
|
||||||
switch (params)
|
switch (params)
|
||||||
@ -605,7 +604,7 @@ bool DCCEXParser::parseZ(Print *stream, int params, int p[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
//===================================
|
//===================================
|
||||||
bool DCCEXParser::parsef(Print *stream, int params, int p[])
|
bool DCCEXParser::parsef(Print *stream, int16_t params, int16_t p[])
|
||||||
{
|
{
|
||||||
// JMRI sends this info in DCC message format but it's not exactly
|
// JMRI sends this info in DCC message format but it's not exactly
|
||||||
// convenient for other processing
|
// convenient for other processing
|
||||||
@ -637,9 +636,9 @@ bool DCCEXParser::parsef(Print *stream, int params, int p[])
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DCCEXParser::funcmap(int cab, byte value, byte fstart, byte fstop)
|
void DCCEXParser::funcmap(int16_t cab, byte value, byte fstart, byte fstop)
|
||||||
{
|
{
|
||||||
for (int i = fstart; i <= fstop; i++)
|
for (int16_t i = fstart; i <= fstop; i++)
|
||||||
{
|
{
|
||||||
DCC::setFn(cab, i, value & 1);
|
DCC::setFn(cab, i, value & 1);
|
||||||
value >>= 1;
|
value >>= 1;
|
||||||
@ -647,7 +646,7 @@ void DCCEXParser::funcmap(int cab, byte value, byte fstart, byte fstop)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//===================================
|
//===================================
|
||||||
bool DCCEXParser::parseT(Print *stream, int params, int p[])
|
bool DCCEXParser::parseT(Print *stream, int16_t params, int16_t p[])
|
||||||
{
|
{
|
||||||
switch (params)
|
switch (params)
|
||||||
{
|
{
|
||||||
@ -690,7 +689,7 @@ bool DCCEXParser::parseT(Print *stream, int params, int p[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DCCEXParser::parseS(Print *stream, int params, int p[])
|
bool DCCEXParser::parseS(Print *stream, int16_t params, int16_t p[])
|
||||||
{
|
{
|
||||||
|
|
||||||
switch (params)
|
switch (params)
|
||||||
@ -722,7 +721,7 @@ bool DCCEXParser::parseS(Print *stream, int params, int p[])
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DCCEXParser::parseD(Print *stream, int params, int p[])
|
bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[])
|
||||||
{
|
{
|
||||||
if (params == 0)
|
if (params == 0)
|
||||||
return false;
|
return false;
|
||||||
@ -798,7 +797,7 @@ bool DCCEXParser::parseD(Print *stream, int params, int p[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CALLBACKS must be static
|
// CALLBACKS must be static
|
||||||
bool DCCEXParser::stashCallback(Print *stream, int p[MAX_COMMAND_PARAMS], RingStream * ringStream)
|
bool DCCEXParser::stashCallback(Print *stream, int16_t p[MAX_COMMAND_PARAMS], RingStream * ringStream)
|
||||||
{
|
{
|
||||||
if (stashBusy )
|
if (stashBusy )
|
||||||
return false;
|
return false;
|
||||||
@ -823,43 +822,43 @@ void DCCEXParser::commitAsyncReplyStream() {
|
|||||||
stashBusy = false;
|
stashBusy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DCCEXParser::callback_W(int result)
|
void DCCEXParser::callback_W(int16_t result)
|
||||||
{
|
{
|
||||||
StringFormatter::send(getAsyncReplyStream(),
|
StringFormatter::send(getAsyncReplyStream(),
|
||||||
F("<r%d|%d|%d %d>\n"), stashP[2], stashP[3], stashP[0], result == 1 ? stashP[1] : -1);
|
F("<r%d|%d|%d %d>\n"), stashP[2], stashP[3], stashP[0], result == 1 ? stashP[1] : -1);
|
||||||
commitAsyncReplyStream();
|
commitAsyncReplyStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DCCEXParser::callback_B(int result)
|
void DCCEXParser::callback_B(int16_t result)
|
||||||
{
|
{
|
||||||
StringFormatter::send(getAsyncReplyStream(),
|
StringFormatter::send(getAsyncReplyStream(),
|
||||||
F("<r%d|%d|%d %d %d>\n"), stashP[3], stashP[4], stashP[0], stashP[1], result == 1 ? stashP[2] : -1);
|
F("<r%d|%d|%d %d %d>\n"), stashP[3], stashP[4], stashP[0], stashP[1], result == 1 ? stashP[2] : -1);
|
||||||
commitAsyncReplyStream();
|
commitAsyncReplyStream();
|
||||||
}
|
}
|
||||||
void DCCEXParser::callback_Vbit(int result)
|
void DCCEXParser::callback_Vbit(int16_t result)
|
||||||
{
|
{
|
||||||
StringFormatter::send(getAsyncReplyStream(), F("<v %d %d %d>\n"), stashP[0], stashP[1], result);
|
StringFormatter::send(getAsyncReplyStream(), F("<v %d %d %d>\n"), stashP[0], stashP[1], result);
|
||||||
commitAsyncReplyStream();
|
commitAsyncReplyStream();
|
||||||
}
|
}
|
||||||
void DCCEXParser::callback_Vbyte(int result)
|
void DCCEXParser::callback_Vbyte(int16_t result)
|
||||||
{
|
{
|
||||||
StringFormatter::send(getAsyncReplyStream(), F("<v %d %d>\n"), stashP[0], result);
|
StringFormatter::send(getAsyncReplyStream(), F("<v %d %d>\n"), stashP[0], result);
|
||||||
commitAsyncReplyStream();
|
commitAsyncReplyStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DCCEXParser::callback_R(int result)
|
void DCCEXParser::callback_R(int16_t result)
|
||||||
{
|
{
|
||||||
StringFormatter::send(getAsyncReplyStream(), F("<r%d|%d|%d %d>\n"), stashP[1], stashP[2], stashP[0], result);
|
StringFormatter::send(getAsyncReplyStream(), F("<r%d|%d|%d %d>\n"), stashP[1], stashP[2], stashP[0], result);
|
||||||
commitAsyncReplyStream();
|
commitAsyncReplyStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DCCEXParser::callback_Rloco(int result)
|
void DCCEXParser::callback_Rloco(int16_t result)
|
||||||
{
|
{
|
||||||
StringFormatter::send(getAsyncReplyStream(), F("<r %d>\n"), result);
|
StringFormatter::send(getAsyncReplyStream(), F("<r %d>\n"), result);
|
||||||
commitAsyncReplyStream();
|
commitAsyncReplyStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DCCEXParser::callback_Wloco(int result)
|
void DCCEXParser::callback_Wloco(int16_t result)
|
||||||
{
|
{
|
||||||
if (result==1) result=stashP[0]; // pick up original requested id from command
|
if (result==1) result=stashP[0]; // pick up original requested id from command
|
||||||
StringFormatter::send(getAsyncReplyStream(), F("<w %d>\n"), result);
|
StringFormatter::send(getAsyncReplyStream(), F("<w %d>\n"), result);
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include "FSH.h"
|
#include "FSH.h"
|
||||||
#include "RingStream.h"
|
#include "RingStream.h"
|
||||||
|
|
||||||
typedef void (*FILTER_CALLBACK)(Print * stream, byte & opcode, byte & paramCount, int p[]);
|
typedef void (*FILTER_CALLBACK)(Print * stream, byte & opcode, byte & paramCount, int16_t p[]);
|
||||||
typedef void (*AT_COMMAND_CALLBACK)(const byte * command);
|
typedef void (*AT_COMMAND_CALLBACK)(const byte * command);
|
||||||
|
|
||||||
struct DCCEXParser
|
struct DCCEXParser
|
||||||
@ -39,18 +39,18 @@ struct DCCEXParser
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static const int MAX_BUFFER=50; // longest command sent in
|
static const int16_t MAX_BUFFER=50; // longest command sent in
|
||||||
byte bufferLength=0;
|
byte bufferLength=0;
|
||||||
bool inCommandPayload=false;
|
bool inCommandPayload=false;
|
||||||
byte buffer[MAX_BUFFER+2];
|
byte buffer[MAX_BUFFER+2];
|
||||||
int splitValues( int result[MAX_COMMAND_PARAMS], const byte * command);
|
int16_t splitValues( int16_t result[MAX_COMMAND_PARAMS], const byte * command);
|
||||||
int splitHexValues( int result[MAX_COMMAND_PARAMS], const byte * command);
|
int16_t splitHexValues( int16_t result[MAX_COMMAND_PARAMS], const byte * command);
|
||||||
|
|
||||||
bool parseT(Print * stream, int params, int p[]);
|
bool parseT(Print * stream, int16_t params, int16_t p[]);
|
||||||
bool parseZ(Print * stream, int params, int p[]);
|
bool parseZ(Print * stream, int16_t params, int16_t p[]);
|
||||||
bool parseS(Print * stream, int params, int p[]);
|
bool parseS(Print * stream, int16_t params, int16_t p[]);
|
||||||
bool parsef(Print * stream, int params, int p[]);
|
bool parsef(Print * stream, int16_t params, int16_t p[]);
|
||||||
bool parseD(Print * stream, int params, int p[]);
|
bool parseD(Print * stream, int16_t params, int16_t p[]);
|
||||||
|
|
||||||
static Print * getAsyncReplyStream();
|
static Print * getAsyncReplyStream();
|
||||||
static void commitAsyncReplyStream();
|
static void commitAsyncReplyStream();
|
||||||
@ -60,19 +60,19 @@ struct DCCEXParser
|
|||||||
static Print * stashStream;
|
static Print * stashStream;
|
||||||
static RingStream * stashRingStream;
|
static RingStream * stashRingStream;
|
||||||
|
|
||||||
static int stashP[MAX_COMMAND_PARAMS];
|
static int16_t stashP[MAX_COMMAND_PARAMS];
|
||||||
bool stashCallback(Print * stream, int p[MAX_COMMAND_PARAMS], RingStream * ringStream);
|
bool stashCallback(Print * stream, int16_t p[MAX_COMMAND_PARAMS], RingStream * ringStream);
|
||||||
static void callback_W(int result);
|
static void callback_W(int16_t result);
|
||||||
static void callback_B(int result);
|
static void callback_B(int16_t result);
|
||||||
static void callback_R(int result);
|
static void callback_R(int16_t result);
|
||||||
static void callback_Rloco(int result);
|
static void callback_Rloco(int16_t result);
|
||||||
static void callback_Wloco(int result);
|
static void callback_Wloco(int16_t result);
|
||||||
static void callback_Vbit(int result);
|
static void callback_Vbit(int16_t result);
|
||||||
static void callback_Vbyte(int result);
|
static void callback_Vbyte(int16_t result);
|
||||||
static FILTER_CALLBACK filterCallback;
|
static FILTER_CALLBACK filterCallback;
|
||||||
static FILTER_CALLBACK filterRMFTCallback;
|
static FILTER_CALLBACK filterRMFTCallback;
|
||||||
static AT_COMMAND_CALLBACK atCommandCallback;
|
static AT_COMMAND_CALLBACK atCommandCallback;
|
||||||
static void funcmap(int cab, byte value, byte fstart, byte fstop);
|
static void funcmap(int16_t cab, byte value, byte fstart, byte fstop);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
55
DCCTimer.cpp
55
DCCTimer.cpp
@ -85,6 +85,61 @@ INTERRUPT_CALLBACK interruptHandler=0;
|
|||||||
mac[0] |= 0x02;
|
mac[0] |= 0x02;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(TEENSYDUINO)
|
||||||
|
IntervalTimer myDCCTimer;
|
||||||
|
|
||||||
|
void DCCTimer::begin(INTERRUPT_CALLBACK callback) {
|
||||||
|
interruptHandler=callback;
|
||||||
|
|
||||||
|
myDCCTimer.begin(interruptHandler, DCC_SIGNAL_TIME);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DCCTimer::isPWMPin(byte pin) {
|
||||||
|
//Teensy: digitalPinHasPWM, todo
|
||||||
|
return false; // TODO what are the relevant pins?
|
||||||
|
}
|
||||||
|
|
||||||
|
void DCCTimer::setPWM(byte pin, bool high) {
|
||||||
|
// TODO what are the relevant pins?
|
||||||
|
}
|
||||||
|
|
||||||
|
void DCCTimer::getSimulatedMacAddress(byte mac[6]) {
|
||||||
|
#if defined(__IMXRT1062__) //Teensy 4.0 and Teensy 4.1
|
||||||
|
uint32_t m1 = HW_OCOTP_MAC1;
|
||||||
|
uint32_t m2 = HW_OCOTP_MAC0;
|
||||||
|
mac[0] = m1 >> 8;
|
||||||
|
mac[1] = m1 >> 0;
|
||||||
|
mac[2] = m2 >> 24;
|
||||||
|
mac[3] = m2 >> 16;
|
||||||
|
mac[4] = m2 >> 8;
|
||||||
|
mac[5] = m2 >> 0;
|
||||||
|
#else
|
||||||
|
read_mac(mac);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(__IMXRT1062__)
|
||||||
|
void DCCTimer::read_mac(byte mac[6]) {
|
||||||
|
read(0xe,mac,0);
|
||||||
|
read(0xf,mac,3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://forum.pjrc.com/threads/91-teensy-3-MAC-address
|
||||||
|
void DCCTimer::read(uint8_t word, uint8_t *mac, uint8_t offset) {
|
||||||
|
FTFL_FCCOB0 = 0x41; // Selects the READONCE command
|
||||||
|
FTFL_FCCOB1 = word; // read the given word of read once area
|
||||||
|
|
||||||
|
// launch command and wait until complete
|
||||||
|
FTFL_FSTAT = FTFL_FSTAT_CCIF;
|
||||||
|
while(!(FTFL_FSTAT & FTFL_FSTAT_CCIF));
|
||||||
|
|
||||||
|
*(mac+offset) = FTFL_FCCOB5; // collect only the top three bytes,
|
||||||
|
*(mac+offset+1) = FTFL_FCCOB6; // in the right orientation (big endian).
|
||||||
|
*(mac+offset+2) = FTFL_FCCOB7; // Skip FTFL_FCCOB4 as it's always 0.
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
// Arduino nano, uno, mega etc
|
// Arduino nano, uno, mega etc
|
||||||
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||||
|
@ -10,6 +10,10 @@ class DCCTimer {
|
|||||||
static void getSimulatedMacAddress(byte mac[6]);
|
static void getSimulatedMacAddress(byte mac[6]);
|
||||||
static bool isPWMPin(byte pin);
|
static bool isPWMPin(byte pin);
|
||||||
static void setPWM(byte pin, bool high);
|
static void setPWM(byte pin, bool high);
|
||||||
|
#if (defined(TEENSYDUINO) && !defined(__IMXRT1062__))
|
||||||
|
static void read_mac(byte mac[6]);
|
||||||
|
static void read(uint8_t word, uint8_t *mac, uint8_t offset);
|
||||||
|
#endif
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,11 +25,9 @@
|
|||||||
#include "DIAG.h"
|
#include "DIAG.h"
|
||||||
#include "freeMemory.h"
|
#include "freeMemory.h"
|
||||||
|
|
||||||
|
|
||||||
DCCWaveform DCCWaveform::mainTrack(PREAMBLE_BITS_MAIN, true);
|
DCCWaveform DCCWaveform::mainTrack(PREAMBLE_BITS_MAIN, true);
|
||||||
DCCWaveform DCCWaveform::progTrack(PREAMBLE_BITS_PROG, false);
|
DCCWaveform DCCWaveform::progTrack(PREAMBLE_BITS_PROG, false);
|
||||||
|
|
||||||
|
|
||||||
bool DCCWaveform::progTrackSyncMain=false;
|
bool DCCWaveform::progTrackSyncMain=false;
|
||||||
bool DCCWaveform::progTrackBoosted=false;
|
bool DCCWaveform::progTrackBoosted=false;
|
||||||
int DCCWaveform::progTripValue=0;
|
int DCCWaveform::progTripValue=0;
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
#ifndef DCCWaveform_h
|
#ifndef DCCWaveform_h
|
||||||
#define DCCWaveform_h
|
#define DCCWaveform_h
|
||||||
|
|
||||||
#include "MotorDriver.h"
|
#include "MotorDriver.h"
|
||||||
|
|
||||||
// Wait times for power management. Unit: milliseconds
|
// Wait times for power management. Unit: milliseconds
|
||||||
|
@ -31,7 +31,12 @@
|
|||||||
#include "DCCEXParser.h"
|
#include "DCCEXParser.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h>
|
||||||
#include <Ethernet.h>
|
#if defined (ARDUINO_TEENSY41)
|
||||||
|
#include <NativeEthernet.h> //TEENSY Ethernet Treiber
|
||||||
|
#include <NativeEthernetUdp.h>
|
||||||
|
#else
|
||||||
|
#include "Ethernet.h"
|
||||||
|
#endif
|
||||||
#include "RingStream.h"
|
#include "RingStream.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -126,6 +126,10 @@ void MotorDriver::setSignal( bool high) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(ARDUINO_TEENSY32) || defined(ARDUINO_TEENSY35)|| defined(ARDUINO_TEENSY36)
|
||||||
|
volatile unsigned int overflow_count=0;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool MotorDriver::canMeasureCurrent() {
|
bool MotorDriver::canMeasureCurrent() {
|
||||||
return currentPin!=UNUSED_PIN;
|
return currentPin!=UNUSED_PIN;
|
||||||
}
|
}
|
||||||
@ -139,10 +143,22 @@ bool MotorDriver::canMeasureCurrent() {
|
|||||||
*/
|
*/
|
||||||
int MotorDriver::getCurrentRaw() {
|
int MotorDriver::getCurrentRaw() {
|
||||||
if (currentPin==UNUSED_PIN) return 0;
|
if (currentPin==UNUSED_PIN) return 0;
|
||||||
|
int current;
|
||||||
int current = analogRead(currentPin)-senseOffset;
|
#if defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41)
|
||||||
|
bool irq = disableInterrupts();
|
||||||
|
current = analogRead(currentPin)-senseOffset;
|
||||||
|
enableInterrupts(irq);
|
||||||
|
#elif defined(ARDUINO_TEENSY32) || defined(ARDUINO_TEENSY35)|| defined(ARDUINO_TEENSY36)
|
||||||
|
unsigned char sreg_backup;
|
||||||
|
sreg_backup = SREG; /* save interrupt enable/disable state */
|
||||||
|
cli();
|
||||||
|
current = analogRead(currentPin)-senseOffset;
|
||||||
|
overflow_count = 0;
|
||||||
|
SREG = sreg_backup; /* restore interrupt state */
|
||||||
|
#else
|
||||||
|
current = analogRead(currentPin)-senseOffset;
|
||||||
|
#endif
|
||||||
if (current<0) current=0-current;
|
if (current<0) current=0-current;
|
||||||
|
|
||||||
if ((faultPin != UNUSED_PIN) && isLOW(fastFaultPin) && isHIGH(fastPowerPin))
|
if ((faultPin != UNUSED_PIN) && isLOW(fastFaultPin) && isHIGH(fastPowerPin))
|
||||||
return (current == 0 ? -1 : -current);
|
return (current == 0 ? -1 : -current);
|
||||||
return current;
|
return current;
|
||||||
|
@ -26,11 +26,19 @@
|
|||||||
#define UNUSED_PIN 127 // inside int8_t
|
#define UNUSED_PIN 127 // inside int8_t
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__IMXRT1062__)
|
||||||
|
struct FASTPIN {
|
||||||
|
volatile uint32_t *inout;
|
||||||
|
uint32_t maskHIGH;
|
||||||
|
uint32_t maskLOW;
|
||||||
|
};
|
||||||
|
#else
|
||||||
struct FASTPIN {
|
struct FASTPIN {
|
||||||
volatile uint8_t *inout;
|
volatile uint8_t *inout;
|
||||||
uint8_t maskHIGH;
|
uint8_t maskHIGH;
|
||||||
uint8_t maskLOW;
|
uint8_t maskLOW;
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
class MotorDriver {
|
class MotorDriver {
|
||||||
public:
|
public:
|
||||||
@ -52,7 +60,6 @@ class MotorDriver {
|
|||||||
inline byte getFaultPin() {
|
inline byte getFaultPin() {
|
||||||
return faultPin;
|
return faultPin;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void getFastPin(const FSH* type,int pin, bool input, FASTPIN & result);
|
void getFastPin(const FSH* type,int pin, bool input, FASTPIN & result);
|
||||||
void getFastPin(const FSH* type,int pin, FASTPIN & result) {
|
void getFastPin(const FSH* type,int pin, FASTPIN & result) {
|
||||||
@ -66,5 +73,16 @@ class MotorDriver {
|
|||||||
int senseOffset;
|
int senseOffset;
|
||||||
unsigned int tripMilliamps;
|
unsigned int tripMilliamps;
|
||||||
int rawCurrentTripValue;
|
int rawCurrentTripValue;
|
||||||
|
#if defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41)
|
||||||
|
static bool disableInterrupts() {
|
||||||
|
uint32_t primask;
|
||||||
|
__asm__ volatile("mrs %0, primask\n" : "=r" (primask)::);
|
||||||
|
__disable_irq();
|
||||||
|
return (primask == 0) ? true : false;
|
||||||
|
}
|
||||||
|
static void enableInterrupts(bool doit) {
|
||||||
|
if (doit) __enable_irq();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
@ -388,7 +388,7 @@ WiThrottle * WiThrottle::stashInstance;
|
|||||||
byte WiThrottle::stashClient;
|
byte WiThrottle::stashClient;
|
||||||
char WiThrottle::stashThrottleChar;
|
char WiThrottle::stashThrottleChar;
|
||||||
|
|
||||||
void WiThrottle::getLocoCallback(int locoid) {
|
void WiThrottle::getLocoCallback(int16_t locoid) {
|
||||||
stashStream->mark(stashClient);
|
stashStream->mark(stashClient);
|
||||||
if (locoid<0) StringFormatter::send(stashStream,F("HMNo loco found on prog track\n"));
|
if (locoid<0) StringFormatter::send(stashStream,F("HMNo loco found on prog track\n"));
|
||||||
else {
|
else {
|
||||||
|
@ -67,7 +67,7 @@ class WiThrottle {
|
|||||||
static WiThrottle * stashInstance;
|
static WiThrottle * stashInstance;
|
||||||
static byte stashClient;
|
static byte stashClient;
|
||||||
static char stashThrottleChar;
|
static char stashThrottleChar;
|
||||||
static void getLocoCallback(int locoid);
|
static void getLocoCallback(int16_t locoid);
|
||||||
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
// WIFI_ON: All prereqs for running with WIFI are met
|
// WIFI_ON: All prereqs for running with WIFI are met
|
||||||
// Note: WIFI_CHANNEL may not exist in early config.h files so is added here if needed.
|
// Note: WIFI_CHANNEL may not exist in early config.h files so is added here if needed.
|
||||||
|
|
||||||
#if ENABLE_WIFI && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_SAMD_ZERO))
|
#if ENABLE_WIFI && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_SAMD_ZERO) || defined(TEENSYDUINO))
|
||||||
#define WIFI_ON true
|
#define WIFI_ON true
|
||||||
#ifndef WIFI_CHANNEL
|
#ifndef WIFI_CHANNEL
|
||||||
#define WIFI_CHANNEL 1
|
#define WIFI_CHANNEL 1
|
||||||
@ -32,7 +32,7 @@
|
|||||||
#define WIFI_ON false
|
#define WIFI_ON false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ENABLE_ETHERNET && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_SAMD_ZERO))
|
#if ENABLE_ETHERNET && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_SAMD_ZERO) || defined(TEENSYDUINO))
|
||||||
#define ETHERNET_ON true
|
#define ETHERNET_ON true
|
||||||
#else
|
#else
|
||||||
#define ETHERNET_ON false
|
#define ETHERNET_ON false
|
||||||
|
@ -34,7 +34,7 @@ extern char *__malloc_heap_start;
|
|||||||
|
|
||||||
static volatile int minimum_free_memory = __INT_MAX__;
|
static volatile int minimum_free_memory = __INT_MAX__;
|
||||||
|
|
||||||
|
#if !defined(__IMXRT1062__)
|
||||||
static inline int freeMemory() {
|
static inline int freeMemory() {
|
||||||
char top;
|
char top;
|
||||||
#if defined(__arm__)
|
#if defined(__arm__)
|
||||||
@ -46,6 +46,54 @@ static inline int freeMemory() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return low memory value.
|
||||||
|
int minimumFreeMemory() {
|
||||||
|
byte sreg_save = SREG;
|
||||||
|
noInterrupts(); // Disable interrupts
|
||||||
|
int retval = minimum_free_memory;
|
||||||
|
SREG = sreg_save; // Restore interrupt state
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
#if defined(ARDUINO_TEENSY40)
|
||||||
|
static const unsigned DTCM_START = 0x20000000UL;
|
||||||
|
static const unsigned OCRAM_START = 0x20200000UL;
|
||||||
|
static const unsigned OCRAM_SIZE = 512;
|
||||||
|
static const unsigned FLASH_SIZE = 1984;
|
||||||
|
#elif defined(ARDUINO_TEENSY41)
|
||||||
|
static const unsigned DTCM_START = 0x20000000UL;
|
||||||
|
static const unsigned OCRAM_START = 0x20200000UL;
|
||||||
|
static const unsigned OCRAM_SIZE = 512;
|
||||||
|
static const unsigned FLASH_SIZE = 7936;
|
||||||
|
#if TEENSYDUINO>151
|
||||||
|
extern "C" uint8_t external_psram_size;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline int freeMemory() {
|
||||||
|
extern unsigned long _ebss;
|
||||||
|
extern unsigned long _sdata;
|
||||||
|
extern unsigned long _estack;
|
||||||
|
const unsigned DTCM_START = 0x20000000UL;
|
||||||
|
unsigned dtcm = (unsigned)&_estack - DTCM_START;
|
||||||
|
unsigned stackinuse = (unsigned) &_estack - (unsigned) __builtin_frame_address(0);
|
||||||
|
unsigned varsinuse = (unsigned)&_ebss - (unsigned)&_sdata;
|
||||||
|
unsigned freemem = dtcm - (stackinuse + varsinuse);
|
||||||
|
return freemem;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return low memory value.
|
||||||
|
int minimumFreeMemory() {
|
||||||
|
//byte sreg_save = SREG;
|
||||||
|
//noInterrupts(); // Disable interrupts
|
||||||
|
int retval = minimum_free_memory;
|
||||||
|
//SREG = sreg_save; // Restore interrupt state
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Update low ram level. Allow for extra bytes to be specified
|
// Update low ram level. Allow for extra bytes to be specified
|
||||||
// by estimation or inspection, that may be used by other
|
// by estimation or inspection, that may be used by other
|
||||||
// called subroutines. Must be called with interrupts disabled.
|
// called subroutines. Must be called with interrupts disabled.
|
||||||
@ -61,11 +109,3 @@ void updateMinimumFreeMemory(unsigned char extraBytes) {
|
|||||||
if (spare < minimum_free_memory) minimum_free_memory = spare;
|
if (spare < minimum_free_memory) minimum_free_memory = spare;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return low memory value.
|
|
||||||
int minimumFreeMemory() {
|
|
||||||
byte sreg_save = SREG;
|
|
||||||
noInterrupts(); // Disable interrupts
|
|
||||||
int retval = minimum_free_memory;
|
|
||||||
SREG = sreg_save; // Restore interrupt state
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user