mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-12-23 21:01:25 +01:00
First checkin
This commit is contained in:
parent
e95a1a11a5
commit
2ebf1a6f66
67
.travis.yml
67
.travis.yml
@ -1,67 +0,0 @@
|
||||
# Continuous Integration (CI) is the practice, in software
|
||||
# engineering, of merging all developer working copies with a shared mainline
|
||||
# several times a day < https://docs.platformio.org/page/ci/index.html >
|
||||
#
|
||||
# Documentation:
|
||||
#
|
||||
# * Travis CI Embedded Builds with PlatformIO
|
||||
# < https://docs.travis-ci.com/user/integration/platformio/ >
|
||||
#
|
||||
# * PlatformIO integration with Travis CI
|
||||
# < https://docs.platformio.org/page/ci/travis.html >
|
||||
#
|
||||
# * User Guide for `platformio ci` command
|
||||
# < https://docs.platformio.org/page/userguide/cmd_ci.html >
|
||||
#
|
||||
#
|
||||
# Please choose one of the following templates (proposed below) and uncomment
|
||||
# it (remove "# " before each line) or use own configuration according to the
|
||||
# Travis CI documentation (see above).
|
||||
#
|
||||
|
||||
|
||||
#
|
||||
# Template #1: General project. Test it using existing `platformio.ini`.
|
||||
#
|
||||
|
||||
# language: python
|
||||
# python:
|
||||
# - "2.7"
|
||||
#
|
||||
# sudo: false
|
||||
# cache:
|
||||
# directories:
|
||||
# - "~/.platformio"
|
||||
#
|
||||
# install:
|
||||
# - pip install -U platformio
|
||||
# - platformio update
|
||||
#
|
||||
# script:
|
||||
# - platformio run
|
||||
|
||||
|
||||
#
|
||||
# Template #2: The project is intended to be used as a library with examples.
|
||||
#
|
||||
|
||||
# language: python
|
||||
# python:
|
||||
# - "2.7"
|
||||
#
|
||||
# sudo: false
|
||||
# cache:
|
||||
# directories:
|
||||
# - "~/.platformio"
|
||||
#
|
||||
# env:
|
||||
# - PLATFORMIO_CI_SRC=path/to/test/file.c
|
||||
# - PLATFORMIO_CI_SRC=examples/file.ino
|
||||
# - PLATFORMIO_CI_SRC=path/to/test/directory
|
||||
#
|
||||
# install:
|
||||
# - pip install -U platformio
|
||||
# - platformio update
|
||||
#
|
||||
# script:
|
||||
# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N
|
7
.vscode/extensions.json
vendored
7
.vscode/extensions.json
vendored
@ -1,7 +0,0 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
]
|
||||
}
|
67
CVReader.ino
Normal file
67
CVReader.ino
Normal file
@ -0,0 +1,67 @@
|
||||
#include "DCCWaveform.h"
|
||||
#include "DIAG.h"
|
||||
bool verifyCV(int cv, byte bValue);
|
||||
int readCv(int cv);
|
||||
const int cvnums[]={1,2,3,4,5,17,18,19,21,22,29};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
DCCWaveform::begin();
|
||||
Serial.println(F("CVReader"));
|
||||
|
||||
DIAG(F("\n===================================\n"));
|
||||
|
||||
for (byte x=0;x<sizeof(cvnums)/sizeof(cvnums[0]);x++) {
|
||||
DIAG(F("\n\nCV VERIFICATION %d = %s\n"),cvnums[x],readCV(cvnums[x])>=0?"OK":"FAIL");
|
||||
}
|
||||
|
||||
DIAG(F("\nProgram complete, press reset to retry"));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
}
|
||||
|
||||
byte cv1(byte opcode, int cv) {
|
||||
cv--;
|
||||
return (highByte(cv) & (byte)0x03) | opcode;
|
||||
}
|
||||
byte cv2(int cv) {
|
||||
cv--;
|
||||
return lowByte(cv);
|
||||
}
|
||||
|
||||
//// The functions below are lifted from the DCCApi for easy testing and experimentation.
|
||||
// Once reliable, tha DCCApi should be updated to match
|
||||
bool verifyCV(int cv, byte value) {
|
||||
|
||||
delay(2); // allow for decoder to quiesce latest pulse
|
||||
|
||||
|
||||
byte message[] = {
|
||||
cv1(0x74,cv) , // set-up to re-verify entire byte
|
||||
cv2(cv),
|
||||
value
|
||||
};
|
||||
|
||||
DCCWaveform::progTrack.schedulePacket(message, sizeof(message), 5);
|
||||
return DCCWaveform::progTrack.getAck();
|
||||
}
|
||||
|
||||
int readCV(int cv)
|
||||
{
|
||||
|
||||
byte message[]={ cv1(0x78,cv) , // any CV>1023 will become modulus(1024) due to bit-mask of 0x03
|
||||
cv2(cv),
|
||||
0}; // trailing zero will be updated in loop below
|
||||
|
||||
byte value = 0;
|
||||
|
||||
for (int i = 0; i<8; i++) {
|
||||
message[2] = 0xE8 + i;
|
||||
DCCWaveform::progTrack.schedulePacket(message,sizeof(message), 4); // NMRA recommends 5 rerad packets
|
||||
value+= (DCCWaveform::progTrack.getAck()<<i);
|
||||
}
|
||||
DIAG(F("\n*** READ CV %d = %d ******\n"),cv,value);
|
||||
return verifyCV(cv,value)?value:-1;
|
||||
}
|
235
DCCWaveform.cpp
Normal file
235
DCCWaveform.cpp
Normal file
@ -0,0 +1,235 @@
|
||||
#include <Arduino.h>
|
||||
#include <TimerThree.h>
|
||||
#include "DCCWaveform.h"
|
||||
#include "DIAG.h"
|
||||
DCCWaveform DCCWaveform::mainTrack(MAIN_POWER_PIN,MAIN_SIGNAL_PIN,MAIN_SENSE_PIN,PREAMBLE_BITS_MAIN,true);
|
||||
DCCWaveform DCCWaveform::progTrack(PROG_POWER_PIN,PROG_SIGNAL_PIN,PROG_SENSE_PIN,PREAMBLE_BITS_PROG,false);
|
||||
|
||||
void DCCWaveform::begin() {
|
||||
|
||||
Timer3.initialize(58);
|
||||
Timer3.disablePwm(MAIN_SIGNAL_PIN);
|
||||
Timer3.disablePwm(PROG_SIGNAL_PIN);
|
||||
Timer3.attachInterrupt(interruptHandler);
|
||||
mainTrack.beginTrack();
|
||||
progTrack.beginTrack();
|
||||
}
|
||||
|
||||
void DCCWaveform::loop() {
|
||||
mainTrack.checkPowerOverload();
|
||||
progTrack.checkPowerOverload();
|
||||
}
|
||||
|
||||
|
||||
// static //
|
||||
void DCCWaveform::interruptHandler() {
|
||||
// call the timer edge sensitive actions for progtrack and maintrack
|
||||
bool mainCall2=mainTrack.interrupt1();
|
||||
bool progCall2=progTrack.interrupt1();
|
||||
|
||||
// call (if necessary) the procs to get the current bits
|
||||
// these must complete within 50microsecs of the interrupt
|
||||
// but they are only called ONCE PER BIT TRANSMITTED
|
||||
// after the rising edge of the signal
|
||||
if (mainCall2) mainTrack.interrupt2();
|
||||
if (progCall2) progTrack.interrupt2();
|
||||
}
|
||||
|
||||
|
||||
// An instance of this class handles the DCC transmissions for one track. (main or prog)
|
||||
// Interrupts are marshalled via the statics.
|
||||
// A track has a current transmit buffer, and a pending buffer.
|
||||
// When the current buffer is exhausted, either the pending buffer (if there is one waiting) or an idle buffer.
|
||||
|
||||
|
||||
// This bitmask has 9 entries as each byte is trasmitted as a zero + 8 bits.
|
||||
const byte bitMask[]={0x00,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
|
||||
|
||||
|
||||
DCCWaveform::DCCWaveform(byte powerPinNo, byte directionPinNo, byte sensePinNo, byte preambleBits, bool isMain) {
|
||||
// establish appropriate pins
|
||||
powerPin=Arduino_to_GPIO_pin(powerPinNo);
|
||||
directionPin=Arduino_to_GPIO_pin(directionPinNo);
|
||||
sensePin=sensePinNo;
|
||||
isMainTrack=isMain;
|
||||
packetPending=false;
|
||||
memcpy(transmitPacket,idlePacket,sizeof(idlePacket));
|
||||
state=0;
|
||||
requiredPreambles=preambleBits;
|
||||
bytes_sent=0;
|
||||
bits_sent=0;
|
||||
nextSampleDue=0;
|
||||
}
|
||||
void DCCWaveform::beginTrack() {
|
||||
pinMode2f(powerPin,OUTPUT);
|
||||
pinMode2f(directionPin,OUTPUT);
|
||||
pinMode(sensePin,INPUT);
|
||||
setPowerMode(POWERMODE::ON);
|
||||
DIAG(F("\nTrack started sensePin=%d\n"),sensePin);
|
||||
}
|
||||
|
||||
POWERMODE DCCWaveform::getPowerMode() {
|
||||
return powerMode;
|
||||
}
|
||||
|
||||
void DCCWaveform::setPowerMode(POWERMODE mode) {
|
||||
powerMode=mode;
|
||||
digitalWrite2f(powerPin, mode==POWERMODE::ON ? HIGH:LOW);
|
||||
if (mode==POWERMODE::ON) schedulePacket(resetMessage,2,20);
|
||||
}
|
||||
|
||||
|
||||
void DCCWaveform::checkPowerOverload() {
|
||||
if (millis()<nextSampleDue) return;
|
||||
int current;
|
||||
int delay;
|
||||
|
||||
switch (powerMode) {
|
||||
case POWERMODE::OFF:
|
||||
delay=POWER_SAMPLE_OFF_WAIT;
|
||||
break;
|
||||
case POWERMODE::ON:
|
||||
// Check current
|
||||
current=analogRead(sensePin);
|
||||
if (current < POWER_SAMPLE_MAX) delay=POWER_SAMPLE_ON_WAIT;
|
||||
else {
|
||||
setPowerMode(POWERMODE::OVERLOAD);
|
||||
DIAG(F("\n*** %s TRACK POWER OVERLOAD pin=%d current=%d max=%d ***\n"),isMainTrack?"MAIN":"PROG",sensePin,current,POWER_SAMPLE_MAX);
|
||||
delay=POWER_SAMPLE_OVERLOAD_WAIT;
|
||||
}
|
||||
break;
|
||||
case POWERMODE::OVERLOAD:
|
||||
// Try setting it back on after the OVERLOAD_WAIT
|
||||
setPowerMode(POWERMODE::ON);
|
||||
delay=POWER_SAMPLE_ON_WAIT;
|
||||
break;
|
||||
default:
|
||||
delay=999; // cant get here..meaningless statement to avoid compiler warning.
|
||||
}
|
||||
nextSampleDue=millis()+delay;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// process time-edge sensitive part of interrupt
|
||||
// return true if second level required
|
||||
bool DCCWaveform::interrupt1() {
|
||||
// NOTE: this must consume transmission buffers even if the power is off
|
||||
// otherwise can cause hangs in main loop waiting for the pendingBuffer.
|
||||
switch (state) {
|
||||
case 0: // start of bit transmission
|
||||
digitalWrite2f(directionPin, HIGH);
|
||||
state = 1;
|
||||
return true; // must call interrupt2
|
||||
|
||||
case 1: // 58Ms after case 0
|
||||
if (currentBit) {
|
||||
digitalWrite2f(directionPin, LOW);
|
||||
state = 0;
|
||||
}
|
||||
else state = 2;
|
||||
break;
|
||||
case 2: digitalWrite2f(directionPin, LOW);
|
||||
state = 3;
|
||||
break;
|
||||
case 3: state = 0;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
void DCCWaveform::interrupt2() {
|
||||
// set currentBit to be the next bit to be sent.
|
||||
|
||||
if (remainingPreambles > 0 ) {
|
||||
currentBit=true;
|
||||
remainingPreambles--;
|
||||
return;
|
||||
}
|
||||
|
||||
// beware OF 9-BIT MASK generating a zero to start each byte
|
||||
currentBit=transmitPacket[bytes_sent] & bitMask[bits_sent];
|
||||
bits_sent++;
|
||||
|
||||
// If this is the last bit of a byte, prepare for the next byte
|
||||
|
||||
if (bits_sent==9) { // zero followed by 8 bits of a byte
|
||||
//end of Byte
|
||||
bits_sent=0;
|
||||
bytes_sent++;
|
||||
// if this is the last byte, prepere for next packet
|
||||
if (bytes_sent >= transmitLength) {
|
||||
// end of transmission buffer... repeat or switch to next message
|
||||
bytes_sent = 0;
|
||||
remainingPreambles=requiredPreambles;
|
||||
|
||||
if (transmitRepeats > 0) {
|
||||
transmitRepeats--;
|
||||
}
|
||||
else if (packetPending) {
|
||||
// Copy pending packet to transmit packet
|
||||
for (int b=0;b<pendingLength;b++) transmitPacket[b]= pendingPacket[b];
|
||||
transmitLength=pendingLength;
|
||||
transmitRepeats=pendingRepeats;
|
||||
packetPending=false;
|
||||
}
|
||||
else {
|
||||
// Fortunately reset and idle packets are the same length
|
||||
memcpy( transmitPacket,isMainTrack?idlePacket:resetPacket, sizeof(idlePacket));
|
||||
transmitLength=sizeof(idlePacket);
|
||||
transmitRepeats=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Wait until there is no packet pending, then make this pending
|
||||
void DCCWaveform::schedulePacket(const byte buffer[], byte byteCount, byte repeats) {
|
||||
if (byteCount>=MAX_PACKET_SIZE) return; // allow for chksum
|
||||
while(packetPending) delay(1);
|
||||
|
||||
byte checksum=0;
|
||||
for (int b=0;b<byteCount; b++) {
|
||||
checksum^=buffer[b];
|
||||
pendingPacket[b]=buffer[b];
|
||||
}
|
||||
pendingPacket[byteCount]=checksum;
|
||||
pendingLength=byteCount+1;
|
||||
pendingRepeats=repeats;
|
||||
packetPending=true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool DCCWaveform::getAck()
|
||||
{
|
||||
|
||||
if (isMainTrack) return false; // cant do this on main track
|
||||
|
||||
while(packetPending) delay(1); // wait until transmitter has gont into reset packets
|
||||
delay(20); // time for enough resets
|
||||
unsigned long timeout=millis()+ACK_TIMEOUT;
|
||||
int maxCurrent=0;
|
||||
bool result=false;
|
||||
int upsamples=0;
|
||||
int downsamples=0;
|
||||
while(result==false && timeout>millis()) {
|
||||
upsamples++;
|
||||
delay(1);
|
||||
int current=analogRead(sensePin);
|
||||
maxCurrent=max(maxCurrent,current);
|
||||
result=current > ACK_MIN_PULSE;
|
||||
}
|
||||
if (result) while( true) {
|
||||
downsamples++;
|
||||
delay(1);
|
||||
int current=analogRead(sensePin);
|
||||
maxCurrent=max(maxCurrent,current);
|
||||
if (current<= ACK_MAX_NOT_PULSE)break;
|
||||
}
|
||||
DIAG(F("\nack=%d max=%d, up=%d, down=%d "),result,maxCurrent, upsamples,downsamples);
|
||||
return result;
|
||||
}
|
89
DCCWaveform.h
Normal file
89
DCCWaveform.h
Normal file
@ -0,0 +1,89 @@
|
||||
#include <DIO2.h>
|
||||
// This hardware configuration would normally be setup in a .h file elsewhere
|
||||
const byte MAIN_POWER_PIN=3;
|
||||
const byte MAIN_SIGNAL_PIN=12;
|
||||
const byte MAIN_SENSE_PIN=A0;
|
||||
|
||||
const byte PROG_POWER_PIN=11;
|
||||
const byte PROG_SIGNAL_PIN=13;
|
||||
const byte PROG_SENSE_PIN=A1;
|
||||
|
||||
const int POWER_SAMPLE_MAX=300;
|
||||
const int POWER_SAMPLE_ON_WAIT=100;
|
||||
const int POWER_SAMPLE_OFF_WAIT=1000;
|
||||
const int POWER_SAMPLE_OVERLOAD_WAIT=4000;
|
||||
|
||||
|
||||
// ACK current analogRead values (vary depending on motor shield and cpu voltage)
|
||||
const int ACK_TIMEOUT = 5 ; // millis getAck is prepared to wait for a signal
|
||||
const int ACK_MAX_NOT_PULSE = 10 ; // current below which this is NOT a pulse any more
|
||||
const int ACK_MIN_PULSE = 50 ; // current above which a pulse is recognised
|
||||
|
||||
const int PREAMBLE_BITS_MAIN=16;
|
||||
const int PREAMBLE_BITS_PROG=22;
|
||||
|
||||
const byte MAX_PACKET_SIZE=12;
|
||||
// NOTE: static functions are used for the overall controller, then
|
||||
// one instance is created for each track.
|
||||
|
||||
|
||||
enum class POWERMODE { OFF, ON, OVERLOAD };
|
||||
const byte idleMessage[]={0xFF,0x00};
|
||||
const byte resetMessage[]={0x00,0x00};
|
||||
const byte idlePacket[]={0xFF,0x00,0xFF};
|
||||
const byte resetPacket[]={0x00,0x00,0x00};
|
||||
|
||||
class DCCWaveform {
|
||||
public:
|
||||
DCCWaveform(byte powerPinNo, byte directionPinNo, byte sensePinNo, byte preambleBits, bool isMain);
|
||||
static void begin();
|
||||
static void loop();
|
||||
static DCCWaveform mainTrack;
|
||||
static DCCWaveform progTrack;
|
||||
|
||||
void beginTrack();
|
||||
void setPowerMode(POWERMODE);
|
||||
POWERMODE getPowerMode();
|
||||
void checkPowerOverload();
|
||||
void schedulePacket(const byte buffer[], byte byteCount, byte repeats);
|
||||
volatile bool packetPending;
|
||||
bool startAckProcess();
|
||||
bool getAck();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
static void interruptHandler();
|
||||
bool interrupt1();
|
||||
void interrupt2();
|
||||
|
||||
POWERMODE powerMode;
|
||||
|
||||
// Transmission controller
|
||||
byte transmitPacket[MAX_PACKET_SIZE]; // packet being transmitted
|
||||
byte transmitLength;
|
||||
byte transmitRepeats; // remaining repeats of transmission
|
||||
byte remainingPreambles;
|
||||
byte requiredPreambles;
|
||||
bool currentBit; // bit to be transmitted
|
||||
|
||||
byte bits_sent; // 0-8 (yes 9 bits) sent for current byte
|
||||
byte bytes_sent; // number of bytes sent from transmitPacket
|
||||
|
||||
byte state; // wave generator state machine
|
||||
|
||||
byte pendingPacket[MAX_PACKET_SIZE];
|
||||
byte pendingLength;
|
||||
byte pendingRepeats;
|
||||
|
||||
// Hardware pins
|
||||
GPIO_pin_t directionPin;
|
||||
GPIO_pin_t powerPin;
|
||||
|
||||
// current sampling
|
||||
bool isMainTrack;
|
||||
byte sensePin;
|
||||
unsigned long nextSampleDue;
|
||||
int ackBaseCurrent;
|
||||
|
||||
};
|
27
DIAG.cpp
Normal file
27
DIAG.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include <arduino.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
void Serialprint(const __FlashStringHelper* input...) {
|
||||
// thanks to Jan Turoň https://arduino.stackexchange.com/questions/56517/formatting-strings-in-arduino-for-output
|
||||
|
||||
va_list args;
|
||||
va_start(args, input);
|
||||
char* flash=(char*)input;
|
||||
for(int i=0; ; ++i) {
|
||||
char c=pgm_read_byte_near(flash+i);
|
||||
if (c=='\0') return;
|
||||
if(c!='%') { Serial.print(c); continue; }
|
||||
i++;
|
||||
c=pgm_read_byte_near(flash+i);
|
||||
switch(c) {
|
||||
case '%': Serial.print('%'); break;
|
||||
case 's': Serial.print(va_arg(args, char*)); break;
|
||||
case 'd': Serial.print(va_arg(args, int), DEC); break;
|
||||
case 'b': Serial.print(va_arg(args, int), BIN); break;
|
||||
case 'o': Serial.print(va_arg(args, int), OCT); break;
|
||||
case 'x': Serial.print(va_arg(args, int), HEX); break;
|
||||
case 'f': Serial.print(va_arg(args, double), 2); break;
|
||||
}
|
||||
}
|
||||
va_end(args);
|
||||
}
|
5
DIAG.h
Normal file
5
DIAG.h
Normal file
@ -0,0 +1,5 @@
|
||||
void Serialprint(const __FlashStringHelper* input...);
|
||||
#ifndef DIAG_ENABLED
|
||||
#define DIAG_ENABLED true
|
||||
#endif
|
||||
#define DIAG if (DIAG_ENABLED) Serialprint
|
@ -1,39 +0,0 @@
|
||||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the usual convention is to give header files names that end with `.h'.
|
||||
It is most portable to use only letters, digits, dashes, and underscores in
|
||||
header file names, and at most one dot.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
46
lib/README
46
lib/README
@ -1,46 +0,0 @@
|
||||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into executable file.
|
||||
|
||||
The source code of each library should be placed in a an own separate directory
|
||||
("lib/your_library_name/[here are source files]").
|
||||
|
||||
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
and a contents of `src/main.c`:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
@ -1,14 +0,0 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:megaatmega1280]
|
||||
platform = atmelavr
|
||||
board = megaatmega1280
|
||||
framework = arduino
|
10
src/main.cpp
10
src/main.cpp
@ -1,10 +0,0 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println(F("CVReader"));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// put your main code here, to run repeatedly:
|
||||
}
|
11
test/README
11
test/README
@ -1,11 +0,0 @@
|
||||
|
||||
This directory is intended for PIO Unit Testing and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PIO Unit Testing:
|
||||
- https://docs.platformio.org/page/plus/unit-testing.html
|
Loading…
Reference in New Issue
Block a user