Init fork from Stuart Robinson's repo

This commit is contained in:
2024-10-03 14:30:13 +03:00
commit 9395706524
201 changed files with 45709 additions and 0 deletions

View File

@ -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
}

View File

@ -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
}

View File

@ -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;

View File

@ -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;
}