Init fork from Stuart Robinson's repo
This commit is contained in:
@ -0,0 +1,200 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 19/03/22
|
||||
|
||||
This program is supplied as is, it is up to the user of the program to decide if the program is
|
||||
suitable for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
/*******************************************************************************************************
|
||||
Program Operation - This is a program for receiving files transmitted by LoRa and saving them to SD card
|
||||
and then optionally transfering them to a PC using a second serial port and the Ymodem protocol. Arduino
|
||||
DUEs were used for testing the program, these have multiple hardware Serial ports.
|
||||
|
||||
Progress messages on the transfer are sent to the IDE Serial monitor and printed on a connected ILI9341
|
||||
TFT display.
|
||||
|
||||
For details of the PC upload process see here;
|
||||
|
||||
https://stuartsprojects.github.io/2022/01/01/StuartCAM-ESP32CAM-Getting-the-Pictures-Onto-a-PC.html
|
||||
|
||||
|
||||
Serial monitor baud rate is set at 115200.
|
||||
*******************************************************************************************************/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <SX128XLT.h>
|
||||
#include <ProgramLT_Definitions.h>
|
||||
|
||||
#define USELORA //enable this define to use LoRa packets
|
||||
//#define USEFLRC //enable this define to use FLRC packets
|
||||
#include "Settings.h" //LoRa settings etc.
|
||||
SX128XLT LoRa; //create an SX128XLT library instance called LoRa, required by SDtransfer
|
||||
|
||||
//#define SDLIB //define SDLIB for SD.h or SDFATLIB for SDfat.h
|
||||
#define SDFATLIB
|
||||
#include "DTSDlibrary.h"
|
||||
|
||||
#include "Adafruit_GFX.h" //get library here > https://github.com/adafruit/Adafruit-GFX-Library
|
||||
#include "Adafruit_ILI9341.h" //get library here > https://github.com/adafruit/Adafruit_ILI9341
|
||||
Adafruit_ILI9341 disp = Adafruit_ILI9341(DISPCS, DISPDC, DISPRESET); //for dispaly defaults, textsize and rotation, see Settings.h
|
||||
|
||||
#define ENABLEMONITOR //enable monitor prints
|
||||
#define PRINTSEGMENTNUM
|
||||
#define ENABLEFILECRC //enable this define to uses and show file CRCs
|
||||
//#define DISABLEPAYLOADCRC //enable this define if you want to disable payload CRC checking
|
||||
//#define DEBUG //see additional debug info
|
||||
#define ENABLEPCTRANSFER //enable this define for YModem transfer to PC
|
||||
|
||||
#include "SDtransferDisplay.h" //library of data transfer with display functions
|
||||
#include "YModem.h" //YModem for the the save SD File
|
||||
|
||||
uint32_t bytestransfered; //bytes transfered via YModem
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
SDreceiveaPacketDT();
|
||||
|
||||
#ifdef ENABLEPCTRANSFER
|
||||
if (SDDTFileSaved)
|
||||
{
|
||||
Monitorport.println(F("File saved to SD - start YModem transfer to PC"));
|
||||
setCursor(0, 4);
|
||||
disp.print(F("Run YModem"));
|
||||
digitalWrite(LED1, HIGH);
|
||||
setCursor(0, 6);
|
||||
disp.print(F(" ")); //clear segment number
|
||||
|
||||
bytestransfered = yModemSend(SDDTfilenamebuff, 1, 1);
|
||||
|
||||
if (bytestransfered > 0)
|
||||
{
|
||||
Monitorport.print(F("YModem transfer completed "));
|
||||
Monitorport.print(bytestransfered);
|
||||
Monitorport.println(F(" bytes sent"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Monitorport.println(F("YModem transfer FAILED"));
|
||||
}
|
||||
Monitorport.println();
|
||||
|
||||
setCursor(0, 4);
|
||||
disp.print(F(" "));
|
||||
digitalWrite(LED1, LOW);
|
||||
SDDTFileSaved = false;
|
||||
//Monitorport.println(F("YModem transfer finished"));
|
||||
//Monitorport.println();
|
||||
Monitorport.println(F("Wait for file"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void led_Flash(uint16_t flashes, uint16_t delaymS)
|
||||
{
|
||||
uint16_t index;
|
||||
for (index = 1; index <= flashes; index++)
|
||||
{
|
||||
digitalWrite(LED1, HIGH);
|
||||
delay(delaymS);
|
||||
digitalWrite(LED1, LOW);
|
||||
delay(delaymS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
pinMode(LED1, OUTPUT); //setup pin as output for indicator LED
|
||||
led_Flash(2, 125); //two quick LED flashes to indicate program start
|
||||
SDsetLED(LED1); //setup LED pin for data transfer indicator
|
||||
|
||||
YModemSerial.begin(115200);
|
||||
|
||||
#ifdef ENABLEMONITOR
|
||||
Monitorport.begin(115200);
|
||||
Monitorport.println();
|
||||
Monitorport.println(F(__FILE__));
|
||||
#endif
|
||||
|
||||
SPI.begin();
|
||||
|
||||
if (LoRa.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
|
||||
{
|
||||
led_Flash(2, 125);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef ENABLEMONITOR
|
||||
Monitorport.println(F("LoRa device error"));
|
||||
#endif
|
||||
while (1)
|
||||
{
|
||||
led_Flash(50, 50); //long fast speed flash indicates device error
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USELORA
|
||||
LoRa.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate);
|
||||
Serial.println(F("Using LoRa packets"));
|
||||
#endif
|
||||
|
||||
#ifdef USEFLRC
|
||||
LoRa.setupFLRC(Frequency, Offset, BandwidthBitRate, CodingRate, BT, Syncword);
|
||||
Serial.println(F("Using FLRC packets"));
|
||||
#endif
|
||||
|
||||
#ifdef ENABLEMONITOR
|
||||
Monitorport.println();
|
||||
Monitorport.print(F("Initializing SD card..."));
|
||||
#endif
|
||||
|
||||
if (DTSD_initSD(SDCS))
|
||||
{
|
||||
Monitorport.println(F("SD Card initialized."));
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef ENABLEMONITOR
|
||||
Monitorport.println(F("SD Card failed, or not present."));
|
||||
#endif
|
||||
while (1) led_Flash(100, 50);
|
||||
}
|
||||
|
||||
#ifdef ENABLEMONITOR
|
||||
Monitorport.println();
|
||||
#endif
|
||||
|
||||
#ifdef DISABLEPAYLOADCRC
|
||||
LoRa.setReliableConfig(NoReliableCRC);
|
||||
#endif
|
||||
|
||||
if (LoRa.getReliableConfig(NoReliableCRC))
|
||||
{
|
||||
Monitorport.println(F("Payload CRC disabled"));
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef ENABLEMONITOR
|
||||
Monitorport.println(F("Payload CRC enabled"));
|
||||
#endif
|
||||
}
|
||||
|
||||
disp.begin();
|
||||
disp.fillScreen(ILI9341_BLACK);
|
||||
disp.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
|
||||
disp.setRotation(rotation);
|
||||
disp.setTextSize(textscale);
|
||||
setCursor(0, 0);
|
||||
disp.print(F("Waiting File"));
|
||||
|
||||
SDDTSegmentNext = 0;
|
||||
SDDTFileOpened = false;
|
||||
SDDTFileSaved = false; //file has not been saved to SD yet
|
||||
|
||||
#ifdef ENABLEMONITOR
|
||||
Monitorport.println(F("SDfile transfer receiver ready"));
|
||||
Monitorport.println();
|
||||
#endif
|
||||
}
|
||||
@ -0,0 +1,461 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 19/03/22
|
||||
|
||||
This code is supplied as is, it is up to the user of the program to decide if the program is suitable
|
||||
for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
#ifdef SDFATLIB
|
||||
#include <SdFat.h>
|
||||
SdFat SD;
|
||||
File dataFile; //name the file instance needed for SD library routines
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SDLIB
|
||||
#include <SD.h>
|
||||
File dataFile; //name the file instance needed for SD library routines
|
||||
#endif
|
||||
|
||||
#ifndef Monitorport
|
||||
#define Monitorport Serial //output to Serial if no other port defined
|
||||
#endif
|
||||
|
||||
bool DTSD_dumpFileASCII(char *buff);
|
||||
bool DTSD_dumpFileHEX(char *buff);
|
||||
bool DTSD_dumpSegmentHEX(uint8_t segmentsize);
|
||||
bool DTSD_initSD(uint8_t CSpin);
|
||||
uint32_t DTSD_getFileSize(char *buff);
|
||||
void DTSD_printDirectory();
|
||||
uint32_t DTSD_openFileRead(char *buff);
|
||||
uint16_t DTSD_getNumberSegments(uint32_t filesize, uint8_t segmentsize);
|
||||
uint8_t DTSD_getLastSegmentSize(uint32_t filesize, uint8_t segmentsize);
|
||||
bool DTSD_openNewFileWrite(char *buff);
|
||||
bool DTSD_openFileWrite(char *buff, uint32_t position);
|
||||
uint8_t DTSD_readFileSegment(uint8_t *buff, uint8_t segmentsize);
|
||||
uint8_t DTSD_writeSegmentFile(uint8_t *buff, uint8_t segmentsize);
|
||||
void DTSD_seekFileLocation(uint32_t position);
|
||||
uint16_t DTSD_createFile(char *buff);
|
||||
uint16_t DTSD_fileCRCCCITT();
|
||||
void DTSD_fileFlush();
|
||||
void DTSD_closeFile();
|
||||
void printDirectorySD(File dir, int numTabs);
|
||||
|
||||
|
||||
bool DTSD_dumpFileASCII(char *buff)
|
||||
{
|
||||
|
||||
File dataFile = SD.open(buff); //open the test file note that only one file can be open at a time,
|
||||
|
||||
if (dataFile) //if the file is available, read from it
|
||||
{
|
||||
while (dataFile.available())
|
||||
{
|
||||
Monitorport.write(dataFile.read());
|
||||
}
|
||||
dataFile.close();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DTSD_dumpFileHEX(char *buff)
|
||||
{
|
||||
//Note, this function will return true if the SD card is removed.
|
||||
uint16_t Loopv1, Loopv2;
|
||||
uint8_t fileData;
|
||||
uint32_t filesize;
|
||||
|
||||
if (!SD.exists(buff))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
dataFile = SD.open(buff);
|
||||
filesize = dataFile.size();
|
||||
filesize--; //file data locations are from 0 to (filesize -1);
|
||||
Monitorport.print(F("Lcn 0 1 2 3 4 5 6 7 8 9 A B C D E F"));
|
||||
Monitorport.println();
|
||||
|
||||
if (dataFile) //if the file is available, read from it
|
||||
{
|
||||
while (dataFile.available())
|
||||
{
|
||||
for (Loopv1 = 0; Loopv1 <= filesize;)
|
||||
{
|
||||
Monitorport.print(F("0x"));
|
||||
if (Loopv1 < 0x10)
|
||||
{
|
||||
Monitorport.print(F("0"));
|
||||
}
|
||||
Monitorport.print((Loopv1), HEX);
|
||||
Monitorport.print(F(" "));
|
||||
for (Loopv2 = 0; Loopv2 <= 15; Loopv2++)
|
||||
{
|
||||
fileData = dataFile.read();
|
||||
if (fileData < 0x10)
|
||||
{
|
||||
Monitorport.print(F("0"));
|
||||
}
|
||||
Monitorport.print(fileData, HEX);
|
||||
Monitorport.print(F(" "));
|
||||
Loopv1++;
|
||||
}
|
||||
Monitorport.println();
|
||||
}
|
||||
}
|
||||
dataFile.close();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Monitorport.println(F("File not available"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DTSD_initSD(uint8_t CSpin)
|
||||
{
|
||||
if (SD.begin(CSpin))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t DTSD_getFileSize(char *buff)
|
||||
{
|
||||
uint32_t filesize;
|
||||
|
||||
if (!SD.exists(buff))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
dataFile = SD.open(buff);
|
||||
filesize = dataFile.size();
|
||||
dataFile.close();
|
||||
return filesize;
|
||||
}
|
||||
|
||||
|
||||
#ifdef SDFATLIB
|
||||
void DTSD_printDirectory()
|
||||
{
|
||||
dataFile = SD.open("/");
|
||||
Monitorport.println(F("Card directory"));
|
||||
SD.ls("/", LS_R);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SDLIB
|
||||
void DTSD_printDirectory()
|
||||
{
|
||||
dataFile = SD.open("/");
|
||||
|
||||
printDirectorySD(dataFile, 0);
|
||||
|
||||
Monitorport.println();
|
||||
}
|
||||
|
||||
|
||||
void printDirectorySD(File dir, int numTabs)
|
||||
{
|
||||
|
||||
while (true)
|
||||
{
|
||||
File entry = dir.openNextFile();
|
||||
|
||||
if (! entry)
|
||||
{
|
||||
//no more files
|
||||
break;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < numTabs; i++)
|
||||
{
|
||||
Monitorport.print('\t');
|
||||
}
|
||||
|
||||
Monitorport.print(entry.name());
|
||||
|
||||
if (entry.isDirectory())
|
||||
{
|
||||
Monitorport.println("/");
|
||||
printDirectorySD(entry, numTabs + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// files have sizes, directories do not
|
||||
Monitorport.print("\t\t");
|
||||
Monitorport.println(entry.size(), DEC);
|
||||
}
|
||||
entry.close();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool DTSD_dumpSegmentHEX(uint8_t segmentsize)
|
||||
{
|
||||
uint16_t Loopv1, Loopv2;
|
||||
uint8_t fileData;
|
||||
|
||||
Monitorport.print(F("Print segment of "));
|
||||
Monitorport.print(segmentsize);
|
||||
Monitorport.println(F(" bytes"));
|
||||
Monitorport.print(F("Lcn 0 1 2 3 4 5 6 7 8 9 A B C D E F"));
|
||||
Monitorport.println();
|
||||
|
||||
if (dataFile) //if the file is available, read from it
|
||||
{
|
||||
for (Loopv1 = 0; Loopv1 < segmentsize;)
|
||||
{
|
||||
Monitorport.print(F("0x"));
|
||||
if (Loopv1 < 0x10)
|
||||
{
|
||||
Monitorport.print(F("0"));
|
||||
}
|
||||
Monitorport.print((Loopv1), HEX);
|
||||
Monitorport.print(F(" "));
|
||||
for (Loopv2 = 0; Loopv2 <= 15; Loopv2++)
|
||||
{
|
||||
//stop printing if all of segment has been printed
|
||||
if (Loopv1 < segmentsize)
|
||||
{
|
||||
fileData = dataFile.read();
|
||||
if (fileData < 0x10)
|
||||
{
|
||||
Monitorport.print(F("0"));
|
||||
}
|
||||
Monitorport.print(fileData, HEX);
|
||||
Monitorport.print(F(" "));
|
||||
Loopv1++;
|
||||
}
|
||||
}
|
||||
Monitorport.println();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t DTSD_openFileRead2(char *buff)
|
||||
{
|
||||
uint32_t filesize;
|
||||
|
||||
dataFile = SD.open(buff);
|
||||
filesize = dataFile.size();
|
||||
dataFile.seek(0);
|
||||
return filesize;
|
||||
}
|
||||
|
||||
|
||||
uint32_t DTSD_openFileRead(char *buff)
|
||||
{
|
||||
uint32_t filesize;
|
||||
|
||||
if (SD.exists(buff))
|
||||
{
|
||||
//Monitorport.println(F("File exists"));
|
||||
dataFile = SD.open(buff);
|
||||
filesize = dataFile.size();
|
||||
dataFile.seek(0);
|
||||
return filesize;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Monitorport.println(F("File does not exist"));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint16_t DTSD_getNumberSegments(uint32_t filesize, uint8_t segmentsize)
|
||||
{
|
||||
uint16_t segments;
|
||||
segments = filesize / segmentsize;
|
||||
|
||||
if ((filesize % segmentsize) > 0)
|
||||
{
|
||||
segments++;
|
||||
}
|
||||
return segments;
|
||||
}
|
||||
|
||||
|
||||
uint8_t DTSD_getLastSegmentSize(uint32_t filesize, uint8_t segmentsize)
|
||||
{
|
||||
uint8_t lastsize;
|
||||
|
||||
lastsize = filesize % segmentsize;
|
||||
if (lastsize == 0)
|
||||
{
|
||||
lastsize = segmentsize;
|
||||
}
|
||||
return lastsize;
|
||||
}
|
||||
|
||||
|
||||
bool DTSD_openNewFileWrite(char *buff)
|
||||
{
|
||||
if (SD.exists(buff))
|
||||
{
|
||||
//Monitorport.print(buff);
|
||||
//Monitorport.println(F(" File exists - deleting"));
|
||||
SD.remove(buff);
|
||||
}
|
||||
|
||||
if (dataFile = SD.open(buff, FILE_WRITE))
|
||||
{
|
||||
//Monitorport.print(buff);
|
||||
//Monitorport.println(F(" SD File opened"));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Monitorport.print(buff);
|
||||
//Monitorport.println(F(" ERROR opening file"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DTSD_openFileWrite(char *buff, uint32_t position)
|
||||
{
|
||||
dataFile = SD.open(buff, FILE_WRITE); //seems to operate as append
|
||||
dataFile.seek(position); //seek to first position in file
|
||||
|
||||
if (dataFile)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t DTSD_readFileSegment(uint8_t *buff, uint8_t segmentsize)
|
||||
{
|
||||
uint8_t index = 0;
|
||||
uint8_t fileData;
|
||||
|
||||
while (index < segmentsize)
|
||||
{
|
||||
fileData = (uint8_t) dataFile.read();
|
||||
buff[index] = fileData;
|
||||
index++;
|
||||
};
|
||||
|
||||
if (index == segmentsize)
|
||||
{
|
||||
return segmentsize; //if all written return segment size
|
||||
}
|
||||
else
|
||||
{
|
||||
return index - 1; //if not all written return number bytes read
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t DTSD_writeSegmentFile(uint8_t *buff, uint8_t segmentsize)
|
||||
{
|
||||
uint8_t index, byteswritten = 0;
|
||||
|
||||
for (index = 0; index < segmentsize; index++)
|
||||
{
|
||||
dataFile.write(buff[index]);
|
||||
byteswritten++;
|
||||
}
|
||||
return byteswritten;
|
||||
}
|
||||
|
||||
|
||||
void DTSD_seekFileLocation(uint32_t position)
|
||||
{
|
||||
dataFile.seek(position); //seek to position in file
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
uint16_t DTSD_createFile(char *buff)
|
||||
{
|
||||
//creats a new filename use this definition as the base;
|
||||
//char filename[] = "/SD0000.txt"; //filename used as base for creating logfile, 0000 replaced with numbers
|
||||
//the 0000 in the filename is replaced with the next number avaialable
|
||||
|
||||
uint16_t index;
|
||||
|
||||
for (index = 1; index <= 9999; index++) {
|
||||
buff[3] = index / 1000 + '0';
|
||||
buff[4] = ((index % 1000) / 100) + '0';
|
||||
buff[5] = ((index % 100) / 10) + '0';
|
||||
buff[6] = index % 10 + '0' ;
|
||||
if (! SD.exists(buff))
|
||||
{
|
||||
// only open a new file if it doesn't exist
|
||||
dataFile = SD.open(buff, FILE_WRITE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dataFile)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return index; //return number of logfile created
|
||||
}
|
||||
|
||||
|
||||
uint16_t DTSD_fileCRCCCITT(uint32_t fsize)
|
||||
{
|
||||
uint32_t index;
|
||||
uint16_t CRCcalc;
|
||||
uint8_t j, filedata;
|
||||
|
||||
CRCcalc = 0xFFFF; //start value for CRC16
|
||||
|
||||
for (index = 0; index < fsize; index++)
|
||||
{
|
||||
filedata = dataFile.read();
|
||||
CRCcalc ^= (((uint16_t) filedata ) << 8);
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
if (CRCcalc & 0x8000)
|
||||
CRCcalc = (CRCcalc << 1) ^ 0x1021;
|
||||
else
|
||||
CRCcalc <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return CRCcalc;
|
||||
}
|
||||
|
||||
|
||||
void DTSD_fileFlush()
|
||||
{
|
||||
dataFile.flush();
|
||||
}
|
||||
|
||||
|
||||
void DTSD_closeFile()
|
||||
{
|
||||
dataFile.close(); //close local file
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,71 @@
|
||||
/*******************************************************************************************************
|
||||
Programs for Arduino - Copyright of the author Stuart Robinson - 19/03/22
|
||||
|
||||
This program is supplied as is, it is up to the user of the program to decide if the program is
|
||||
suitable for the intended purpose and free from errors.
|
||||
*******************************************************************************************************/
|
||||
|
||||
#define NSS 10 //select on LoRa device
|
||||
#define NRESET 9 //reset on LoRa device
|
||||
#define RFBUSY 7 //RFBUSY pin on LoRa device
|
||||
#define DIO1 3 //DIO1 on LoRa device, used for RX and TX done
|
||||
#define LED1 8 //On board LED, high for on
|
||||
#define SDCS 30 //select pin for SD card
|
||||
|
||||
#define LORA_DEVICE DEVICE_SX1280 //this is the device we are using
|
||||
|
||||
#define DISPCS 23 //CS for ILI9341
|
||||
#define DISPDC 24 //DC for ILI9341
|
||||
#define DISPRESET 25 //RESET for ILI9341
|
||||
#define TOUCHCS 29 //ILI9341 may have touch ICs, so we need to disable it, set to -1 if not fitted
|
||||
|
||||
#define YModemSerial Serial2 //define Serial port to use for Ymodem transfer here
|
||||
#define Monitorport Serial //define Hardware Serial monitor port to use for monitoring
|
||||
|
||||
const uint32_t Frequency = 2445000000; //frequency of transmissions
|
||||
const uint32_t Offset = 0; //offset frequency for calibration purposes
|
||||
const int8_t TXpower = 10; //LoRa transmit power
|
||||
|
||||
//******* Setup LoRa modem parameters here ! ***************
|
||||
const uint8_t Bandwidth = LORA_BW_1600; //LoRa bandwidth
|
||||
const uint8_t SpreadingFactor = LORA_SF5; //LoRa spreading factor
|
||||
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
|
||||
|
||||
//******* Setup FLRC modem parameters here ! ***************
|
||||
const uint8_t BandwidthBitRate = FLRC_BR_1_300_BW_1_2; //FLRC bandwidth and bit rate, 1.3Mbs
|
||||
//const uint8_t BandwidthBitRate = FLRC_BR_0_260_BW_0_3; //FLRC 260kbps
|
||||
const uint8_t CodingRate = FLRC_CR_1_0; //FLRC coding rate
|
||||
const uint8_t BT = RADIO_MOD_SHAPING_BT_1_0; //FLRC BT
|
||||
const uint32_t Syncword = 0x01234567; //FLRC uses syncword
|
||||
|
||||
const uint32_t TXtimeoutmS = 5000; //mS to wait for TX to complete
|
||||
const uint32_t RXtimeoutmS = 60000; //mS to wait for receiving a packet
|
||||
const uint32_t ACKdelaymS = 10; //ms delay after packet actioned and ack sent
|
||||
const uint32_t ACKsegtimeoutmS = 75; //mS to wait for receiving an ACK before re-trying transmit segment
|
||||
const uint32_t ACKopentimeoutmS = 250; //mS to wait for receiving an ACK before re-trying transmit file open
|
||||
const uint32_t ACKclosetimeoutmS = 250; //mS to wait for receiving an ACK before re-trying transmit file close
|
||||
const uint32_t DuplicatedelaymS = 10; //ms delay if there has been an duplicate segment or command receipt
|
||||
const uint32_t NoAckCountLimit = 250; //if no NoAckCount exceeds this value - restart transfer
|
||||
const uint32_t FunctionDelaymS = 0; //delay between functions such as open file, send segments etc
|
||||
const uint32_t PacketDelaymS = 1000; //mS delay between transmitted packets such as DTInfo etc
|
||||
const uint8_t HeaderSizeMax = 12; //max size of header in bytes, minimum size is 7 bytes
|
||||
const uint8_t DataSizeMax = 245; //max size of data array in bytes
|
||||
const uint8_t Maxfilenamesize = 32; //size of DTfilename buffer
|
||||
const uint8_t SendAttempts = 10; //number of attempts sending a packet or attempting a process before a restart of transfer
|
||||
const uint8_t StartAttempts = 10; //number of attempts sending the file
|
||||
|
||||
const uint16_t NetworkID = 0x3210; //a unique identifier to go out with packet
|
||||
|
||||
#ifdef USELORA
|
||||
const uint8_t SegmentSize = 245; //number of bytes in each segment, 245 is maximum value for LoRa
|
||||
#endif
|
||||
|
||||
#ifdef USEFLRC
|
||||
const uint8_t SegmentSize = 117; //number of bytes in each segment, 117 is maximum value for FLRC
|
||||
#endif
|
||||
|
||||
|
||||
//******* ILI9341 Display settings here ***************
|
||||
|
||||
const uint8_t textscale = 3;
|
||||
const byte rotation = 1;
|
||||
@ -0,0 +1,264 @@
|
||||
//29/12/21 Working for repeat transfer - source of this version not clear
|
||||
// Code below taken from https://gist.github.com/zonque/0ae2dc8cedbcdbd9b933
|
||||
// file xymodem-mini.c
|
||||
|
||||
// MarkD modifcations
|
||||
// - uses 128 byte packets for low RAM devices
|
||||
// - supports batch upload of several files at once
|
||||
|
||||
//StuartsProjects - hard coded for Serial2
|
||||
//080222 - added timeouts
|
||||
|
||||
#define X_SOH 0x01
|
||||
#define X_STX 0x02
|
||||
#define X_ACK 0x06
|
||||
#define X_NAK 0x15
|
||||
#define X_EOT 0x04
|
||||
|
||||
const uint32_t transfertimeoutmS = 5000;
|
||||
const uint8_t ackerrorlimit = 16;
|
||||
|
||||
struct yModemPacket {
|
||||
uint8_t start;
|
||||
uint8_t block;
|
||||
uint8_t block_neg;
|
||||
uint8_t payload[128];
|
||||
uint16_t crc;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define CRC_POLY 0x1021
|
||||
|
||||
static uint16_t crc_update(uint16_t crc_in, int incr)
|
||||
{
|
||||
uint16_t _xor = crc_in >> 15;
|
||||
uint16_t _out = crc_in << 1;
|
||||
|
||||
if (incr)
|
||||
_out++;
|
||||
|
||||
if (_xor)
|
||||
_out ^= CRC_POLY;
|
||||
|
||||
return _out;
|
||||
}
|
||||
|
||||
static uint16_t crc16(const uint8_t *data, uint16_t size)
|
||||
{
|
||||
uint16_t crc, i;
|
||||
|
||||
for (crc = 0; size > 0; size--, data++)
|
||||
for (i = 0x80; i; i >>= 1)
|
||||
crc = crc_update(crc, *data & i);
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
crc = crc_update(crc, 0);
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
static uint16_t swap16(uint16_t in)
|
||||
{
|
||||
return (in >> 8) | ((in & 0xff) << 8);
|
||||
}
|
||||
|
||||
// Main YModem code.
|
||||
// filename is pointer to null terminated string
|
||||
// set waitForReceiver to 1 so that the upload begins when TeraTerm is ready
|
||||
// set batchMode to 0 when sending 1 file
|
||||
// set batchMode to 1 for each file sent apart from the last one.
|
||||
|
||||
static int yModemSend(const char *filename, int waitForReceiver, int batchMode )
|
||||
{
|
||||
uint32_t numBytesStillToSend = 0;
|
||||
uint16_t numBytesThisPacket = 0;
|
||||
uint8_t skip_payload;
|
||||
uint8_t doNextBlock;
|
||||
uint8_t answer = 0;
|
||||
char spfBuff[16];
|
||||
struct yModemPacket yPacket;
|
||||
uint32_t filebytescopied = 0;
|
||||
uint32_t startmS;
|
||||
uint8_t ackerrors = 0;
|
||||
|
||||
File srcFile = SD.open(filename, O_RDONLY);
|
||||
|
||||
if (srcFile < 0)
|
||||
{
|
||||
Serial.println("Open error");
|
||||
return 0;
|
||||
}
|
||||
|
||||
numBytesStillToSend = srcFile.size();
|
||||
|
||||
if (numBytesStillToSend == 0)
|
||||
{
|
||||
Serial.println("SD file error");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//convert the size of the file to an ASCII representation for header packet
|
||||
sprintf(spfBuff, "%ld", numBytesStillToSend);
|
||||
|
||||
// wait here for the receiving device to respond
|
||||
if ( waitForReceiver )
|
||||
{
|
||||
Serial.print("Waiting for receiver ping ... ");
|
||||
while ( Serial2.available() ) Serial2.read();
|
||||
startmS = millis();
|
||||
|
||||
do
|
||||
{
|
||||
if ( Serial2.available() ) answer = Serial2.read();
|
||||
}
|
||||
while ((answer != 'C') && ((uint32_t) (millis() - startmS) < transfertimeoutmS));
|
||||
|
||||
if (answer != 'C')
|
||||
{
|
||||
Serial.println("Timeout starting YModem transfer");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("done");
|
||||
}
|
||||
}
|
||||
|
||||
Serial.print("YModem Sending ");
|
||||
Serial.print(filename);
|
||||
Serial.print(" ");
|
||||
Serial.print(spfBuff);
|
||||
Serial.println(" bytes");
|
||||
|
||||
yPacket.start = X_SOH;
|
||||
yPacket.block = 0;
|
||||
|
||||
// copy the filename into the payload - fill remainder of payload with 0x00
|
||||
strncpy((char *) yPacket.payload, filename, sizeof(yPacket.payload));
|
||||
|
||||
// insert the file size in bytes as ASCII after the NULL of the filename string
|
||||
strcpy( (char *)(yPacket.payload) + strlen(filename) + 1 , spfBuff );
|
||||
|
||||
// first pass - don't read any file data as it will overwrite the file details packet
|
||||
skip_payload = 1;
|
||||
|
||||
while (numBytesStillToSend > 0)
|
||||
{
|
||||
doNextBlock = 0;
|
||||
|
||||
// if this isn't the 1st pass, then read a block of up to 128 bytes from the file
|
||||
if (skip_payload == 0)
|
||||
{
|
||||
numBytesThisPacket = min(numBytesStillToSend, sizeof(yPacket.payload));
|
||||
srcFile.read(yPacket.payload, numBytesThisPacket);
|
||||
|
||||
filebytescopied = filebytescopied + numBytesThisPacket;
|
||||
|
||||
if (numBytesThisPacket < sizeof(yPacket.payload)) {
|
||||
// pad out the rest of the payload block with 0x1A
|
||||
memset(yPacket.payload + numBytesThisPacket, 0x1A, sizeof(yPacket.payload) - numBytesThisPacket);
|
||||
}
|
||||
}
|
||||
|
||||
yPacket.block_neg = 0xff - yPacket.block;
|
||||
|
||||
// calculate and insert the CRC16 checksum into the packet
|
||||
yPacket.crc = swap16(crc16(yPacket.payload, sizeof(yPacket.payload)));
|
||||
|
||||
// send the whole packet to the receiver - will block here
|
||||
startmS = millis();
|
||||
Serial2.write( (uint8_t*)&yPacket, sizeof(yPacket));
|
||||
|
||||
// wait for the receiver to send back a response to the packet
|
||||
while ((!Serial2.available()) && ((uint32_t) (millis() - startmS) < transfertimeoutmS));
|
||||
|
||||
if ( ((uint32_t) (millis() - startmS) >= transfertimeoutmS))
|
||||
{
|
||||
Serial.println("Timeout waiting YModem response");
|
||||
return 0;
|
||||
}
|
||||
|
||||
answer = Serial2.read();
|
||||
switch (answer) {
|
||||
case X_NAK:
|
||||
// something went wrong - send the same packet again?
|
||||
Serial.print("N");
|
||||
ackerrors++;
|
||||
break;
|
||||
case X_ACK:
|
||||
// got ACK to move to the next block of data
|
||||
Serial.print(".");
|
||||
doNextBlock = 1;
|
||||
break;
|
||||
default:
|
||||
// unknown response
|
||||
Serial.print("?");
|
||||
ackerrors++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ackerrors >= ackerrorlimit)
|
||||
{
|
||||
Serial.println("Ack error limit reached");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// need to handle the 'C' response after the initial file details packet has been sent
|
||||
if (skip_payload == 1) {
|
||||
|
||||
startmS = millis();
|
||||
while ((!Serial2.available()) && ((uint32_t) (millis() - startmS) < transfertimeoutmS));
|
||||
|
||||
if ( ((uint32_t) (millis() - startmS) >= transfertimeoutmS))
|
||||
{
|
||||
Serial.println("Timeout waiting YModem response");
|
||||
return 0;
|
||||
}
|
||||
|
||||
answer = Serial2.read();
|
||||
if (answer == 'C') {
|
||||
// good - start sending the data in the next transmission
|
||||
skip_payload = 0;
|
||||
} else {
|
||||
// error? send the file details packet again?
|
||||
doNextBlock = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// move on to the next block of data
|
||||
if (doNextBlock == 1) {
|
||||
yPacket.block++;
|
||||
numBytesStillToSend = numBytesStillToSend - numBytesThisPacket;
|
||||
}
|
||||
}
|
||||
|
||||
// all done - send the end of transmission code
|
||||
Serial2.write( X_EOT );
|
||||
|
||||
// need to send EOT again for YMODEM
|
||||
startmS = millis();
|
||||
while ((!Serial2.available()) && ((uint32_t) (millis() - startmS) < transfertimeoutmS));
|
||||
|
||||
if ( ((uint32_t) (millis() - startmS) >= transfertimeoutmS))
|
||||
{
|
||||
Serial.println("Timeout waiting YModem response");
|
||||
return 0;
|
||||
}
|
||||
|
||||
answer = Serial2.read();
|
||||
Serial2.write( X_EOT );
|
||||
|
||||
if (batchMode == 0) {
|
||||
// and then a packet full of NULL seems to terminate the process
|
||||
// and make TeraTerm close the receive dialog box
|
||||
yPacket.block = 0;
|
||||
yPacket.block_neg = 0xff - yPacket.block;
|
||||
memset(yPacket.payload, 0x00, sizeof(yPacket.payload) );
|
||||
yPacket.crc = swap16(crc16(yPacket.payload, sizeof(yPacket.payload)));
|
||||
Serial2.write( (uint8_t*)&yPacket, sizeof(yPacket));
|
||||
}
|
||||
Serial.println("done");
|
||||
|
||||
srcFile.close();
|
||||
return filebytescopied;
|
||||
}
|
||||
Reference in New Issue
Block a user