1
- Extruder::selectExtruderById(Printer::lastextruderID);
- #endif
+ //Davinci Specific, restore extruder for DUO
+ #if NUM_EXTRUDER>1
+ Extruder::selectExtruderById(Printer::lastextruderID);
+ #endif
GCode::executeFString(PSTR(PAUSE_END_COMMANDS));
Printer::GoToMemoryPosition(true, true, false, false, Printer::maxFeedrate[X_AXIS]);
Printer::GoToMemoryPosition(false, false, true, false, Printer::maxFeedrate[Z_AXIS] / 2.0f);
@@ -229,27 +201,31 @@ void SDCard::stopPrint()
void SDCard::writeCommand(GCode *code)
{
- unsigned int sum1=0,sum2=0; // for fletcher-16 checksum
+ unsigned int sum1 = 0, sum2 = 0; // for fletcher-16 checksum
uint8_t buf[100];
- uint8_t p=2;
+ uint8_t p = 2;
file.writeError = false;
- int params = 128 | (code->params & ~1);
- *(int*)buf = params;
+ uint16_t params = 128 | (code->params & ~1);
+ memcopy2(buf,¶ms);
+ //*(int*)buf = params;
if(code->isV2()) // Read G,M as 16 bit value
{
- *(int*)&buf[p] = code->params2;
- p+=2;
+ memcopy2(&buf[p],&code->params2);
+ //*(int*)&buf[p] = code->params2;
+ p += 2;
if(code->hasString())
buf[p++] = strlen(code->text);
if(code->hasM())
{
- *(int*)&buf[p] = code->M;
- p+=2;
+ memcopy2(&buf[p],&code->M);
+ //*(int*)&buf[p] = code->M;
+ p += 2;
}
if(code->hasG())
{
- *(int*)&buf[p]= code->G;
- p+=2;
+ memcopy2(&buf[p],&code->G);
+ //*(int*)&buf[p]= code->G;
+ p += 2;
}
}
else
@@ -265,28 +241,33 @@ void SDCard::writeCommand(GCode *code)
}
if(code->hasX())
{
- *(float*)&buf[p] = code->X;
- p+=4;
+ memcopy4(&buf[p],&code->X);
+ //*(float*)&buf[p] = code->X;
+ p += 4;
}
if(code->hasY())
{
- *(float*)&buf[p] = code->Y;
- p+=4;
+ memcopy4(&buf[p],&code->Y);
+ //*(float*)&buf[p] = code->Y;
+ p += 4;
}
if(code->hasZ())
{
- *(float*)&buf[p] = code->Z;
- p+=4;
+ memcopy4(&buf[p],&code->Z);
+ //*(float*)&buf[p] = code->Z;
+ p += 4;
}
if(code->hasE())
{
- *(float*)&buf[p] = code->E;
- p+=4;
+ memcopy4(&buf[p],&code->E);
+ //*(float*)&buf[p] = code->E;
+ p += 4;
}
if(code->hasF())
{
- *(float*)&buf[p] = code->F;
- p+=4;
+ memcopy4(&buf[p],&code->F);
+ //*(float*)&buf[p] = code->F;
+ p += 4;
}
if(code->hasT())
{
@@ -294,23 +275,81 @@ void SDCard::writeCommand(GCode *code)
}
if(code->hasS())
{
- *(long int*)&buf[p] = code->S;
- p+=4;
+ memcopy4(&buf[p],&code->S);
+ //*(int32_t*)&buf[p] = code->S;
+ p += 4;
}
if(code->hasP())
{
- *(long int*)&buf[p] = code->P;
- p+=4;
+ memcopy4(&buf[p],&code->P);
+ //*(int32_t*)&buf[p] = code->P;
+ p += 4;
}
if(code->hasI())
{
- *(float*)&buf[p] = code->I;
- p+=4;
+ memcopy4(&buf[p],&code->I);
+ //*(float*)&buf[p] = code->I;
+ p += 4;
}
if(code->hasJ())
{
- *(float*)&buf[p] = code->J;
- p+=4;
+ memcopy4(&buf[p],&code->J);
+ //*(float*)&buf[p] = code->J;
+ p += 4;
+ }
+ if(code->hasR())
+ {
+ memcopy4(&buf[p],&code->R);
+ //*(float*)&buf[p] = code->R;
+ p += 4;
+ }
+ if(code->hasD())
+ {
+ memcopy4(&buf[p],&code->D);
+ //*(float*)&buf[p] = code->D;
+ p += 4;
+ }
+ if(code->hasC())
+ {
+ memcopy4(&buf[p],&code->C);
+ //*(float*)&buf[p] = code->C;
+ p += 4;
+ }
+ if(code->hasH())
+ {
+ memcopy4(&buf[p],&code->H);
+ //*(float*)&buf[p] = code->H;
+ p += 4;
+ }
+ if(code->hasA())
+ {
+ memcopy4(&buf[p],&code->A);
+ //*(float*)&buf[p] = code->A;
+ p += 4;
+ }
+ if(code->hasB())
+ {
+ memcopy4(&buf[p],&code->B);
+ //*(float*)&buf[p] = code->B;
+ p += 4;
+ }
+ if(code->hasK())
+ {
+ memcopy4(&buf[p],&code->K);
+ //*(float*)&buf[p] = code->K;
+ p += 4;
+ }
+ if(code->hasL())
+ {
+ memcopy4(&buf[p],&code->L);
+ //*(float*)&buf[p] = code->L;
+ p += 4;
+ }
+ if(code->hasO())
+ {
+ memcopy4(&buf[p],&code->O);
+ //*(float*)&buf[p] = code->O;
+ p += 4;
}
if(code->hasString()) // read 16 uint8_t into string
{
@@ -322,7 +361,7 @@ void SDCard::writeCommand(GCode *code)
}
else
{
- for(uint8_t i=0; i<16; ++i) buf[p++] = *sp++;
+ for(uint8_t i = 0; i < 16; ++i) buf[p++] = *sp++;
}
}
uint8_t *ptr = buf;
@@ -334,14 +373,19 @@ void SDCard::writeCommand(GCode *code)
do
{
sum1 += *ptr++;
- if(sum1>=255) sum1-=255;
+ if(sum1 >= 255) sum1 -= 255;
sum2 += sum1;
- if(sum2>=255) sum2-=255;
+ if(sum2 >= 255) sum2 -= 255;
}
while (--tlen);
}
buf[p++] = sum1;
buf[p++] = sum2;
+ // Debug
+ /*Com::printF(PSTR("Buf: "));
+ for(int i=0;iinit(targetFile);
+ }
+ if (!targetFile.isOpen()) {
+ Com::printF(Com::tJSONErrorStart);
+ Com::printF(Com::tNotSDPrinting);
+ Com::printFLN(Com::tJSONErrorEnd);
+ return;
+ }
+
+ // {"err":0,"size":457574,"height":4.00,"layerHeight":0.25,"filament":[6556.3],"generatedBy":"Slic3r 1.1.7 on 2014-11-09 at 17:11:32"}
+ Com::printF(Com::tJSONFileInfoStart);
+ Com::print(info->fileSize);
+ Com::printF(Com::tJSONFileInfoHeight);
+ Com::print(info->objectHeight);
+ Com::printF(Com::tJSONFileInfoLayerHeight);
+ Com::print(info->layerHeight);
+ Com::printF(Com::tJSONFileInfoFilament);
+ Com::print(info->filamentNeeded);
+ Com::printF(Com::tJSONFileInfoGeneratedBy);
+ Com::print(info->generatedBy);
+ Com::print('"');
+ if (strlen(filename) == 0) {
+ Com::printF(Com::tJSONFileInfoName);
+ file.printName();
+ Com::print('"');
+ }
+ Com::print('}');
+ Com::println();
+};
+
+#endif
+
bool SDCard::selectFile(const char *filename, bool silent)
{
SdBaseFile parent;
const char *oldP = filename;
- boolean bFound;
if(!sdactive) return false;
sdmode = 0;
@@ -451,6 +581,9 @@ bool SDCard::selectFile(const char *filename, bool silent)
Com::printF(Com::tFileOpened, oldP);
Com::printFLN(Com::tSpaceSizeColon,file.fileSize());
}
+#if JSON_OUTPUT
+ fileInfo.init(file);
+#endif
sdpos = 0;
filesize = file.fileSize();
Com::printFLN(Com::tFileSelected);
@@ -489,7 +622,7 @@ void SDCard::startWrite(char *filename)
}
else
{
- UI_STATUS(UI_TEXT_UPLOADING);
+ UI_STATUS_F(Com::translatedF(UI_TEXT_UPLOADING_ID));
savetosd = true;
Com::printFLN(Com::tWritingToFile,filename);
}
diff --git a/src/ArduinoDUE/Repetier/SdFat.cpp b/src/ArduinoDUE/Repetier/SdFat.cpp
index da5e3d0..0c914de 100644
--- a/src/ArduinoDUE/Repetier/SdFat.cpp
+++ b/src/ArduinoDUE/Repetier/SdFat.cpp
@@ -32,11 +32,6 @@ extern int8_t RFstrnicmp(const char* s1, const char* s2, size_t n);
//#define GLENN_DEBUG
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-static void pstrPrint(FSTRINGPARAM(str)) {
- Com::printF(str);
-}
//------------------------------------------------------------------------------
static void pstrPrintln(FSTRINGPARAM(str)) {
Com::printFLN(str);
@@ -652,11 +647,12 @@ void SdBaseFile::ls(uint8_t flags) {
ls(flags, 0);
}
-uint8_t SdBaseFile::lsRecursive(SdBaseFile *parent, uint8_t level, char *findFilename, SdBaseFile *pParentFound)
+uint8_t SdBaseFile::lsRecursive(SdBaseFile *parent, uint8_t level, char *findFilename, SdBaseFile *pParentFound, bool isJson)
{
dir_t *p = NULL;
- uint8_t cnt=0;
- char *oldpathend = pathend;
+ //uint8_t cnt=0;
+ //char *oldpathend = pathend;
+ bool firstFile = true;
parent->rewind();
@@ -665,21 +661,29 @@ uint8_t SdBaseFile::lsRecursive(SdBaseFile *parent, uint8_t level, char *findFil
HAL::pingWatchdog();
if (! (DIR_IS_FILE(p) || DIR_IS_SUBDIR(p))) continue;
if (strcmp(tempLongFilename, "..") == 0) continue;
- if( DIR_IS_SUBDIR(p))
- {
- if(level>=SD_MAX_FOLDER_DEPTH) continue; // can't go deeper
- if(level= SD_MAX_FOLDER_DEPTH) continue; // can't go deeper
+ if (level < SD_MAX_FOLDER_DEPTH && findFilename == NULL) {
+ if (level && !isJson) {
+ Com::print(fullName);
+ Com::printF(Com::tSlash);
+ }
+#if JSON_OUTPUT
+ if (isJson) {
+ if (!firstFile) Com::print(',');
+ Com::print('"');Com::print('*');
+ SDCard::printEscapeChars(tempLongFilename);
+ Com::print('"');
+ firstFile = false;
+ } else {
+ Com::print(tempLongFilename);
+ Com::printFLN(Com::tSlash); // End with / to mark it as directory entry, so we can see empty directories.
}
+#else
+ Com::print(tempLongFilename);
+ Com::printFLN(Com::tSlash); // End with / to mark it as directory entry, so we can see empty directories.
+#endif
}
SdBaseFile next;
char *tmp;
@@ -689,11 +693,11 @@ uint8_t SdBaseFile::lsRecursive(SdBaseFile *parent, uint8_t level, char *findFil
strcat(fullName, tempLongFilename);
uint16_t index = (parent->curPosition()-31) >> 5;
- if(next.open(parent, index, O_READ))
- {
- if (next.lsRecursive(&next,level+1, findFilename, pParentFound))
+ if(!isJson && next.open(parent, index, O_READ))
+ {
+ if (next.lsRecursive(&next,level+1, findFilename, pParentFound,false))
return true;
- }
+ }
parent->seekSet(32 * (index + 1));
if ((tmp = strrchr(fullName, '/'))!= NULL)
*tmp = 0;
@@ -721,16 +725,27 @@ uint8_t SdBaseFile::lsRecursive(SdBaseFile *parent, uint8_t level, char *findFil
}
else
{
- if(level)
+ if(level && !isJson)
{
Com::print(fullName);
Com::printF(Com::tSlash);
}
- Com::print(tempLongFilename);
-#if SD_EXTENDED_DIR
- Com::printF(Com::tSpace,(long)p->fileSize);
+#if JSON_OUTPUT
+ if (isJson) {
+ if (!firstFile) Com::printF(Com::tComma);
+ Com::print('"');
+ SDCard::printEscapeChars(tempLongFilename);
+ Com::print('"');
+ firstFile = false;
+ } else
#endif
- Com::println();
+ {
+ Com::print(tempLongFilename);
+#if SD_EXTENDED_DIR
+ Com::printF(Com::tSpace, (long) p->fileSize);
+#endif
+ Com::println();
+ }
}
}
}
@@ -754,20 +769,30 @@ uint8_t SdBaseFile::lsRecursive(SdBaseFile *parent, uint8_t level, char *findFil
* list to indicate subdirectory level.
*/
void SdBaseFile::ls(uint8_t flags, uint8_t indent) {
- SdBaseFile parent;
-
- rewind();
+ SdBaseFile parent;
+ rewind();
*fullName = 0;
- pathend = fullName;
- parent = *this;
- lsRecursive(&parent, 0, NULL, NULL);
+ pathend = fullName;
+ parent = *this;
+ lsRecursive(&parent, 0, NULL, NULL, false);
}
+
+#if JSON_OUTPUT
+void SdBaseFile::lsJSON() {
+ SdBaseFile parent;
+ rewind();
+ *fullName = 0;
+ parent = *this;
+ lsRecursive(&parent, 0, NULL, NULL, true);
+}
+#endif
+
//------------------------------------------------------------------------------
// saves 32 bytes on stack for ls recursion
// return 0 - EOF, 1 - normal file, or 2 - directory
int8_t SdBaseFile::lsPrintNext(uint8_t flags, uint8_t indent) {
dir_t dir;
- uint8_t w = 0;
+ //uint8_t w = 0;
while (1) {
if (read(&dir, sizeof(dir)) != sizeof(dir)) return 0;
if (dir.name[0] == DIR_NAME_FREE) return 0;
@@ -876,8 +901,6 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const char* path, bool pFlag) {
{
return mkdir(&newParent, dname);
}
-
- fail:
return false;
}
//------------------------------------------------------------------------------
@@ -886,13 +909,13 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t *dname) {
if (!parent->isDir()) {
DBG_FAIL_MACRO;
- goto fail;
+ return false;
}
// create a normal file
if (!open(parent, dname, O_CREAT | O_EXCL | O_RDWR, true)) {
DBG_FAIL_MACRO;
- goto fail;
+ return false;
}
// make entry for '.'
@@ -908,7 +931,7 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t *dname) {
for (uint8_t i = 1; i < 11; i++) d.name[i] = ' ';
if (write(&d, sizeof(dir_t)) < 0)
- goto fail;
+ return false;
sync();
// make entry for '..'
@@ -921,18 +944,16 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t *dname) {
d.firstClusterHigh = parent->firstCluster_ >> 16;
}
if (write(&d, sizeof(dir_t)) < 0)
- goto fail;
+ return false;
sync();
memset(&d, 0, sizeof(dir_t));
if (write(&d, sizeof(dir_t)) < 0)
- goto fail;
+ return false;
sync();
// fileSize_ = 0;
type_ = FAT_FILE_TYPE_SUBDIR;
flags_ |= F_FILE_DIR_DIRTY;
return true;
- fail:
- return false;
}
//------------------------------------------------------------------------------
/** Open a file in the current working directory.
@@ -1005,10 +1026,10 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t *dname) {
SdBaseFile *newParent, boolean bMakeDirs) {
SdBaseFile dir1, dir2;
SdBaseFile *parent = dirFile;
- dir_t *pEntry;
+ //dir_t *pEntry;
SdBaseFile *sub = &dir1;
char *p;
- boolean bFound;
+ //boolean bFound;
#ifdef GLENN_DEBUG
Commands::checkFreeMemory();
@@ -1052,7 +1073,7 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t *dname) {
Commands::checkFreeMemory();
Commands::writeLowestFreeRAM();
#endif
- bFound = false;
+ //bFound = false;
if (!sub->open(parent, dname, O_READ, false))
{
if (!bMakeDirs)
@@ -1093,7 +1114,6 @@ bool SdBaseFile::open(SdBaseFile* dirFile, const char* path, uint8_t oflag)
return open(&parent, dname, oflag, false);
}
- fail:
return false;
}
@@ -1113,11 +1133,11 @@ uint8_t SdBaseFile::lfn_checksum(const unsigned char *pFCBName)
bool SdBaseFile::open(SdBaseFile* dirFile,const uint8_t *dname, uint8_t oflag, bool bDir) {
bool emptyFound = false;
uint8_t index = 0;
- dir_t tempDir, *p;
+ dir_t tempDir, *p = NULL;
const char *tempPtr;
char newName[SHORT_FILENAME_LENGTH+2];
boolean bShortName = false;
- int8_t cVFATNeeded = -1, wIndex, cVFATFoundCur;
+ int8_t cVFATNeeded = -1, cVFATFoundCur;
uint32_t wIndexPos = 0;
uint8_t cbFilename;
char *Filename = (char *)dname;
@@ -1570,6 +1590,9 @@ bool SdBaseFile::openParent(SdBaseFile* dir) {
bool SdBaseFile::openRoot(SdVolume* vol) {
// error if file is already open
if (isOpen()) {
+#if defined(DEBUG_SD_ERROR)
+ Com::printErrorFLN(PSTR("Root already open"));
+#endif
DBG_FAIL_MACRO;
goto fail;
}
@@ -1587,6 +1610,10 @@ bool SdBaseFile::openRoot(SdVolume* vol) {
}
} else {
// volume is not initialized, invalid, or FAT12 without support
+#if defined(DEBUG_SD_ERROR)
+ Com::printErrorF(PSTR("volume is not initialized, invalid, or FAT12 without support, type:"));
+ Com::print((int)vol->fatType());Com::println();
+#endif
DBG_FAIL_MACRO;
goto fail;
}
@@ -1603,6 +1630,9 @@ bool SdBaseFile::openRoot(SdVolume* vol) {
return true;
fail:
+#if defined(DEBUG_SD_ERROR)
+ Com::printErrorFLN(PSTR("SD open root dir failed"));
+#endif
return false;
}
//------------------------------------------------------------------------------
@@ -2055,7 +2085,7 @@ dir_t *SdBaseFile::getLongFilename(dir_t *dir, char *longFilename, int8_t cVFATN
bool SdBaseFile::findSpace(dir_t *dir, int8_t cVFATNeeded, int8_t *pcVFATFound, uint32_t *pwIndexPos)
{
- int16_t n;
+ //int16_t n; // unused
int8_t cVFATFound = 0;
// if not a directory file or miss-positioned return an error
if (!isDir()) return -1;
@@ -2081,7 +2111,7 @@ bool SdBaseFile::findSpace(dir_t *dir, int8_t cVFATNeeded, int8_t *pcVFATFound,
{
if (DIR_IS_LONG_NAME(dir))
{
- vfat_t *VFAT = (vfat_t*)dir;
+ //vfat_t *VFAT = (vfat_t*)dir; // unused
cVFATFound++;
}
else
@@ -3029,7 +3059,10 @@ void (*SdBaseFile::oldDateTime_)(uint16_t& date, uint16_t& time) = 0; // NOLINT
* initialize SPI pins
*/
static void spiBegin() {
+ // Already spi init for EEPROM in Alligator boards
+#if !defined(EEPROM_AVAILABLE) || !defined(EEPROM_SPI_ALLIGATOR) || EEPROM_AVAILABLE != EEPROM_SPI_ALLIGATOR
HAL::spiBegin();
+#endif
}
//------------------------------------------------------------------------------
/**
@@ -3199,7 +3232,7 @@ uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {
#if USE_SD_CRC
// form message
- uint8_t d[6] = {cmd | 0X40, pa[3], pa[2], pa[1], pa[0]};
+ uint8_t d[6] = {static_cast(cmd | static_cast(0X40)), pa[3], pa[2], pa[1], pa[0]};
// add crc
d[5] = CRC7(d, 5);
@@ -3395,7 +3428,7 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
if ((spiRec() & 0XC0) == 0XC0) type(SD_CARD_TYPE_SDHC);
// discard rest of ocr - contains allowed voltage range
for (uint8_t i = 0; i < 3; i++) spiRec();
- }
+ }
#if USE_SD_CRC
if (cardCommand(CMD59, 1) > 1) {
error(SD_CARD_ERROR_CMD59);
@@ -3412,6 +3445,9 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
fail:
chipSelectHigh();
+#if defined(DEBUG_SD_ERROR)
+ Com::printErrorFLN(PSTR("SD card initalization failed"));
+#endif
return false;
}
//------------------------------------------------------------------------------
@@ -3466,7 +3502,7 @@ bool Sd2Card::readData(uint8_t* dst, size_t count) {
goto fail;
}
// transfer data
- if (status_ = spiRec(dst, count)) {
+ if ((status_ = spiRec(dst, count))) {
error(SD_CARD_ERROR_SPI_DMA);
goto fail;
}
@@ -4221,7 +4257,7 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
cacheStatus_ = 0; // cacheSync() will write block if true
cacheBlockNumber_ = 0XFFFFFFFF;
cacheFatOffset_ = 0;
-#if USE_SERARATEFAT_CACHE
+#if defined(USE_SERARATEFAT_CACHE) && USE_SERARATEFAT_CACHE
cacheFatStatus_ = 0; // cacheSync() will write block if true
cacheFatBlockNumber_ = 0XFFFFFFFF;
#endif // USE_SERARATEFAT_CACHE
@@ -4229,11 +4265,17 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
// if part > 0 assume mbr volume with partition table
if (part) {
if (part > 4) {
+#if defined(DEBUG_SD_ERROR)
+ Com::printErrorFLN(PSTR("volume init: illegal part"));
+#endif
DBG_FAIL_MACRO;
goto fail;
}
pc = cacheFetch(volumeStartBlock, CACHE_FOR_READ);
if (!pc) {
+#if defined(DEBUG_SD_ERROR)
+ Com::printErrorFLN(PSTR("volume init: cache fetch failed"));
+#endif
DBG_FAIL_MACRO;
goto fail;
}
@@ -4242,6 +4284,9 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
p->totalSectors < 100 ||
p->firstSector == 0) {
// not a valid partition
+#if defined(DEBUG_SD_ERROR)
+ Com::printErrorFLN(PSTR("volume init: invalid partition"));
+#endif
DBG_FAIL_MACRO;
goto fail;
}
@@ -4249,6 +4294,9 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
}
pc = cacheFetch(volumeStartBlock, CACHE_FOR_READ);
if (!pc) {
+#if defined(DEBUG_SD_ERROR)
+Com::printErrorFLN(PSTR("volume init: cache fetch failed"));
+#endif
DBG_FAIL_MACRO;
goto fail;
}
@@ -4258,6 +4306,13 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
fbs->reservedSectorCount == 0 ||
fbs->sectorsPerCluster == 0) {
// not valid FAT volume
+#if defined(DEBUG_SD_ERROR)
+ Com::printErrorFLN(PSTR("volume init: not a valid FAT volume"));
+ Com::printFLN(PSTR("BytesPerSector:"),fbs->bytesPerSector);
+ Com::printFLN(PSTR("fatCount:"),fbs->fatCount);
+ Com::printFLN(PSTR("reservedSectorCount:"),fbs->reservedSectorCount);
+ Com::printFLN(PSTR("sectorsPerCluster:"),fbs->sectorsPerCluster);
+#endif
DBG_FAIL_MACRO;
goto fail;
}
@@ -4300,6 +4355,9 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
if (clusterCount_ < 4085) {
fatType_ = 12;
if (!FAT12_SUPPORT) {
+#if defined(DEBUG_SD_ERROR)
+ Com::printErrorFLN(PSTR("volume init: No FAT 12 support"));
+#endif
DBG_FAIL_MACRO;
goto fail;
}
@@ -4312,6 +4370,9 @@ bool SdVolume::init(Sd2Card* dev, uint8_t part) {
return true;
fail:
+#if defined(DEBUG_SD_ERROR)
+ Com::printErrorFLN(PSTR("SD volume open failed"));
+#endif
return false;
}
// =============== SdFile.cpp ====================
diff --git a/src/ArduinoDUE/Repetier/SdFat.h b/src/ArduinoDUE/Repetier/SdFat.h
index f5ce058..6c6cb60 100644
--- a/src/ArduinoDUE/Repetier/SdFat.h
+++ b/src/ArduinoDUE/Repetier/SdFat.h
@@ -1937,7 +1937,7 @@ class SdBaseFile {
uint8_t lfn_checksum(const unsigned char *pFCBName);
bool openParentReturnFile(SdBaseFile* dirFile, const char* path, uint8_t *dname, SdBaseFile *newParent, boolean bMakeDirs);
-
+
/** \return True if this is a directory else false. */
bool isDir() const {return type_ >= FAT_FILE_TYPE_MIN_DIR;}
/** \return True if this is a normal file else false. */
@@ -2057,7 +2057,7 @@ class SdBaseFile {
dir_t* readDirCacheSpecial();
dir_t *getLongFilename(dir_t *dir, char *longFilename, int8_t cVFATNeeded, uint32_t *pwIndexPos);
bool findSpace(dir_t *dir, int8_t cVFATNeeded, int8_t *pcVFATFound, uint32_t *pwIndexPos);
- uint8_t lsRecursive(SdBaseFile *parent, uint8_t level, char *findFilename, SdBaseFile *pParentFound);
+ uint8_t lsRecursive(SdBaseFile *parent, uint8_t level, char *findFilename, SdBaseFile *pParentFound, bool isJson);
bool setDirSize();
//------------------------------------------------------------------------------
@@ -2208,6 +2208,9 @@ class SdBaseFile {
static bool remove(SdBaseFile& dirFile, const char* path) // NOLINT
__attribute__((error("use remove(&dirFile, path)")));
#endif // ALLOW_DEPRECATED_FUNCTIONS
+#if JSON_OUTPUT
+ void lsJSON();
+#endif
};
//------------------------------------------------------------------------------
/**
diff --git a/src/ArduinoDUE/Repetier/fastio.h b/src/ArduinoDUE/Repetier/fastio.h
index a99aabf..32179c3 100644
--- a/src/ArduinoDUE/Repetier/fastio.h
+++ b/src/ArduinoDUE/Repetier/fastio.h
@@ -3,3046 +3,354 @@
why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
2012/3/10 AT90USB128x modified by lincomatic to match Teensyduino
*/
-#ifndef _ARDUINO_H
-#define _ARDUINO_H
-
-#include
-
-/*
- utility functions
-*/
-
-#ifndef MASK
-/// MASKING- returns \f$2^PIN\f$
- #define MASK(PIN) (1 << PIN)
-#endif
-
-/*
- magic I/O routines
-
- now you can simply SET_OUTPUT(STEP); WRITE(STEP, 1); WRITE(STEP, 0);
-*/
-
-/// Read a pin
-#define _READ(IO) ((bool)(DIO ## IO ## _RPORT & MASK(DIO ## IO ## _PIN)))
-/// write to a pin
-#define _WRITE(IO, v) do { if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); }; } while (0)
-/// toggle a pin
-#define _TOGGLE(IO) do {DIO ## IO ## _RPORT = MASK(DIO ## IO ## _PIN); } while (0)
-
-/// set pin as input
-#define _SET_INPUT(IO) do {DIO ## IO ## _DDR &= ~MASK(DIO ## IO ## _PIN); } while (0)
-/// set pin as output
-#define _SET_OUTPUT(IO) do {DIO ## IO ## _DDR |= MASK(DIO ## IO ## _PIN); } while (0)
-
-/// check if pin is an input
-#define _GET_INPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) == 0)
-/// check if pin is an output
-#define _GET_OUTPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) != 0)
-
-// why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
-
-/// Read a pin wrapper
-#define READ(IO) _READ(IO)
-/// Write to a pin wrapper
-#define WRITE(IO, v) _WRITE(IO, v)
-#define PULLUP(IO,v) _WRITE(IO, v)
-/// toggle a pin wrapper
-#define TOGGLE(IO) _TOGGLE(IO)
-
-/// set pin as input wrapper
-#define SET_INPUT(IO) _SET_INPUT(IO)
-/// set pin as output wrapper
-#define SET_OUTPUT(IO) _SET_OUTPUT(IO)
-
-/// check if pin is an input wrapper
-#define GET_INPUT(IO) _GET_INPUT(IO)
-/// check if pin is an output wrapper
-#define GET_OUTPUT(IO) _GET_OUTPUT(IO)
-
-/*
- ports and functions
-
- added as necessary or if I feel like it- not a comprehensive list!
-*/
-
-#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__)
-// UART
-#define RXD DIO0
-#define TXD DIO1
-
-// SPI
-#define SCK 13
-#define MISO DIO12
-#define MOSI DIO11
-#define SS 10
-
-// TWI (I2C)
-#define SCL AIO5
-#define SDA AIO4
-
-// timers and PWM
-#define OC0A DIO6
-#define OC0B DIO5
-#define OC1A DIO9
-#define OC1B DIO10
-#define OC2A DIO11
-#define OC2B DIO3
-
-#define DEBUG_LED AIO5
-
-/*
-pins
-*/
-
-#define DIO0_PIN PIND0
-#define DIO0_RPORT PIND
-#define DIO0_WPORT PORTD
-#define DIO0_DDR DDRD
-#define DIO0_PWM NULL
-
-#define DIO1_PIN PIND1
-#define DIO1_RPORT PIND
-#define DIO1_WPORT PORTD
-#define DIO1_DDR DDRD
-#define DIO1_PWM NULL
-
-#define DIO2_PIN PIND2
-#define DIO2_RPORT PIND
-#define DIO2_WPORT PORTD
-#define DIO2_DDR DDRD
-#define DIO2_PWM NULL
-
-#define DIO3_PIN PIND3
-#define DIO3_RPORT PIND
-#define DIO3_WPORT PORTD
-#define DIO3_DDR DDRD
-#define DIO3_PWM &OCR2B
-
-#define DIO4_PIN PIND4
-#define DIO4_RPORT PIND
-#define DIO4_WPORT PORTD
-#define DIO4_DDR DDRD
-#define DIO4_PWM NULL
-
-#define DIO5_PIN PIND5
-#define DIO5_RPORT PIND
-#define DIO5_WPORT PORTD
-#define DIO5_DDR DDRD
-#define DIO5_PWM &OCR0B
-
-#define DIO6_PIN PIND6
-#define DIO6_RPORT PIND
-#define DIO6_WPORT PORTD
-#define DIO6_DDR DDRD
-#define DIO6_PWM &OCR0A
-
-#define DIO7_PIN PIND7
-#define DIO7_RPORT PIND
-#define DIO7_WPORT PORTD
-#define DIO7_DDR DDRD
-#define DIO7_PWM NULL
-
-#define DIO8_PIN PINB0
-#define DIO8_RPORT PINB
-#define DIO8_WPORT PORTB
-#define DIO8_DDR DDRB
-#define DIO8_PWM NULL
-
-#define DIO9_PIN PINB1
-#define DIO9_RPORT PINB
-#define DIO9_WPORT PORTB
-#define DIO9_DDR DDRB
-#define DIO9_PWM NULL
-
-#define DIO10_PIN PINB2
-#define DIO10_RPORT PINB
-#define DIO10_WPORT PORTB
-#define DIO10_DDR DDRB
-#define DIO10_PWM NULL
-
-#define DIO11_PIN PINB3
-#define DIO11_RPORT PINB
-#define DIO11_WPORT PORTB
-#define DIO11_DDR DDRB
-#define DIO11_PWM &OCR2A
-
-#define DIO12_PIN PINB4
-#define DIO12_RPORT PINB
-#define DIO12_WPORT PORTB
-#define DIO12_DDR DDRB
-#define DIO12_PWM NULL
-
-#define DIO13_PIN PINB5
-#define DIO13_RPORT PINB
-#define DIO13_WPORT PORTB
-#define DIO13_DDR DDRB
-#define DIO13_PWM NULL
-
-
-#define DIO14_PIN PINC0
-#define DIO14_RPORT PINC
-#define DIO14_WPORT PORTC
-#define DIO14_DDR DDRC
-#define DIO14_PWM NULL
-
-#define DIO15_PIN PINC1
-#define DIO15_RPORT PINC
-#define DIO15_WPORT PORTC
-#define DIO15_DDR DDRC
-#define DIO15_PWM NULL
-
-#define DIO16_PIN PINC2
-#define DIO16_RPORT PINC
-#define DIO16_WPORT PORTC
-#define DIO16_DDR DDRC
-#define DIO16_PWM NULL
-
-#define DIO17_PIN PINC3
-#define DIO17_RPORT PINC
-#define DIO17_WPORT PORTC
-#define DIO17_DDR DDRC
-#define DIO17_PWM NULL
-
-#define DIO18_PIN PINC4
-#define DIO18_RPORT PINC
-#define DIO18_WPORT PORTC
-#define DIO18_DDR DDRC
-#define DIO18_PWM NULL
-
-#define DIO19_PIN PINC5
-#define DIO19_RPORT PINC
-#define DIO19_WPORT PORTC
-#define DIO19_DDR DDRC
-#define DIO19_PWM NULL
-
-#define DIO20_PIN PINC6
-#define DIO20_RPORT PINC
-#define DIO20_WPORT PORTC
-#define DIO20_DDR DDRC
-#define DIO20_PWM NULL
-
-#define DIO21_PIN PINC7
-#define DIO21_RPORT PINC
-#define DIO21_WPORT PORTC
-#define DIO21_DDR DDRC
-#define DIO21_PWM NULL
-
-
-
-#undef PB0
-#define PB0_PIN PINB0
-#define PB0_RPORT PINB
-#define PB0_WPORT PORTB
-#define PB0_DDR DDRB
-#define PB0_PWM NULL
-
-#undef PB1
-#define PB1_PIN PINB1
-#define PB1_RPORT PINB
-#define PB1_WPORT PORTB
-#define PB1_DDR DDRB
-#define PB1_PWM NULL
-
-#undef PB2
-#define PB2_PIN PINB2
-#define PB2_RPORT PINB
-#define PB2_WPORT PORTB
-#define PB2_DDR DDRB
-#define PB2_PWM NULL
-
-#undef PB3
-#define PB3_PIN PINB3
-#define PB3_RPORT PINB
-#define PB3_WPORT PORTB
-#define PB3_DDR DDRB
-#define PB3_PWM &OCR2A
-
-#undef PB4
-#define PB4_PIN PINB4
-#define PB4_RPORT PINB
-#define PB4_WPORT PORTB
-#define PB4_DDR DDRB
-#define PB4_PWM NULL
-
-#undef PB5
-#define PB5_PIN PINB5
-#define PB5_RPORT PINB
-#define PB5_WPORT PORTB
-#define PB5_DDR DDRB
-#define PB5_PWM NULL
-
-#undef PB6
-#define PB6_PIN PINB6
-#define PB6_RPORT PINB
-#define PB6_WPORT PORTB
-#define PB6_DDR DDRB
-#define PB6_PWM NULL
-
-#undef PB7
-#define PB7_PIN PINB7
-#define PB7_RPORT PINB
-#define PB7_WPORT PORTB
-#define PB7_DDR DDRB
-#define PB7_PWM NULL
-
-
-#undef PC0
-#define PC0_PIN PINC0
-#define PC0_RPORT PINC
-#define PC0_WPORT PORTC
-#define PC0_DDR DDRC
-#define PC0_PWM NULL
-
-#undef PC1
-#define PC1_PIN PINC1
-#define PC1_RPORT PINC
-#define PC1_WPORT PORTC
-#define PC1_DDR DDRC
-#define PC1_PWM NULL
-
-#undef PC2
-#define PC2_PIN PINC2
-#define PC2_RPORT PINC
-#define PC2_WPORT PORTC
-#define PC2_DDR DDRC
-#define PC2_PWM NULL
-
-#undef PC3
-#define PC3_PIN PINC3
-#define PC3_RPORT PINC
-#define PC3_WPORT PORTC
-#define PC3_DDR DDRC
-#define PC3_PWM NULL
-
-#undef PC4
-#define PC4_PIN PINC4
-#define PC4_RPORT PINC
-#define PC4_WPORT PORTC
-#define PC4_DDR DDRC
-#define PC4_PWM NULL
-
-#undef PC5
-#define PC5_PIN PINC5
-#define PC5_RPORT PINC
-#define PC5_WPORT PORTC
-#define PC5_DDR DDRC
-#define PC5_PWM NULL
-
-#undef PC6
-#define PC6_PIN PINC6
-#define PC6_RPORT PINC
-#define PC6_WPORT PORTC
-#define PC6_DDR DDRC
-#define PC6_PWM NULL
-
-#undef PC7
-#define PC7_PIN PINC7
-#define PC7_RPORT PINC
-#define PC7_WPORT PORTC
-#define PC7_DDR DDRC
-#define PC7_PWM NULL
-
-
-#undef PD0
-#define PD0_PIN PIND0
-#define PD0_RPORT PIND
-#define PD0_WPORT PORTD
-#define PD0_DDR DDRD
-#define PD0_PWM NULL
-
-#undef PD1
-#define PD1_PIN PIND1
-#define PD1_RPORT PIND
-#define PD1_WPORT PORTD
-#define PD1_DDR DDRD
-#define PD1_PWM NULL
-
-#undef PD2
-#define PD2_PIN PIND2
-#define PD2_RPORT PIND
-#define PD2_WPORT PORTD
-#define PD2_DDR DDRD
-#define PD2_PWM NULL
-
-#undef PD3
-#define PD3_PIN PIND3
-#define PD3_RPORT PIND
-#define PD3_WPORT PORTD
-#define PD3_DDR DDRD
-#define PD3_PWM &OCR2B
-
-#undef PD4
-#define PD4_PIN PIND4
-#define PD4_RPORT PIND
-#define PD4_WPORT PORTD
-#define PD4_DDR DDRD
-#define PD4_PWM NULL
-
-#undef PD5
-#define PD5_PIN PIND5
-#define PD5_RPORT PIND
-#define PD5_WPORT PORTD
-#define PD5_DDR DDRD
-#define PD5_PWM &OCR0B
-
-#undef PD6
-#define PD6_PIN PIND6
-#define PD6_RPORT PIND
-#define PD6_WPORT PORTD
-#define PD6_DDR DDRD
-#define PD6_PWM &OCR0A
-
-#undef PD7
-#define PD7_PIN PIND7
-#define PD7_RPORT PIND
-#define PD7_WPORT PORTD
-#define PD7_DDR DDRD
-#define PD7_PWM NULL
-#endif /* _AVR_ATmega{168,328,328P}__ */
-
-#if defined (__AVR_ATmega644__) || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644PA__) || defined (__AVR_ATmega1284P__)
-// UART
-#define RXD DIO8
-#define TXD DIO9
-#define RXD0 DIO8
-#define TXD0 DIO9
-
-#define RXD1 DIO10
-#define TXD1 DIO11
-
-// SPI
-#define SCK 7
-#define MISO DIO6
-#define MOSI DIO5
-#define SS 4
-
-// TWI (I2C)
-#define SCL DIO16
-#define SDA DIO17
-
-// timers and PWM
-#define OC0A DIO3
-#define OC0B DIO4
-#define OC1A DIO13
-#define OC1B DIO12
-#define OC2A DIO15
-#define OC2B DIO14
-
-#define DEBUG_LED DIO0
-/*
-pins
-*/
-
-#define DIO0_PIN PINB0
-#define DIO0_RPORT PINB
-#define DIO0_WPORT PORTB
-#define DIO0_DDR DDRB
-#define DIO0_PWM NULL
-
-#define DIO1_PIN PINB1
-#define DIO1_RPORT PINB
-#define DIO1_WPORT PORTB
-#define DIO1_DDR DDRB
-#define DIO1_PWM NULL
-
-#define DIO2_PIN PINB2
-#define DIO2_RPORT PINB
-#define DIO2_WPORT PORTB
-#define DIO2_DDR DDRB
-#define DIO2_PWM NULL
-
-#define DIO3_PIN PINB3
-#define DIO3_RPORT PINB
-#define DIO3_WPORT PORTB
-#define DIO3_DDR DDRB
-#define DIO3_PWM &OCR0A
-
-#define DIO4_PIN PINB4
-#define DIO4_RPORT PINB
-#define DIO4_WPORT PORTB
-#define DIO4_DDR DDRB
-#define DIO4_PWM &OCR0B
-
-#define DIO5_PIN PINB5
-#define DIO5_RPORT PINB
-#define DIO5_WPORT PORTB
-#define DIO5_DDR DDRB
-#define DIO5_PWM NULL
-
-#define DIO6_PIN PINB6
-#define DIO6_RPORT PINB
-#define DIO6_WPORT PORTB
-#define DIO6_DDR DDRB
-#define DIO6_PWM NULL
-
-#define DIO7_PIN PINB7
-#define DIO7_RPORT PINB
-#define DIO7_WPORT PORTB
-#define DIO7_DDR DDRB
-#define DIO7_PWM NULL
-
-#define DIO8_PIN PIND0
-#define DIO8_RPORT PIND
-#define DIO8_WPORT PORTD
-#define DIO8_DDR DDRD
-#define DIO8_PWM NULL
-
-#define DIO9_PIN PIND1
-#define DIO9_RPORT PIND
-#define DIO9_WPORT PORTD
-#define DIO9_DDR DDRD
-#define DIO9_PWM NULL
-
-#define DIO10_PIN PIND2
-#define DIO10_RPORT PIND
-#define DIO10_WPORT PORTD
-#define DIO10_DDR DDRD
-#define DIO10_PWM NULL
-
-#define DIO11_PIN PIND3
-#define DIO11_RPORT PIND
-#define DIO11_WPORT PORTD
-#define DIO11_DDR DDRD
-#define DIO11_PWM NULL
-
-#define DIO12_PIN PIND4
-#define DIO12_RPORT PIND
-#define DIO12_WPORT PORTD
-#define DIO12_DDR DDRD
-#define DIO12_PWM NULL
-
-#define DIO13_PIN PIND5
-#define DIO13_RPORT PIND
-#define DIO13_WPORT PORTD
-#define DIO13_DDR DDRD
-#define DIO13_PWM NULL
-
-#define DIO14_PIN PIND6
-#define DIO14_RPORT PIND
-#define DIO14_WPORT PORTD
-#define DIO14_DDR DDRD
-#define DIO14_PWM &OCR2B
-
-#define DIO15_PIN PIND7
-#define DIO15_RPORT PIND
-#define DIO15_WPORT PORTD
-#define DIO15_DDR DDRD
-#define DIO15_PWM &OCR2A
-
-#define DIO16_PIN PINC0
-#define DIO16_RPORT PINC
-#define DIO16_WPORT PORTC
-#define DIO16_DDR DDRC
-#define DIO16_PWM NULL
-
-#define DIO17_PIN PINC1
-#define DIO17_RPORT PINC
-#define DIO17_WPORT PORTC
-#define DIO17_DDR DDRC
-#define DIO17_PWM NULL
-
-#define DIO18_PIN PINC2
-#define DIO18_RPORT PINC
-#define DIO18_WPORT PORTC
-#define DIO18_DDR DDRC
-#define DIO18_PWM NULL
-
-#define DIO19_PIN PINC3
-#define DIO19_RPORT PINC
-#define DIO19_WPORT PORTC
-#define DIO19_DDR DDRC
-#define DIO19_PWM NULL
-
-#define DIO20_PIN PINC4
-#define DIO20_RPORT PINC
-#define DIO20_WPORT PORTC
-#define DIO20_DDR DDRC
-#define DIO20_PWM NULL
-
-#define DIO21_PIN PINC5
-#define DIO21_RPORT PINC
-#define DIO21_WPORT PORTC
-#define DIO21_DDR DDRC
-#define DIO21_PWM NULL
-
-#define DIO22_PIN PINC6
-#define DIO22_RPORT PINC
-#define DIO22_WPORT PORTC
-#define DIO22_DDR DDRC
-#define DIO22_PWM NULL
-
-#define DIO23_PIN PINC7
-#define DIO23_RPORT PINC
-#define DIO23_WPORT PORTC
-#define DIO23_DDR DDRC
-#define DIO23_PWM NULL
-
-#define DIO24_PIN PINA7
-#define DIO24_RPORT PINA
-#define DIO24_WPORT PORTA
-#define DIO24_DDR DDRA
-#define DIO24_PWM NULL
-
-#define DIO25_PIN PINA6
-#define DIO25_RPORT PINA
-#define DIO25_WPORT PORTA
-#define DIO25_DDR DDRA
-#define DIO25_PWM NULL
-
-#define DIO26_PIN PINA5
-#define DIO26_RPORT PINA
-#define DIO26_WPORT PORTA
-#define DIO26_DDR DDRA
-#define DIO26_PWM NULL
-
-#define DIO27_PIN PINA4
-#define DIO27_RPORT PINA
-#define DIO27_WPORT PORTA
-#define DIO27_DDR DDRA
-#define DIO27_PWM NULL
-
-#define DIO28_PIN PINA3
-#define DIO28_RPORT PINA
-#define DIO28_WPORT PORTA
-#define DIO28_DDR DDRA
-#define DIO28_PWM NULL
-
-#define DIO29_PIN PINA2
-#define DIO29_RPORT PINA
-#define DIO29_WPORT PORTA
-#define DIO29_DDR DDRA
-#define DIO29_PWM NULL
-
-#define DIO30_PIN PINA1
-#define DIO30_RPORT PINA
-#define DIO30_WPORT PORTA
-#define DIO30_DDR DDRA
-#define DIO30_PWM NULL
-
-#define DIO31_PIN PINA0
-#define DIO31_RPORT PINA
-#define DIO31_WPORT PORTA
-#define DIO31_DDR DDRA
-#define DIO31_PWM NULL
-
-#define AIO0_PIN PINA0
-#define AIO0_RPORT PINA
-#define AIO0_WPORT PORTA
-#define AIO0_DDR DDRA
-#define AIO0_PWM NULL
-
-#define AIO1_PIN PINA1
-#define AIO1_RPORT PINA
-#define AIO1_WPORT PORTA
-#define AIO1_DDR DDRA
-#define AIO1_PWM NULL
-
-#define AIO2_PIN PINA2
-#define AIO2_RPORT PINA
-#define AIO2_WPORT PORTA
-#define AIO2_DDR DDRA
-#define AIO2_PWM NULL
-
-#define AIO3_PIN PINA3
-#define AIO3_RPORT PINA
-#define AIO3_WPORT PORTA
-#define AIO3_DDR DDRA
-#define AIO3_PWM NULL
-
-#define AIO4_PIN PINA4
-#define AIO4_RPORT PINA
-#define AIO4_WPORT PORTA
-#define AIO4_DDR DDRA
-#define AIO4_PWM NULL
-
-#define AIO5_PIN PINA5
-#define AIO5_RPORT PINA
-#define AIO5_WPORT PORTA
-#define AIO5_DDR DDRA
-#define AIO5_PWM NULL
-
-#define AIO6_PIN PINA6
-#define AIO6_RPORT PINA
-#define AIO6_WPORT PORTA
-#define AIO6_DDR DDRA
-#define AIO6_PWM NULL
-
-#define AIO7_PIN PINA7
-#define AIO7_RPORT PINA
-#define AIO7_WPORT PORTA
-#define AIO7_DDR DDRA
-#define AIO7_PWM NULL
-
-
-
-#undef PA0
-#define PA0_PIN PINA0
-#define PA0_RPORT PINA
-#define PA0_WPORT PORTA
-#define PA0_DDR DDRA
-#define PA0_PWM NULL
-
-#undef PA1
-#define PA1_PIN PINA1
-#define PA1_RPORT PINA
-#define PA1_WPORT PORTA
-#define PA1_DDR DDRA
-#define PA1_PWM NULL
-
-#undef PA2
-#define PA2_PIN PINA2
-#define PA2_RPORT PINA
-#define PA2_WPORT PORTA
-#define PA2_DDR DDRA
-#define PA2_PWM NULL
-
-#undef PA3
-#define PA3_PIN PINA3
-#define PA3_RPORT PINA
-#define PA3_WPORT PORTA
-#define PA3_DDR DDRA
-#define PA3_PWM NULL
-
-#undef PA4
-#define PA4_PIN PINA4
-#define PA4_RPORT PINA
-#define PA4_WPORT PORTA
-#define PA4_DDR DDRA
-#define PA4_PWM NULL
-
-#undef PA5
-#define PA5_PIN PINA5
-#define PA5_RPORT PINA
-#define PA5_WPORT PORTA
-#define PA5_DDR DDRA
-#define PA5_PWM NULL
-
-#undef PA6
-#define PA6_PIN PINA6
-#define PA6_RPORT PINA
-#define PA6_WPORT PORTA
-#define PA6_DDR DDRA
-#define PA6_PWM NULL
-
-#undef PA7
-#define PA7_PIN PINA7
-#define PA7_RPORT PINA
-#define PA7_WPORT PORTA
-#define PA7_DDR DDRA
-#define PA7_PWM NULL
-
-
-#undef PB0
-#define PB0_PIN PINB0
-#define PB0_RPORT PINB
-#define PB0_WPORT PORTB
-#define PB0_DDR DDRB
-#define PB0_PWM NULL
-
-#undef PB1
-#define PB1_PIN PINB1
-#define PB1_RPORT PINB
-#define PB1_WPORT PORTB
-#define PB1_DDR DDRB
-#define PB1_PWM NULL
-
-#undef PB2
-#define PB2_PIN PINB2
-#define PB2_RPORT PINB
-#define PB2_WPORT PORTB
-#define PB2_DDR DDRB
-#define PB2_PWM NULL
-
-#undef PB3
-#define PB3_PIN PINB3
-#define PB3_RPORT PINB
-#define PB3_WPORT PORTB
-#define PB3_DDR DDRB
-#define PB3_PWM &OCR0A
-
-#undef PB4
-#define PB4_PIN PINB4
-#define PB4_RPORT PINB
-#define PB4_WPORT PORTB
-#define PB4_DDR DDRB
-#define PB4_PWM &OCR0B
-
-#undef PB5
-#define PB5_PIN PINB5
-#define PB5_RPORT PINB
-#define PB5_WPORT PORTB
-#define PB5_DDR DDRB
-#define PB5_PWM NULL
-
-#undef PB6
-#define PB6_PIN PINB6
-#define PB6_RPORT PINB
-#define PB6_WPORT PORTB
-#define PB6_DDR DDRB
-#define PB6_PWM NULL
-
-#undef PB7
-#define PB7_PIN PINB7
-#define PB7_RPORT PINB
-#define PB7_WPORT PORTB
-#define PB7_DDR DDRB
-#define PB7_PWM NULL
-
-
-#undef PC0
-#define PC0_PIN PINC0
-#define PC0_RPORT PINC
-#define PC0_WPORT PORTC
-#define PC0_DDR DDRC
-#define PC0_PWM NULL
-
-#undef PC1
-#define PC1_PIN PINC1
-#define PC1_RPORT PINC
-#define PC1_WPORT PORTC
-#define PC1_DDR DDRC
-#define PC1_PWM NULL
-
-#undef PC2
-#define PC2_PIN PINC2
-#define PC2_RPORT PINC
-#define PC2_WPORT PORTC
-#define PC2_DDR DDRC
-#define PC2_PWM NULL
-
-#undef PC3
-#define PC3_PIN PINC3
-#define PC3_RPORT PINC
-#define PC3_WPORT PORTC
-#define PC3_DDR DDRC
-#define PC3_PWM NULL
-
-#undef PC4
-#define PC4_PIN PINC4
-#define PC4_RPORT PINC
-#define PC4_WPORT PORTC
-#define PC4_DDR DDRC
-#define PC4_PWM NULL
-
-#undef PC5
-#define PC5_PIN PINC5
-#define PC5_RPORT PINC
-#define PC5_WPORT PORTC
-#define PC5_DDR DDRC
-#define PC5_PWM NULL
-
-#undef PC6
-#define PC6_PIN PINC6
-#define PC6_RPORT PINC
-#define PC6_WPORT PORTC
-#define PC6_DDR DDRC
-#define PC6_PWM NULL
-
-#undef PC7
-#define PC7_PIN PINC7
-#define PC7_RPORT PINC
-#define PC7_WPORT PORTC
-#define PC7_DDR DDRC
-#define PC7_PWM NULL
-
-
-#undef PD0
-#define PD0_PIN PIND0
-#define PD0_RPORT PIND
-#define PD0_WPORT PORTD
-#define PD0_DDR DDRD
-#define PD0_PWM NULL
-
-#undef PD1
-#define PD1_PIN PIND1
-#define PD1_RPORT PIND
-#define PD1_WPORT PORTD
-#define PD1_DDR DDRD
-#define PD1_PWM NULL
-
-#undef PD2
-#define PD2_PIN PIND2
-#define PD2_RPORT PIND
-#define PD2_WPORT PORTD
-#define PD2_DDR DDRD
-#define PD2_PWM NULL
-
-#undef PD3
-#define PD3_PIN PIND3
-#define PD3_RPORT PIND
-#define PD3_WPORT PORTD
-#define PD3_DDR DDRD
-#define PD3_PWM NULL
-
-#undef PD4
-#define PD4_PIN PIND4
-#define PD4_RPORT PIND
-#define PD4_WPORT PORTD
-#define PD4_DDR DDRD
-#define PD4_PWM NULL
-
-#undef PD5
-#define PD5_PIN PIND5
-#define PD5_RPORT PIND
-#define PD5_WPORT PORTD
-#define PD5_DDR DDRD
-#define PD5_PWM NULL
-
-#undef PD6
-#define PD6_PIN PIND6
-#define PD6_RPORT PIND
-#define PD6_WPORT PORTD
-#define PD6_DDR DDRD
-#define PD6_PWM &OCR2B
-
-#undef PD7
-#define PD7_PIN PIND7
-#define PD7_RPORT PIND
-#define PD7_WPORT PORTD
-#define PD7_DDR DDRD
-#define PD7_PWM &OCR2A
-#endif /* _AVR_ATmega{644,644P,644PA}__ */
-
-#if defined (__AVR_ATmega1280__) || defined (__AVR_ATmega2560__)
-// UART
-#define RXD DIO0
-#define TXD DIO1
-
-// SPI
-#define SCK 52
-#define MISO DIO50
-#define MOSI DIO51
-#define SS 53
-
-// TWI (I2C)
-#define SCL DIO21
-#define SDA DIO20
-
-// timers and PWM
-#define OC0A DIO13
-#define OC0B DIO4
-#define OC1A DIO11
-#define OC1B DIO12
-#define OC2A DIO10
-#define OC2B DIO9
-#define OC3A DIO5
-#define OC3B DIO2
-#define OC3C DIO3
-#define OC4A DIO6
-#define OC4B DIO7
-#define OC4C DIO8
-#define OC5A DIO46
-#define OC5B DIO45
-#define OC5C DIO44
-
-// change for your board
-#if MOTHERBOARD == 12
-#define DEBUG_LED DIO22
-#else
-#define DEBUG_LED DIO21
-#endif
-/*
-pins
-*/
-#define DIO0_PIN PINE0
-#define DIO0_RPORT PINE
-#define DIO0_WPORT PORTE
-#define DIO0_DDR DDRE
-#define DIO0_PWM NULL
-
-#define DIO1_PIN PINE1
-#define DIO1_RPORT PINE
-#define DIO1_WPORT PORTE
-#define DIO1_DDR DDRE
-#define DIO1_PWM NULL
-
-#define DIO2_PIN PINE4
-#define DIO2_RPORT PINE
-#define DIO2_WPORT PORTE
-#define DIO2_DDR DDRE
-#define DIO2_PWM &OCR3BL
-
-#define DIO3_PIN PINE5
-#define DIO3_RPORT PINE
-#define DIO3_WPORT PORTE
-#define DIO3_DDR DDRE
-#define DIO3_PWM &OCR3CL
-
-#define DIO4_PIN PING5
-#define DIO4_RPORT PING
-#define DIO4_WPORT PORTG
-#define DIO4_DDR DDRG
-#define DIO4_PWM &OCR0B
-
-#define DIO5_PIN PINE3
-#define DIO5_RPORT PINE
-#define DIO5_WPORT PORTE
-#define DIO5_DDR DDRE
-#define DIO5_PWM &OCR3AL
-
-#define DIO6_PIN PINH3
-#define DIO6_RPORT PINH
-#define DIO6_WPORT PORTH
-#define DIO6_DDR DDRH
-#define DIO6_PWM &OCR4AL
-
-#define DIO7_PIN PINH4
-#define DIO7_RPORT PINH
-#define DIO7_WPORT PORTH
-#define DIO7_DDR DDRH
-#define DIO7_PWM &OCR4BL
-
-#define DIO8_PIN PINH5
-#define DIO8_RPORT PINH
-#define DIO8_WPORT PORTH
-#define DIO8_DDR DDRH
-#define DIO8_PWM &OCR4CL
-
-#define DIO9_PIN PINH6
-#define DIO9_RPORT PINH
-#define DIO9_WPORT PORTH
-#define DIO9_DDR DDRH
-#define DIO9_PWM &OCR2B
-
-#define DIO10_PIN PINB4
-#define DIO10_RPORT PINB
-#define DIO10_WPORT PORTB
-#define DIO10_DDR DDRB
-#define DIO10_PWM &OCR2A
-
-#define DIO11_PIN PINB5
-#define DIO11_RPORT PINB
-#define DIO11_WPORT PORTB
-#define DIO11_DDR DDRB
-#define DIO11_PWM NULL
-
-#define DIO12_PIN PINB6
-#define DIO12_RPORT PINB
-#define DIO12_WPORT PORTB
-#define DIO12_DDR DDRB
-#define DIO12_PWM NULL
-
-#define DIO13_PIN PINB7
-#define DIO13_RPORT PINB
-#define DIO13_WPORT PORTB
-#define DIO13_DDR DDRB
-#define DIO13_PWM &OCR0A
-
-#define DIO14_PIN PINJ1
-#define DIO14_RPORT PINJ
-#define DIO14_WPORT PORTJ
-#define DIO14_DDR DDRJ
-#define DIO14_PWM NULL
-
-#define DIO15_PIN PINJ0
-#define DIO15_RPORT PINJ
-#define DIO15_WPORT PORTJ
-#define DIO15_DDR DDRJ
-#define DIO15_PWM NULL
-
-#define DIO16_PIN PINH1
-#define DIO16_RPORT PINH
-#define DIO16_WPORT PORTH
-#define DIO16_DDR DDRH
-#define DIO16_PWM NULL
-
-#define DIO17_PIN PINH0
-#define DIO17_RPORT PINH
-#define DIO17_WPORT PORTH
-#define DIO17_DDR DDRH
-#define DIO17_PWM NULL
-
-#define DIO18_PIN PIND3
-#define DIO18_RPORT PIND
-#define DIO18_WPORT PORTD
-#define DIO18_DDR DDRD
-#define DIO18_PWM NULL
-
-#define DIO19_PIN PIND2
-#define DIO19_RPORT PIND
-#define DIO19_WPORT PORTD
-#define DIO19_DDR DDRD
-#define DIO19_PWM NULL
-
-#define DIO20_PIN PIND1
-#define DIO20_RPORT PIND
-#define DIO20_WPORT PORTD
-#define DIO20_DDR DDRD
-#define DIO20_PWM NULL
-
-#define DIO21_PIN PIND0
-#define DIO21_RPORT PIND
-#define DIO21_WPORT PORTD
-#define DIO21_DDR DDRD
-#define DIO21_PWM NULL
-
-#define DIO22_PIN PINA0
-#define DIO22_RPORT PINA
-#define DIO22_WPORT PORTA
-#define DIO22_DDR DDRA
-#define DIO22_PWM NULL
-
-#define DIO23_PIN PINA1
-#define DIO23_RPORT PINA
-#define DIO23_WPORT PORTA
-#define DIO23_DDR DDRA
-#define DIO23_PWM NULL
-
-#define DIO24_PIN PINA2
-#define DIO24_RPORT PINA
-#define DIO24_WPORT PORTA
-#define DIO24_DDR DDRA
-#define DIO24_PWM NULL
-
-#define DIO25_PIN PINA3
-#define DIO25_RPORT PINA
-#define DIO25_WPORT PORTA
-#define DIO25_DDR DDRA
-#define DIO25_PWM NULL
-
-#define DIO26_PIN PINA4
-#define DIO26_RPORT PINA
-#define DIO26_WPORT PORTA
-#define DIO26_DDR DDRA
-#define DIO26_PWM NULL
-
-#define DIO27_PIN PINA5
-#define DIO27_RPORT PINA
-#define DIO27_WPORT PORTA
-#define DIO27_DDR DDRA
-#define DIO27_PWM NULL
-
-#define DIO28_PIN PINA6
-#define DIO28_RPORT PINA
-#define DIO28_WPORT PORTA
-#define DIO28_DDR DDRA
-#define DIO28_PWM NULL
-
-#define DIO29_PIN PINA7
-#define DIO29_RPORT PINA
-#define DIO29_WPORT PORTA
-#define DIO29_DDR DDRA
-#define DIO29_PWM NULL
-
-#define DIO30_PIN PINC7
-#define DIO30_RPORT PINC
-#define DIO30_WPORT PORTC
-#define DIO30_DDR DDRC
-#define DIO30_PWM NULL
-
-#define DIO31_PIN PINC6
-#define DIO31_RPORT PINC
-#define DIO31_WPORT PORTC
-#define DIO31_DDR DDRC
-#define DIO31_PWM NULL
-
-#define DIO32_PIN PINC5
-#define DIO32_RPORT PINC
-#define DIO32_WPORT PORTC
-#define DIO32_DDR DDRC
-#define DIO32_PWM NULL
-
-#define DIO33_PIN PINC4
-#define DIO33_RPORT PINC
-#define DIO33_WPORT PORTC
-#define DIO33_DDR DDRC
-#define DIO33_PWM NULL
-
-#define DIO34_PIN PINC3
-#define DIO34_RPORT PINC
-#define DIO34_WPORT PORTC
-#define DIO34_DDR DDRC
-#define DIO34_PWM NULL
-
-#define DIO35_PIN PINC2
-#define DIO35_RPORT PINC
-#define DIO35_WPORT PORTC
-#define DIO35_DDR DDRC
-#define DIO35_PWM NULL
-
-#define DIO36_PIN PINC1
-#define DIO36_RPORT PINC
-#define DIO36_WPORT PORTC
-#define DIO36_DDR DDRC
-#define DIO36_PWM NULL
-
-#define DIO37_PIN PINC0
-#define DIO37_RPORT PINC
-#define DIO37_WPORT PORTC
-#define DIO37_DDR DDRC
-#define DIO37_PWM NULL
-
-#define DIO38_PIN PIND7
-#define DIO38_RPORT PIND
-#define DIO38_WPORT PORTD
-#define DIO38_DDR DDRD
-#define DIO38_PWM NULL
-
-#define DIO39_PIN PING2
-#define DIO39_RPORT PING
-#define DIO39_WPORT PORTG
-#define DIO39_DDR DDRG
-#define DIO39_PWM NULL
-
-#define DIO40_PIN PING1
-#define DIO40_RPORT PING
-#define DIO40_WPORT PORTG
-#define DIO40_DDR DDRG
-#define DIO40_PWM NULL
-
-#define DIO41_PIN PING0
-#define DIO41_RPORT PING
-#define DIO41_WPORT PORTG
-#define DIO41_DDR DDRG
-#define DIO41_PWM NULL
-
-#define DIO42_PIN PINL7
-#define DIO42_RPORT PINL
-#define DIO42_WPORT PORTL
-#define DIO42_DDR DDRL
-#define DIO42_PWM NULL
-
-#define DIO43_PIN PINL6
-#define DIO43_RPORT PINL
-#define DIO43_WPORT PORTL
-#define DIO43_DDR DDRL
-#define DIO43_PWM NULL
-
-#define DIO44_PIN PINL5
-#define DIO44_RPORT PINL
-#define DIO44_WPORT PORTL
-#define DIO44_DDR DDRL
-#define DIO44_PWM &OCR5CL
-
-#define DIO45_PIN PINL4
-#define DIO45_RPORT PINL
-#define DIO45_WPORT PORTL
-#define DIO45_DDR DDRL
-#define DIO45_PWM &OCR5BL
-
-#define DIO46_PIN PINL3
-#define DIO46_RPORT PINL
-#define DIO46_WPORT PORTL
-#define DIO46_DDR DDRL
-#define DIO46_PWM &OCR5AL
-
-#define DIO47_PIN PINL2
-#define DIO47_RPORT PINL
-#define DIO47_WPORT PORTL
-#define DIO47_DDR DDRL
-#define DIO47_PWM NULL
-
-#define DIO48_PIN PINL1
-#define DIO48_RPORT PINL
-#define DIO48_WPORT PORTL
-#define DIO48_DDR DDRL
-#define DIO48_PWM NULL
-
-#define DIO49_PIN PINL0
-#define DIO49_RPORT PINL
-#define DIO49_WPORT PORTL
-#define DIO49_DDR DDRL
-#define DIO49_PWM NULL
-
-#define DIO50_PIN PINB3
-#define DIO50_RPORT PINB
-#define DIO50_WPORT PORTB
-#define DIO50_DDR DDRB
-#define DIO50_PWM NULL
-
-#define DIO51_PIN PINB2
-#define DIO51_RPORT PINB
-#define DIO51_WPORT PORTB
-#define DIO51_DDR DDRB
-#define DIO51_PWM NULL
-
-#define DIO52_PIN PINB1
-#define DIO52_RPORT PINB
-#define DIO52_WPORT PORTB
-#define DIO52_DDR DDRB
-#define DIO52_PWM NULL
-
-#define DIO53_PIN PINB0
-#define DIO53_RPORT PINB
-#define DIO53_WPORT PORTB
-#define DIO53_DDR DDRB
-#define DIO53_PWM NULL
-
-#define DIO54_PIN PINF0
-#define DIO54_RPORT PINF
-#define DIO54_WPORT PORTF
-#define DIO54_DDR DDRF
-#define DIO54_PWM NULL
-
-#define DIO55_PIN PINF1
-#define DIO55_RPORT PINF
-#define DIO55_WPORT PORTF
-#define DIO55_DDR DDRF
-#define DIO55_PWM NULL
-
-#define DIO56_PIN PINF2
-#define DIO56_RPORT PINF
-#define DIO56_WPORT PORTF
-#define DIO56_DDR DDRF
-#define DIO56_PWM NULL
-
-#define DIO57_PIN PINF3
-#define DIO57_RPORT PINF
-#define DIO57_WPORT PORTF
-#define DIO57_DDR DDRF
-#define DIO57_PWM NULL
-
-#define DIO58_PIN PINF4
-#define DIO58_RPORT PINF
-#define DIO58_WPORT PORTF
-#define DIO58_DDR DDRF
-#define DIO58_PWM NULL
-
-#define DIO59_PIN PINF5
-#define DIO59_RPORT PINF
-#define DIO59_WPORT PORTF
-#define DIO59_DDR DDRF
-#define DIO59_PWM NULL
-
-#define DIO60_PIN PINF6
-#define DIO60_RPORT PINF
-#define DIO60_WPORT PORTF
-#define DIO60_DDR DDRF
-#define DIO60_PWM NULL
-
-#define DIO61_PIN PINF7
-#define DIO61_RPORT PINF
-#define DIO61_WPORT PORTF
-#define DIO61_DDR DDRF
-#define DIO61_PWM NULL
-
-#define DIO62_PIN PINK0
-#define DIO62_RPORT PINK
-#define DIO62_WPORT PORTK
-#define DIO62_DDR DDRK
-#define DIO62_PWM NULL
-
-#define DIO63_PIN PINK1
-#define DIO63_RPORT PINK
-#define DIO63_WPORT PORTK
-#define DIO63_DDR DDRK
-#define DIO63_PWM NULL
-
-#define DIO64_PIN PINK2
-#define DIO64_RPORT PINK
-#define DIO64_WPORT PORTK
-#define DIO64_DDR DDRK
-#define DIO64_PWM NULL
-
-#define DIO65_PIN PINK3
-#define DIO65_RPORT PINK
-#define DIO65_WPORT PORTK
-#define DIO65_DDR DDRK
-#define DIO65_PWM NULL
-
-#define DIO66_PIN PINK4
-#define DIO66_RPORT PINK
-#define DIO66_WPORT PORTK
-#define DIO66_DDR DDRK
-#define DIO66_PWM NULL
-
-#define DIO67_PIN PINK5
-#define DIO67_RPORT PINK
-#define DIO67_WPORT PORTK
-#define DIO67_DDR DDRK
-#define DIO67_PWM NULL
-
-#define DIO68_PIN PINK6
-#define DIO68_RPORT PINK
-#define DIO68_WPORT PORTK
-#define DIO68_DDR DDRK
-#define DIO68_PWM NULL
-
-#define DIO69_PIN PINK7
-#define DIO69_RPORT PINK
-#define DIO69_WPORT PORTK
-#define DIO69_DDR DDRK
-#define DIO69_PWM NULL
-
-#if MOTHERBOARD == 12
-#define DIO80_PIN PINJ2
-#define DIO80_RPORT PINJ
-#define DIO80_WPORT PORTJ
-#define DIO80_DDR DDRJ
-#define DIO80_PWM NULL
-
-#define DIO81_PIN PINJ4
-#define DIO81_RPORT PINJ
-#define DIO81_WPORT PORTJ
-#define DIO81_DDR DDRJ
-#define DIO81_PWM NULL
-
-#define DIO82_PIN PINJ5
-#define DIO82_RPORT PINJ
-#define DIO82_WPORT PORTJ
-#define DIO82_DDR DDRJ
-#define DIO82_PWM NULL
-
-#define DIO83_PIN PINJ6
-#define DIO83_RPORT PINJ
-#define DIO83_WPORT PORTJ
-#define DIO83_DDR DDRJ
-#define DIO83_PWM NULL
-
-#define DIO84_PIN PINJ7
-#define DIO84_RPORT PINJ
-#define DIO84_WPORT PORTJ
-#define DIO84_DDR DDRJ
-#define DIO84_PWM NULL
-
-#define DIO85_PIN PINH7
-#define DIO85_RPORT PINH
-#define DIO85_WPORT PORTH
-#define DIO85_DDR DDRH
-#define DIO85_PWM NULL
-
-#define DIO86_PIN PINH2
-#define DIO86_RPORT PINH
-#define DIO86_WPORT PORTH
-#define DIO86_DDR DDRH
-#define DIO86_PWM NULL
-
-#define DIO90_PIN PINE7
-#define DIO90_RPORT PINE
-#define DIO90_WPORT PORTE
-#define DIO90_DDR DDRE
-#define DIO90_PWM NULL
-
-#define DIO91_PIN PINE2
-#define DIO91_RPORT PINE
-#define DIO91_WPORT PORTE
-#define DIO91_DDR DDRE
-#define DIO91_PWM NULL
-
-#define DIO92_PIN PIND4
-#define DIO92_RPORT PIND
-#define DIO92_WPORT PORTD
-#define DIO92_DDR DDRD
-#define DIO92_PWM NULL
-
-#define DIO93_PIN PIND5
-#define DIO93_RPORT PIND
-#define DIO93_WPORT PORTD
-#define DIO93_DDR DDRD
-#define DIO93_PWM NULL
-
-#define DIO94_PIN PIND6
-#define DIO94_RPORT PIND
-#define DIO94_WPORT PORTD
-#define DIO94_DDR DDRD
-#define DIO94_PWM NULL
-#else // MOTHERBOARD == 12
-
-//added below DIO definitions for RAMBo support for LCD's etc...
-
-#define DIO70_PIN PING4
-#define DIO70_RPORT PING
-#define DIO70_WPORT PORTG
-#define DIO70_DDR DDRG
-#define DIO70_PWM NULL
-#define DIO71_PIN PING3
-#define DIO71_RPORT PING
-#define DIO71_WPORT PORTG
-#define DIO71_DDR DDRG
-#define DIO71_PWM NULL
-#define DIO72_PIN PINJ2
-#define DIO72_RPORT PINJ
-#define DIO72_WPORT PORTJ
-#define DIO72_DDR DDRJ
-#define DIO72_PWM NULL
-#define DIO73_PIN PINJ3
-#define DIO73_RPORT PINJ
-#define DIO73_WPORT PORTJ
-#define DIO73_DDR DDRJ
-#define DIO73_PWM NULL
-#define DIO74_PIN PINJ7
-#define DIO74_RPORT PINJ
-#define DIO74_WPORT PORTJ
-#define DIO74_DDR DDRJ
-#define DIO74_PWM NULL
-#define DIO75_PIN PINJ4
-#define DIO75_RPORT PINJ
-#define DIO75_WPORT PORTJ
-#define DIO75_DDR DDRJ
-#define DIO75_PWM NULL
-
-
-#define DIO76_PIN PINJ5
-#define DIO76_RPORT PINJ
-#define DIO76_WPORT PORTJ
-#define DIO76_DDR DDRJ
-#define DIO76_PWM NULL
-#define DIO77_PIN PINJ6
-#define DIO77_RPORT PINJ
-#define DIO77_WPORT PORTJ
-#define DIO77_DDR DDRJ
-#define DIO77_PWM NULL
-#define DIO78_PIN PINE2
-#define DIO78_RPORT PINE
-#define DIO78_WPORT PORTE
-#define DIO78_DDR DDRE
-#define DIO78_PWM NULL
-#define DIO79_PIN PINE6
-#define DIO79_RPORT PINE
-#define DIO79_WPORT PORTE
-#define DIO79_DDR DDRE
-#define DIO79_PWM NULL
-#define DIO80_PIN PINE7
-#define DIO80_RPORT PINE
-#define DIO80_WPORT PORTE
-#define DIO80_DDR DDRE
-#define DIO80_PWM NULL
-#define DIO81_PIN PIND4
-#define DIO81_RPORT PIND
-#define DIO81_WPORT PORTD
-#define DIO81_DDR DDRD
-#define DIO81_PWM NULL
-
-#endif
-
-#undef PA0
-#define PA0_PIN PINA0
-#define PA0_RPORT PINA
-#define PA0_WPORT PORTA
-#define PA0_DDR DDRA
-#define PA0_PWM NULL
-#undef PA1
-#define PA1_PIN PINA1
-#define PA1_RPORT PINA
-#define PA1_WPORT PORTA
-#define PA1_DDR DDRA
-#define PA1_PWM NULL
-#undef PA2
-#define PA2_PIN PINA2
-#define PA2_RPORT PINA
-#define PA2_WPORT PORTA
-#define PA2_DDR DDRA
-#define PA2_PWM NULL
-#undef PA3
-#define PA3_PIN PINA3
-#define PA3_RPORT PINA
-#define PA3_WPORT PORTA
-#define PA3_DDR DDRA
-#define PA3_PWM NULL
-#undef PA4
-#define PA4_PIN PINA4
-#define PA4_RPORT PINA
-#define PA4_WPORT PORTA
-#define PA4_DDR DDRA
-#define PA4_PWM NULL
-#undef PA5
-#define PA5_PIN PINA5
-#define PA5_RPORT PINA
-#define PA5_WPORT PORTA
-#define PA5_DDR DDRA
-#define PA5_PWM NULL
-#undef PA6
-#define PA6_PIN PINA6
-#define PA6_RPORT PINA
-#define PA6_WPORT PORTA
-#define PA6_DDR DDRA
-#define PA6_PWM NULL
-#undef PA7
-#define PA7_PIN PINA7
-#define PA7_RPORT PINA
-#define PA7_WPORT PORTA
-#define PA7_DDR DDRA
-#define PA7_PWM NULL
-
-#undef PB0
-#define PB0_PIN PINB0
-#define PB0_RPORT PINB
-#define PB0_WPORT PORTB
-#define PB0_DDR DDRB
-#define PB0_PWM NULL
-#undef PB1
-#define PB1_PIN PINB1
-#define PB1_RPORT PINB
-#define PB1_WPORT PORTB
-#define PB1_DDR DDRB
-#define PB1_PWM NULL
-#undef PB2
-#define PB2_PIN PINB2
-#define PB2_RPORT PINB
-#define PB2_WPORT PORTB
-#define PB2_DDR DDRB
-#define PB2_PWM NULL
-#undef PB3
-#define PB3_PIN PINB3
-#define PB3_RPORT PINB
-#define PB3_WPORT PORTB
-#define PB3_DDR DDRB
-#define PB3_PWM NULL
-#undef PB4
-#define PB4_PIN PINB4
-#define PB4_RPORT PINB
-#define PB4_WPORT PORTB
-#define PB4_DDR DDRB
-#define PB4_PWM &OCR2A
-#undef PB5
-#define PB5_PIN PINB5
-#define PB5_RPORT PINB
-#define PB5_WPORT PORTB
-#define PB5_DDR DDRB
-#define PB5_PWM NULL
-#undef PB6
-#define PB6_PIN PINB6
-#define PB6_RPORT PINB
-#define PB6_WPORT PORTB
-#define PB6_DDR DDRB
-#define PB6_PWM NULL
-#undef PB7
-#define PB7_PIN PINB7
-#define PB7_RPORT PINB
-#define PB7_WPORT PORTB
-#define PB7_DDR DDRB
-#define PB7_PWM &OCR0A
-
-#undef PC0
-#define PC0_PIN PINC0
-#define PC0_RPORT PINC
-#define PC0_WPORT PORTC
-#define PC0_DDR DDRC
-#define PC0_PWM NULL
-#undef PC1
-#define PC1_PIN PINC1
-#define PC1_RPORT PINC
-#define PC1_WPORT PORTC
-#define PC1_DDR DDRC
-#define PC1_PWM NULL
-#undef PC2
-#define PC2_PIN PINC2
-#define PC2_RPORT PINC
-#define PC2_WPORT PORTC
-#define PC2_DDR DDRC
-#define PC2_PWM NULL
-#undef PC3
-#define PC3_PIN PINC3
-#define PC3_RPORT PINC
-#define PC3_WPORT PORTC
-#define PC3_DDR DDRC
-#define PC3_PWM NULL
-#undef PC4
-#define PC4_PIN PINC4
-#define PC4_RPORT PINC
-#define PC4_WPORT PORTC
-#define PC4_DDR DDRC
-#define PC4_PWM NULL
-#undef PC5
-#define PC5_PIN PINC5
-#define PC5_RPORT PINC
-#define PC5_WPORT PORTC
-#define PC5_DDR DDRC
-#define PC5_PWM NULL
-#undef PC6
-#define PC6_PIN PINC6
-#define PC6_RPORT PINC
-#define PC6_WPORT PORTC
-#define PC6_DDR DDRC
-#define PC6_PWM NULL
-#undef PC7
-#define PC7_PIN PINC7
-#define PC7_RPORT PINC
-#define PC7_WPORT PORTC
-#define PC7_DDR DDRC
-#define PC7_PWM NULL
-
-#undef PD0
-#define PD0_PIN PIND0
-#define PD0_RPORT PIND
-#define PD0_WPORT PORTD
-#define PD0_DDR DDRD
-#define PD0_PWM NULL
-#undef PD1
-#define PD1_PIN PIND1
-#define PD1_RPORT PIND
-#define PD1_WPORT PORTD
-#define PD1_DDR DDRD
-#define PD1_PWM NULL
-#undef PD2
-#define PD2_PIN PIND2
-#define PD2_RPORT PIND
-#define PD2_WPORT PORTD
-#define PD2_DDR DDRD
-#define PD2_PWM NULL
-#undef PD3
-#define PD3_PIN PIND3
-#define PD3_RPORT PIND
-#define PD3_WPORT PORTD
-#define PD3_DDR DDRD
-#define PD3_PWM NULL
-#undef PD4
-#define PD4_PIN PIND4
-#define PD4_RPORT PIND
-#define PD4_WPORT PORTD
-#define PD4_DDR DDRD
-#define PD4_PWM NULL
-#undef PD5
-#define PD5_PIN PIND5
-#define PD5_RPORT PIND
-#define PD5_WPORT PORTD
-#define PD5_DDR DDRD
-#define PD5_PWM NULL
-#undef PD6
-#define PD6_PIN PIND6
-#define PD6_RPORT PIND
-#define PD6_WPORT PORTD
-#define PD6_DDR DDRD
-#define PD6_PWM NULL
-#undef PD7
-#define PD7_PIN PIND7
-#define PD7_RPORT PIND
-#define PD7_WPORT PORTD
-#define PD7_DDR DDRD
-#define PD7_PWM NULL
-
-#undef PE0
-#define PE0_PIN PINE0
-#define PE0_RPORT PINE
-#define PE0_WPORT PORTE
-#define PE0_DDR DDRE
-#define PE0_PWM NULL
-#undef PE1
-#define PE1_PIN PINE1
-#define PE1_RPORT PINE
-#define PE1_WPORT PORTE
-#define PE1_DDR DDRE
-#define PE1_PWM NULL
-#undef PE2
-#define PE2_PIN PINE2
-#define PE2_RPORT PINE
-#define PE2_WPORT PORTE
-#define PE2_DDR DDRE
-#define PE2_PWM NULL
-#undef PE3
-#define PE3_PIN PINE3
-#define PE3_RPORT PINE
-#define PE3_WPORT PORTE
-#define PE3_DDR DDRE
-#define PE3_PWM &OCR3AL
-#undef PE4
-#define PE4_PIN PINE4
-#define PE4_RPORT PINE
-#define PE4_WPORT PORTE
-#define PE4_DDR DDRE
-#define PE4_PWM &OCR3BL
-#undef PE5
-#define PE5_PIN PINE5
-#define PE5_RPORT PINE
-#define PE5_WPORT PORTE
-#define PE5_DDR DDRE
-#define PE5_PWM &OCR3CL
-#undef PE6
-#define PE6_PIN PINE6
-#define PE6_RPORT PINE
-#define PE6_WPORT PORTE
-#define PE6_DDR DDRE
-#define PE6_PWM NULL
-#undef PE7
-#define PE7_PIN PINE7
-#define PE7_RPORT PINE
-#define PE7_WPORT PORTE
-#define PE7_DDR DDRE
-#define PE7_PWM NULL
-
-#undef PF0
-#define PF0_PIN PINF0
-#define PF0_RPORT PINF
-#define PF0_WPORT PORTF
-#define PF0_DDR DDRF
-#define PF0_PWM NULL
-#undef PF1
-#define PF1_PIN PINF1
-#define PF1_RPORT PINF
-#define PF1_WPORT PORTF
-#define PF1_DDR DDRF
-#define PF1_PWM NULL
-#undef PF2
-#define PF2_PIN PINF2
-#define PF2_RPORT PINF
-#define PF2_WPORT PORTF
-#define PF2_DDR DDRF
-#define PF2_PWM NULL
-#undef PF3
-#define PF3_PIN PINF3
-#define PF3_RPORT PINF
-#define PF3_WPORT PORTF
-#define PF3_DDR DDRF
-#define PF3_PWM NULL
-#undef PF4
-#define PF4_PIN PINF4
-#define PF4_RPORT PINF
-#define PF4_WPORT PORTF
-#define PF4_DDR DDRF
-#define PF4_PWM NULL
-#undef PF5
-#define PF5_PIN PINF5
-#define PF5_RPORT PINF
-#define PF5_WPORT PORTF
-#define PF5_DDR DDRF
-#define PF5_PWM NULL
-#undef PF6
-#define PF6_PIN PINF6
-#define PF6_RPORT PINF
-#define PF6_WPORT PORTF
-#define PF6_DDR DDRF
-#define PF6_PWM NULL
-#undef PF7
-#define PF7_PIN PINF7
-#define PF7_RPORT PINF
-#define PF7_WPORT PORTF
-#define PF7_DDR DDRF
-#define PF7_PWM NULL
-
-#undef PG0
-#define PG0_PIN PING0
-#define PG0_RPORT PING
-#define PG0_WPORT PORTG
-#define PG0_DDR DDRG
-#define PG0_PWM NULL
-#undef PG1
-#define PG1_PIN PING1
-#define PG1_RPORT PING
-#define PG1_WPORT PORTG
-#define PG1_DDR DDRG
-#define PG1_PWM NULL
-#undef PG2
-#define PG2_PIN PING2
-#define PG2_RPORT PING
-#define PG2_WPORT PORTG
-#define PG2_DDR DDRG
-#define PG2_PWM NULL
-#undef PG3
-#define PG3_PIN PING3
-#define PG3_RPORT PING
-#define PG3_WPORT PORTG
-#define PG3_DDR DDRG
-#define PG3_PWM NULL
-#undef PG4
-#define PG4_PIN PING4
-#define PG4_RPORT PING
-#define PG4_WPORT PORTG
-#define PG4_DDR DDRG
-#define PG4_PWM NULL
-#undef PG5
-#define PG5_PIN PING5
-#define PG5_RPORT PING
-#define PG5_WPORT PORTG
-#define PG5_DDR DDRG
-#define PG5_PWM &OCR0B
-#undef PG6
-#define PG6_PIN PING6
-#define PG6_RPORT PING
-#define PG6_WPORT PORTG
-#define PG6_DDR DDRG
-#define PG6_PWM NULL
-#undef PG7
-#define PG7_PIN PING7
-#define PG7_RPORT PING
-#define PG7_WPORT PORTG
-#define PG7_DDR DDRG
-#define PG7_PWM NULL
-
-#undef PH0
-#define PH0_PIN PINH0
-#define PH0_RPORT PINH
-#define PH0_WPORT PORTH
-#define PH0_DDR DDRH
-#define PH0_PWM NULL
-#undef PH1
-#define PH1_PIN PINH1
-#define PH1_RPORT PINH
-#define PH1_WPORT PORTH
-#define PH1_DDR DDRH
-#define PH1_PWM NULL
-#undef PH2
-#define PH2_PIN PINH2
-#define PH2_RPORT PINH
-#define PH2_WPORT PORTH
-#define PH2_DDR DDRH
-#define PH2_PWM NULL
-#undef PH3
-#define PH3_PIN PINH3
-#define PH3_RPORT PINH
-#define PH3_WPORT PORTH
-#define PH3_DDR DDRH
-#define PH3_PWM &OCR4AL
-#undef PH4
-#define PH4_PIN PINH4
-#define PH4_RPORT PINH
-#define PH4_WPORT PORTH
-#define PH4_DDR DDRH
-#define PH4_PWM &OCR4BL
-#undef PH5
-#define PH5_PIN PINH5
-#define PH5_RPORT PINH
-#define PH5_WPORT PORTH
-#define PH5_DDR DDRH
-#define PH5_PWM &OCR4CL
-#undef PH6
-#define PH6_PIN PINH6
-#define PH6_RPORT PINH
-#define PH6_WPORT PORTH
-#define PH6_DDR DDRH
-#define PH6_PWM &OCR2B
-#undef PH7
-#define PH7_PIN PINH7
-#define PH7_RPORT PINH
-#define PH7_WPORT PORTH
-#define PH7_DDR DDRH
-#define PH7_PWM NULL
-
-#undef PJ0
-#define PJ0_PIN PINJ0
-#define PJ0_RPORT PINJ
-#define PJ0_WPORT PORTJ
-#define PJ0_DDR DDRJ
-#define PJ0_PWM NULL
-#undef PJ1
-#define PJ1_PIN PINJ1
-#define PJ1_RPORT PINJ
-#define PJ1_WPORT PORTJ
-#define PJ1_DDR DDRJ
-#define PJ1_PWM NULL
-#undef PJ2
-#define PJ2_PIN PINJ2
-#define PJ2_RPORT PINJ
-#define PJ2_WPORT PORTJ
-#define PJ2_DDR DDRJ
-#define PJ2_PWM NULL
-#undef PJ3
-#define PJ3_PIN PINJ3
-#define PJ3_RPORT PINJ
-#define PJ3_WPORT PORTJ
-#define PJ3_DDR DDRJ
-#define PJ3_PWM NULL
-#undef PJ4
-#define PJ4_PIN PINJ4
-#define PJ4_RPORT PINJ
-#define PJ4_WPORT PORTJ
-#define PJ4_DDR DDRJ
-#define PJ4_PWM NULL
-#undef PJ5
-#define PJ5_PIN PINJ5
-#define PJ5_RPORT PINJ
-#define PJ5_WPORT PORTJ
-#define PJ5_DDR DDRJ
-#define PJ5_PWM NULL
-#undef PJ6
-#define PJ6_PIN PINJ6
-#define PJ6_RPORT PINJ
-#define PJ6_WPORT PORTJ
-#define PJ6_DDR DDRJ
-#define PJ6_PWM NULL
-#undef PJ7
-#define PJ7_PIN PINJ7
-#define PJ7_RPORT PINJ
-#define PJ7_WPORT PORTJ
-#define PJ7_DDR DDRJ
-#define PJ7_PWM NULL
-
-#undef PK0
-#define PK0_PIN PINK0
-#define PK0_RPORT PINK
-#define PK0_WPORT PORTK
-#define PK0_DDR DDRK
-#define PK0_PWM NULL
-#undef PK1
-#define PK1_PIN PINK1
-#define PK1_RPORT PINK
-#define PK1_WPORT PORTK
-#define PK1_DDR DDRK
-#define PK1_PWM NULL
-#undef PK2
-#define PK2_PIN PINK2
-#define PK2_RPORT PINK
-#define PK2_WPORT PORTK
-#define PK2_DDR DDRK
-#define PK2_PWM NULL
-#undef PK3
-#define PK3_PIN PINK3
-#define PK3_RPORT PINK
-#define PK3_WPORT PORTK
-#define PK3_DDR DDRK
-#define PK3_PWM NULL
-#undef PK4
-#define PK4_PIN PINK4
-#define PK4_RPORT PINK
-#define PK4_WPORT PORTK
-#define PK4_DDR DDRK
-#define PK4_PWM NULL
-#undef PK5
-#define PK5_PIN PINK5
-#define PK5_RPORT PINK
-#define PK5_WPORT PORTK
-#define PK5_DDR DDRK
-#define PK5_PWM NULL
-#undef PK6
-#define PK6_PIN PINK6
-#define PK6_RPORT PINK
-#define PK6_WPORT PORTK
-#define PK6_DDR DDRK
-#define PK6_PWM NULL
-#undef PK7
-#define PK7_PIN PINK7
-#define PK7_RPORT PINK
-#define PK7_WPORT PORTK
-#define PK7_DDR DDRK
-#define PK7_PWM NULL
-
-#undef PL0
-#define PL0_PIN PINL0
-#define PL0_RPORT PINL
-#define PL0_WPORT PORTL
-#define PL0_DDR DDRL
-#define PL0_PWM NULL
-#undef PL1
-#define PL1_PIN PINL1
-#define PL1_RPORT PINL
-#define PL1_WPORT PORTL
-#define PL1_DDR DDRL
-#define PL1_PWM NULL
-#undef PL2
-#define PL2_PIN PINL2
-#define PL2_RPORT PINL
-#define PL2_WPORT PORTL
-#define PL2_DDR DDRL
-#define PL2_PWM NULL
-#undef PL3
-#define PL3_PIN PINL3
-#define PL3_RPORT PINL
-#define PL3_WPORT PORTL
-#define PL3_DDR DDRL
-#define PL3_PWM &OCR5AL
-#undef PL4
-#define PL4_PIN PINL4
-#define PL4_RPORT PINL
-#define PL4_WPORT PORTL
-#define PL4_DDR DDRL
-#define PL4_PWM &OCR5BL
-#undef PL5
-#define PL5_PIN PINL5
-#define PL5_RPORT PINL
-#define PL5_WPORT PORTL
-#define PL5_DDR DDRL
-#define PL5_PWM &OCR5CL
-#undef PL6
-#define PL6_PIN PINL6
-#define PL6_RPORT PINL
-#define PL6_WPORT PORTL
-#define PL6_DDR DDRL
-#define PL6_PWM NULL
-#undef PL7
-#define PL7_PIN PINL7
-#define PL7_RPORT PINL
-#define PL7_WPORT PORTL
-#define PL7_DDR DDRL
-#define PL7_PWM NULL
-
-#endif
-
-#if defined (__AVR_AT90USB1287__) || defined (__AVR_AT90USB1286__)
-// SPI
-#define SCK 9
-#define MISO DIO11
-#define MOSI DIO10
-#define SS 8
-
-#if MOTHERBOARD!=8 && MOTHERBOARD!=9
-// change for your board
-#define DEBUG_LED DIO31 /* led D5 red */
-
-/*
-pins
-*/
-#define DIO0_PIN PINA0
-#define DIO0_RPORT PINA
-#define DIO0_WPORT PORTA
-#define DIO0_PWM NULL
-#define DIO0_DDR DDRA
-
-#define DIO1_PIN PINA1
-#define DIO1_RPORT PINA
-#define DIO1_WPORT PORTA
-#define DIO1_PWM NULL
-#define DIO1_DDR DDRA
-
-#define DIO2_PIN PINA2
-#define DIO2_RPORT PINA
-#define DIO2_WPORT PORTA
-#define DIO2_PWM NULL
-#define DIO2_DDR DDRA
-
-#define DIO3_PIN PINA3
-#define DIO3_RPORT PINA
-#define DIO3_WPORT PORTA
-#define DIO3_PWM NULL
-#define DIO3_DDR DDRA
-
-#define DIO4_PIN PINA4
-#define DIO4_RPORT PINA
-#define DIO4_WPORT PORTA
-#define DIO4_PWM NULL
-#define DIO4_DDR DDRA
-
-#define DIO5_PIN PINA5
-#define DIO5_RPORT PINA
-#define DIO5_WPORT PORTA
-#define DIO5_PWM NULL
-#define DIO5_DDR DDRA
-
-#define DIO6_PIN PINA6
-#define DIO6_RPORT PINA
-#define DIO6_WPORT PORTA
-#define DIO6_PWM NULL
-#define DIO6_DDR DDRA
-
-#define DIO7_PIN PINA7
-#define DIO7_RPORT PINA
-#define DIO7_WPORT PORTA
-#define DIO7_PWM NULL
-#define DIO7_DDR DDRA
-
-#define DIO8_PIN PINB0
-#define DIO8_RPORT PINB
-#define DIO8_WPORT PORTB
-#define DIO8_PWM NULL
-#define DIO8_DDR DDRB
-
-#define DIO9_PIN PINB1
-#define DIO9_RPORT PINB
-#define DIO9_WPORT PORTB
-#define DIO9_PWM NULL
-#define DIO9_DDR DDRB
-
-#define DIO10_PIN PINB2
-#define DIO10_RPORT PINB
-#define DIO10_WPORT PORTB
-#define DIO10_PWM NULL
-#define DIO10_DDR DDRB
-
-#define DIO11_PIN PINB3
-#define DIO11_RPORT PINB
-#define DIO11_WPORT PORTB
-#define DIO11_PWM NULL
-#define DIO11_DDR DDRB
-
-#define DIO12_PIN PINB4
-#define DIO12_RPORT PINB
-#define DIO12_WPORT PORTB
-#define DIO12_PWM NULL
-#define DIO12_DDR DDRB
-
-#define DIO13_PIN PINB5
-#define DIO13_RPORT PINB
-#define DIO13_WPORT PORTB
-#define DIO13_PWM NULL
-#define DIO13_DDR DDRB
-
-#define DIO14_PIN PINB6
-#define DIO14_RPORT PINB
-#define DIO14_WPORT PORTB
-#define DIO14_PWM NULL
-#define DIO14_DDR DDRB
-
-#define DIO15_PIN PINB7
-#define DIO15_RPORT PINB
-#define DIO15_WPORT PORTB
-#define DIO15_PWM NULL
-#define DIO15_DDR DDRB
-
-#define DIO16_PIN PINC0
-#define DIO16_RPORT PINC
-#define DIO16_WPORT PORTC
-#define DIO16_PWM NULL
-#define DIO16_DDR DDRC
-
-#define DIO17_PIN PINC1
-#define DIO17_RPORT PINC
-#define DIO17_WPORT PORTC
-#define DIO17_PWM NULL
-#define DIO17_DDR DDRC
-
-#define DIO18_PIN PINC2
-#define DIO18_RPORT PINC
-#define DIO18_WPORT PORTC
-#define DIO18_PWM NULL
-#define DIO18_DDR DDRC
-
-#define DIO19_PIN PINC3
-#define DIO19_RPORT PINC
-#define DIO19_WPORT PORTC
-#define DIO19_PWM NULL
-#define DIO19_DDR DDRC
-
-#define DIO20_PIN PINC4
-#define DIO20_RPORT PINC
-#define DIO20_WPORT PORTC
-#define DIO20_PWM NULL
-#define DIO20_DDR DDRC
-
-#define DIO21_PIN PINC5
-#define DIO21_RPORT PINC
-#define DIO21_WPORT PORTC
-#define DIO21_PWM NULL
-#define DIO21_DDR DDRC
-
-#define DIO22_PIN PINC6
-#define DIO22_RPORT PINC
-#define DIO22_WPORT PORTC
-#define DIO22_PWM NULL
-#define DIO22_DDR DDRC
-
-#define DIO23_PIN PINC7
-#define DIO23_RPORT PINC
-#define DIO23_WPORT PORTC
-#define DIO23_PWM NULL
-#define DIO23_DDR DDRC
-
-#define DIO24_PIN PIND0
-#define DIO24_RPORT PIND
-#define DIO24_WPORT PORTD
-#define DIO24_PWM NULL
-#define DIO24_DDR DDRD
-
-#define DIO25_PIN PIND1
-#define DIO25_RPORT PIND
-#define DIO25_WPORT PORTD
-#define DIO25_PWM NULL
-#define DIO25_DDR DDRD
-
-#define DIO26_PIN PIND2
-#define DIO26_RPORT PIND
-#define DIO26_WPORT PORTD
-#define DIO26_PWM NULL
-#define DIO26_DDR DDRD
-
-#define DIO27_PIN PIND3
-#define DIO27_RPORT PIND
-#define DIO27_WPORT PORTD
-#define DIO27_PWM NULL
-#define DIO27_DDR DDRD
-
-#define DIO28_PIN PIND4
-#define DIO28_RPORT PIND
-#define DIO28_WPORT PORTD
-#define DIO28_PWM NULL
-#define DIO28_DDR DDRD
-
-#define DIO29_PIN PIND5
-#define DIO29_RPORT PIND
-#define DIO29_WPORT PORTD
-#define DIO29_PWM NULL
-#define DIO29_DDR DDRD
-
-#define DIO30_PIN PIND6
-#define DIO30_RPORT PIND
-#define DIO30_WPORT PORTD
-#define DIO30_PWM NULL
-#define DIO30_DDR DDRD
-
-#define DIO31_PIN PIND7
-#define DIO31_RPORT PIND
-#define DIO31_WPORT PORTD
-#define DIO31_PWM NULL
-#define DIO31_DDR DDRD
-
-
-#define DIO32_PIN PINE0
-#define DIO32_RPORT PINE
-#define DIO32_WPORT PORTE
-#define DIO32_PWM NULL
-#define DIO32_DDR DDRE
-
-#define DIO33_PIN PINE1
-#define DIO33_RPORT PINE
-#define DIO33_WPORT PORTE
-#define DIO33_PWM NULL
-#define DIO33_DDR DDRE
-
-#define DIO34_PIN PINE2
-#define DIO34_RPORT PINE
-#define DIO34_WPORT PORTE
-#define DIO34_PWM NULL
-#define DIO34_DDR DDRE
-
-#define DIO35_PIN PINE3
-#define DIO35_RPORT PINE
-#define DIO35_WPORT PORTE
-#define DIO35_PWM NULL
-#define DIO35_DDR DDRE
-
-#define DIO36_PIN PINE4
-#define DIO36_RPORT PINE
-#define DIO36_WPORT PORTE
-#define DIO36_PWM NULL
-#define DIO36_DDR DDRE
-
-#define DIO37_PIN PINE5
-#define DIO37_RPORT PINE
-#define DIO37_WPORT PORTE
-#define DIO37_PWM NULL
-#define DIO37_DDR DDRE
-
-#define DIO38_PIN PINE6
-#define DIO38_RPORT PINE
-#define DIO38_WPORT PORTE
-#define DIO38_PWM NULL
-#define DIO38_DDR DDRE
-
-#define DIO39_PIN PINE7
-#define DIO39_RPORT PINE
-#define DIO39_WPORT PORTE
-#define DIO39_PWM NULL
-#define DIO39_DDR DDRE
-
-#define AIO0_PIN PINF0
-#define AIO0_RPORT PINF
-#define AIO0_WPORT PORTF
-#define AIO0_PWM NULL
-#define AIO0_DDR DDRF
-
-#define AIO1_PIN PINF1
-#define AIO1_RPORT PINF
-#define AIO1_WPORT PORTF
-#define AIO1_PWM NULL
-#define AIO1_DDR DDRF
-
-#define AIO2_PIN PINF2
-#define AIO2_RPORT PINF
-#define AIO2_WPORT PORTF
-#define AIO2_PWM NULL
-#define AIO2_DDR DDRF
-
-#define AIO3_PIN PINF3
-#define AIO3_RPORT PINF
-#define AIO3_WPORT PORTF
-#define AIO3_PWM NULL
-#define AIO3_DDR DDRF
-
-#define AIO4_PIN PINF4
-#define AIO4_RPORT PINF
-#define AIO4_WPORT PORTF
-#define AIO4_PWM NULL
-#define AIO4_DDR DDRF
-
-#define AIO5_PIN PINF5
-#define AIO5_RPORT PINF
-#define AIO5_WPORT PORTF
-#define AIO5_PWM NULL
-#define AIO5_DDR DDRF
-
-#define AIO6_PIN PINF6
-#define AIO6_RPORT PINF
-#define AIO6_WPORT PORTF
-#define AIO6_PWM NULL
-#define AIO6_DDR DDRF
-
-#define AIO7_PIN PINF7
-#define AIO7_RPORT PINF
-#define AIO7_WPORT PORTF
-#define AIO7_PWM NULL
-#define AIO7_DDR DDRF
-
-#define DIO40_PIN PINF0
-#define DIO40_RPORT PINF
-#define DIO40_WPORT PORTF
-#define DIO40_PWM NULL
-#define DIO40_DDR DDRF
-
-#define DIO41_PIN PINF1
-#define DIO41_RPORT PINF
-#define DIO41_WPORT PORTF
-#define DIO41_PWM NULL
-#define DIO41_DDR DDRF
-
-#define DIO42_PIN PINF2
-#define DIO42_RPORT PINF
-#define DIO42_WPORT PORTF
-#define DIO42_PWM NULL
-#define DIO42_DDR DDRF
-
-#define DIO43_PIN PINF3
-#define DIO43_RPORT PINF
-#define DIO43_WPORT PORTF
-#define DIO43_PWM NULL
-#define DIO43_DDR DDRF
-
-#define DIO44_PIN PINF4
-#define DIO44_RPORT PINF
-#define DIO44_WPORT PORTF
-#define DIO44_PWM NULL
-#define DIO44_DDR DDRF
-
-#define DIO45_PIN PINF5
-#define DIO45_RPORT PINF
-#define DIO45_WPORT PORTF
-#define DIO45_PWM NULL
-#define DIO45_DDR DDRF
-
-#define DIO46_PIN PINF6
-#define DIO46_RPORT PINF
-#define DIO46_WPORT PORTF
-#define DIO46_PWM NULL
-#define DIO46_DDR DDRF
-
-#define DIO47_PIN PINF7
-#define DIO47_RPORT PINF
-#define DIO47_WPORT PORTF
-#define DIO47_PWM NULL
-#define DIO47_DDR DDRF
-
-#else
-/*
-pins
-*/
-#define DIO0_PIN PIND0
-#define DIO0_RPORT PIND
-#define DIO0_WPORT PORTD
-#define DIO0_PWM NULL
-#define DIO0_DDR DDRD
-
-#define DIO1_PIN PIND1
-#define DIO1_RPORT PIND
-#define DIO1_WPORT PORTD
-#define DIO1_PWM NULL
-#define DIO1_DDR DDRD
-
-#define DIO2_PIN PIND2
-#define DIO2_RPORT PIND
-#define DIO2_WPORT PORTD
-#define DIO2_PWM NULL
-#define DIO2_DDR DDRD
-
-#define DIO3_PIN PIND3
-#define DIO3_RPORT PIND
-#define DIO3_WPORT PORTD
-#define DIO3_PWM NULL
-#define DIO3_DDR DDRD
-
-#define DIO4_PIN PIND4
-#define DIO4_RPORT PIND
-#define DIO4_WPORT PORTD
-#define DIO4_PWM NULL
-#define DIO4_DDR DDRD
-
-#define DIO5_PIN PIND5
-#define DIO5_RPORT PIND
-#define DIO5_WPORT PORTD
-#define DIO5_PWM NULL
-#define DIO5_DDR DDRD
-
-#define DIO6_PIN PIND6
-#define DIO6_RPORT PIND
-#define DIO6_WPORT PORTD
-#define DIO6_PWM NULL
-#define DIO6_DDR DDRD
-
-#define DIO7_PIN PIND7
-#define DIO7_RPORT PIND
-#define DIO7_WPORT PORTD
-#define DIO7_PWM NULL
-#define DIO7_DDR DDRD
-
-#define DIO8_PIN PINE0
-#define DIO8_RPORT PINE
-#define DIO8_WPORT PORTE
-#define DIO8_PWM NULL
-#define DIO8_DDR DDRE
-
-#define DIO9_PIN PINE1
-#define DIO9_RPORT PINE
-#define DIO9_WPORT PORTE
-#define DIO9_PWM NULL
-#define DIO9_DDR DDRE
-
-#define DIO10_PIN PINC0
-#define DIO10_RPORT PINC
-#define DIO10_WPORT PORTC
-#define DIO10_PWM NULL
-#define DIO10_DDR DDRC
-
-#define DIO11_PIN PINC1
-#define DIO11_RPORT PINC
-#define DIO11_WPORT PORTC
-#define DIO11_PWM NULL
-#define DIO11_DDR DDRC
-
-#define DIO12_PIN PINC2
-#define DIO12_RPORT PINC
-#define DIO12_WPORT PORTC
-#define DIO12_PWM NULL
-#define DIO12_DDR DDRC
-
-#define DIO13_PIN PINC3
-#define DIO13_RPORT PINC
-#define DIO13_WPORT PORTC
-#define DIO13_PWM NULL
-#define DIO13_DDR DDRC
-
-#define DIO14_PIN PINC4
-#define DIO14_RPORT PINC
-#define DIO14_WPORT PORTC
-#define DIO14_PWM NULL
-#define DIO14_DDR DDRC
-
-#define DIO15_PIN PINC5
-#define DIO15_RPORT PINC
-#define DIO15_WPORT PORTC
-#define DIO15_PWM NULL
-#define DIO15_DDR DDRC
-
-#define DIO16_PIN PINC6
-#define DIO16_RPORT PINC
-#define DIO16_WPORT PORTC
-#define DIO16_PWM NULL
-#define DIO16_DDR DDRC
-
-#define DIO17_PIN PINC7
-#define DIO17_RPORT PINC
-#define DIO17_WPORT PORTC
-#define DIO17_PWM NULL
-#define DIO17_DDR DDRC
-
-#define DIO18_PIN PINE6
-#define DIO18_RPORT PINE
-#define DIO18_WPORT PORTE
-#define DIO18_PWM NULL
-#define DIO18_DDR DDRE
-
-#define DIO19_PIN PINE7
-#define DIO19_RPORT PINE
-#define DIO19_WPORT PORTE
-#define DIO19_PWM NULL
-#define DIO19_DDR DDRE
-
-#define DIO20_PIN PINB0
-#define DIO20_RPORT PINB
-#define DIO20_WPORT PORTB
-#define DIO20_PWM NULL
-#define DIO20_DDR DDRB
-
-#define DIO21_PIN PINB1
-#define DIO21_RPORT PINB
-#define DIO21_WPORT PORTB
-#define DIO21_PWM NULL
-#define DIO21_DDR DDRB
-
-#define DIO22_PIN PINB2
-#define DIO22_RPORT PINB
-#define DIO22_WPORT PORTB
-#define DIO22_PWM NULL
-#define DIO22_DDR DDRB
-
-#define DIO23_PIN PINB3
-#define DIO23_RPORT PINB
-#define DIO23_WPORT PORTB
-#define DIO23_PWM NULL
-#define DIO23_DDR DDRB
-
-#define DIO24_PIN PINB4
-#define DIO24_RPORT PINB
-#define DIO24_WPORT PORTB
-#define DIO24_PWM NULL
-#define DIO24_DDR DDRB
-
-#define DIO25_PIN PINB5
-#define DIO25_RPORT PINB
-#define DIO25_WPORT PORTB
-#define DIO25_PWM NULL
-#define DIO25_DDR DDRB
-
-#define DIO26_PIN PINB6
-#define DIO26_RPORT PINB
-#define DIO26_WPORT PORTB
-#define DIO26_PWM NULL
-#define DIO26_DDR DDRB
-
-#define DIO27_PIN PINB7
-#define DIO27_RPORT PINB
-#define DIO27_WPORT PORTB
-#define DIO27_PWM NULL
-#define DIO27_DDR DDRB
-
-#define DIO28_PIN PINA0
-#define DIO28_RPORT PINA
-#define DIO28_WPORT PORTA
-#define DIO28_PWM NULL
-#define DIO28_DDR DDRA
-
-#define DIO29_PIN PINA1
-#define DIO29_RPORT PINA
-#define DIO29_WPORT PORTA
-#define DIO29_PWM NULL
-#define DIO29_DDR DDRA
-
-#define DIO30_PIN PINA2
-#define DIO30_RPORT PINA
-#define DIO30_WPORT PORTA
-#define DIO30_PWM NULL
-#define DIO30_DDR DDRA
-
-#define DIO31_PIN PINA3
-#define DIO31_RPORT PINA
-#define DIO31_WPORT PORTA
-#define DIO31_PWM NULL
-#define DIO31_DDR DDRA
-
-
-#define DIO32_PIN PINA4
-#define DIO32_RPORT PINA
-#define DIO32_WPORT PORTA
-#define DIO32_PWM NULL
-#define DIO32_DDR DDRA
-
-#define DIO33_PIN PINA5
-#define DIO33_RPORT PINA
-#define DIO33_WPORT PORTA
-#define DIO33_PWM NULL
-#define DIO33_DDR DDRA
-
-#define DIO34_PIN PINA6
-#define DIO34_RPORT PINA
-#define DIO34_WPORT PORTA
-#define DIO34_PWM NULL
-#define DIO34_DDR DDRA
-
-#define DIO35_PIN PINA7
-#define DIO35_RPORT PINA
-#define DIO35_WPORT PORTA
-#define DIO35_PWM NULL
-#define DIO35_DDR DDRA
-
-#define DIO36_PIN PINE4
-#define DIO36_RPORT PINE
-#define DIO36_WPORT PORTE
-#define DIO36_PWM NULL
-#define DIO36_DDR DDRE
-
-#define DIO37_PIN PINE5
-#define DIO37_RPORT PINE
-#define DIO37_WPORT PORTE
-#define DIO37_PWM NULL
-#define DIO37_DDR DDRE
-
-#define DIO38_PIN PINF0
-#define DIO38_RPORT PINF
-#define DIO38_WPORT PORTF
-#define DIO38_PWM NULL
-#define DIO38_DDR DDRF
-
-#define DIO39_PIN PINF1
-#define DIO39_RPORT PINF
-#define DIO39_WPORT PORTF
-#define DIO39_PWM NULL
-#define DIO39_DDR DDRF
-
-#define DIO40_PIN PINF2
-#define DIO40_RPORT PINF
-#define DIO40_WPORT PORTF
-#define DIO40_PWM NULL
-#define DIO40_DDR DDRF
-
-#define DIO41_PIN PINF3
-#define DIO41_RPORT PINF
-#define DIO41_WPORT PORTF
-#define DIO41_PWM NULL
-#define DIO41_DDR DDRF
-
-#define DIO42_PIN PINF4
-#define DIO42_RPORT PINF
-#define DIO42_WPORT PORTF
-#define DIO42_PWM NULL
-#define DIO42_DDR DDRF
-
-#define DIO43_PIN PINF5
-#define DIO43_RPORT PINF
-#define DIO43_WPORT PORTF
-#define DIO43_PWM NULL
-#define DIO43_DDR DDRF
-
-#define DIO44_PIN PINF6
-#define DIO44_RPORT PINF
-#define DIO44_WPORT PORTF
-#define DIO44_PWM NULL
-#define DIO44_DDR DDRF
-
-#define DIO45_PIN PINF7
-#define DIO45_RPORT PINF
-#define DIO45_WPORT PORTF
-#define DIO45_PWM NULL
-#define DIO45_DDR DDRF
-
-#define AIO0_PIN PINF0
-#define AIO0_RPORT PINF
-#define AIO0_WPORT PORTF
-#define AIO0_PWM NULL
-#define AIO0_DDR DDRF
-
-#define AIO1_PIN PINF1
-#define AIO1_RPORT PINF
-#define AIO1_WPORT PORTF
-#define AIO1_PWM NULL
-#define AIO1_DDR DDRF
-
-#define AIO2_PIN PINF2
-#define AIO2_RPORT PINF
-#define AIO2_WPORT PORTF
-#define AIO2_PWM NULL
-#define AIO2_DDR DDRF
-
-#define AIO3_PIN PINF3
-#define AIO3_RPORT PINF
-#define AIO3_WPORT PORTF
-#define AIO3_PWM NULL
-#define AIO3_DDR DDRF
-
-#define AIO4_PIN PINF4
-#define AIO4_RPORT PINF
-#define AIO4_WPORT PORTF
-#define AIO4_PWM NULL
-#define AIO4_DDR DDRF
-
-#define AIO5_PIN PINF5
-#define AIO5_RPORT PINF
-#define AIO5_WPORT PORTF
-#define AIO5_PWM NULL
-#define AIO5_DDR DDRF
-
-#define AIO6_PIN PINF6
-#define AIO6_RPORT PINF
-#define AIO6_WPORT PORTF
-#define AIO6_PWM NULL
-#define AIO6_DDR DDRF
-
-#define AIO7_PIN PINF7
-#define AIO7_RPORT PINF
-#define AIO7_WPORT PORTF
-#define AIO7_PWM NULL
-#define AIO7_DDR DDRF
-
-//-- Begin not supported by Teensyduino
-//-- don't use Arduino functions on these pins pinMode/digitalWrite/etc
-#define DIO46_PIN PINE2
-#define DIO46_RPORT PINE
-#define DIO46_WPORT PORTE
-#define DIO46_PWM NULL
-#define DIO46_DDR DDRE
-
-#define DIO47_PIN PINE3
-#define DIO47_RPORT PINE
-#define DIO47_WPORT PORTE
-#define DIO47_PWM NULL
-#define DIO47_DDR DDRE
-//-- end not supported by Teensyduino
-
+#ifndef _FASTIO_H
+#define _FASTIO_H
+
+#include
+#include
+
+// 0 .. 53 - Digital pins
+ // ----------------------
+ // 0/1 - UART (Serial)
+#define DIO0_PORT PIOA
+#define DIO0_PIN PIO_PA8A_URXD // URXD
+
+#define DIO1_PORT PIOA
+#define DIO1_PIN PIO_PA9A_UTXD // UTXD
+
+ // 2
+#define DIO2_PORT PIOB
+#define DIO2_PIN PIO_PB25B_TIOA0 // TIOA0
+#define DIO3_PORT PIOC
+#define DIO3_PIN PIO_PC28B_TIOA7 // TIOA7
+#define DIO4_PORT PIOC
+#define DIO4_PIN PIO_PC26B_TIOB6 // TIOB6
+
+ // 5
+#define DIO5_PORT PIOC
+#define DIO5_PIN PIO_PC25B_TIOA6 // TIOA6
+#define DIO6_PORT PIOC
+#define DIO6_PIN PIO_PC24B_PWML7 // PWML7
+#define DIO7_PORT PIOC
+#define DIO7_PIN PIO_PC23B_PWML6 // PWML6
+#define DIO8_PORT PIOC
+#define DIO8_PIN PIO_PC22B_PWML5 // PWML5
+#define DIO9_PORT PIOC
+#define DIO9_PIN PIO_PC21B_PWML4 // PWML4
+ // 10
+#define DIO10_PORT PIOC
+#define DIO10_PIN PIO_PC29B_TIOB7 // TIOB7
+#define DIO11_PORT PIOD
+#define DIO11_PIN PIO_PD7B_TIOA8 // TIOA8
+#define DIO12_PORT PIOD
+#define DIO12_PIN PIO_PD8B_TIOB8 // TIOB8
+
+ // 13 - AMBER LED
+#define DIO13_PORT PIOB
+#define DIO13_PIN PIO_PB27B_TIOB0 // TIOB0
+
+ // 14/15 - USART3 (Serial3)
+#define DIO14_PORT PIOD
+#define DIO14_PIN PIO_PD4B_TXD3 // TXD3
+#define DIO15_PORT PIOD
+#define DIO15_PIN PIO_PD5B_RXD3 // RXD3
+
+ // 16/17 - USART1 (Serial2)
+#define DIO16_PORT PIOA
+#define DIO16_PIN PIO_PA13A_TXD1 // TXD1
+#define DIO17_PORT PIOA
+#define DIO17_PIN PIO_PA12A_RXD1 // RXD1
+
+ // 18/19 - USART0 (Serial1)
+#define DIO18_PORT PIOA
+#define DIO18_PIN PIO_PA11A_TXD0 // TXD0
+#define DIO19_PORT PIOA
+#define DIO19_PIN PIO_PA10A_RXD0 // RXD0
+
+ // 20/21 - TWI1
+#define DIO20_PORT PIOB
+#define DIO20_PIN PIO_PB12A_TWD1 // TWD1 - SDA0
+#define DIO21_PORT PIOB
+#define DIO21_PIN PIO_PB13A_TWCK1 // TWCK1 - SCL0
+
+ // 22
+#define DIO22_PORT PIOB
+#define DIO22_PIN PIO_PB26 // PIN 22
+#define DIO23_PORT PIOA
+#define DIO23_PIN PIO_PA14 // PIN 23
+#define DIO24_PORT PIOA
+#define DIO24_PIN PIO_PA15 // PIN 24
+#define DIO25_PORT PIOD
+#define DIO25_PIN PIO_PD0 // PIN 25
+
+ // 26
+#define DIO26_PORT PIOD
+#define DIO26_PIN PIO_PD1 // PIN 26
+#define DIO27_PORT PIOD
+#define DIO27_PIN PIO_PD2 // PIN 27
+#define DIO28_PORT PIOD
+#define DIO28_PIN PIO_PD3 // PIN 28
+#define DIO29_PORT PIOD
+#define DIO29_PIN PIO_PD6 // PIN 29
+
+ // 30
+#define DIO30_PORT PIOD
+#define DIO30_PIN PIO_PD9 // PIN 30
+#define DIO31_PORT PIOA
+#define DIO31_PIN PIO_PA7 // PIN 31
+#define DIO32_PORT PIOD
+#define DIO32_PIN PIO_PD10 // PIN 32
+#define DIO33_PORT PIOC
+#define DIO33_PIN PIO_PC1 // PIN 33
+
+ // 34
+#define DIO34_PORT PIOC
+#define DIO34_PIN PIO_PC2 // PIN 34
+#define DIO35_PORT PIOC
+#define DIO35_PIN PIO_PC3 // PIN 35
+#define DIO36_PORT PIOC
+#define DIO36_PIN PIO_PC4 // PIN 36
+#define DIO37_PORT PIOC
+#define DIO37_PIN PIO_PC5 // PIN 37
+
+ // 38
+#define DIO38_PORT PIOC
+#define DIO38_PIN PIO_PC6 // PIN 38
+#define DIO39_PORT PIOC
+#define DIO39_PIN PIO_PC7 // PIN 39
+#define DIO40_PORT PIOC
+#define DIO40_PIN PIO_PC8 // PIN 40
+#define DIO41_PORT PIOC
+#define DIO41_PIN PIO_PC9 // PIN 41
+
+ // 42
+#define DIO42_PORT PIOA
+#define DIO42_PIN PIO_PA19 // PIN 42
+#define DIO43_PORT PIOA
+#define DIO43_PIN PIO_PA20 // PIN 43
+#define DIO44_PORT PIOC
+#define DIO44_PIN PIO_PC19 // PIN 44
+#define DIO45_PORT PIOC
+#define DIO45_PIN PIO_PC18 // PIN 45
+
+ // 46
+#define DIO46_PORT PIOC
+#define DIO46_PIN PIO_PC17 // PIN 46
+#define DIO47_PORT PIOC
+#define DIO47_PIN PIO_PC16 // PIN 47
+#define DIO48_PORT PIOC
+#define DIO48_PIN PIO_PC15 // PIN 48
+#define DIO49_PORT PIOC
+#define DIO49_PIN PIO_PC14 // PIN 49
+
+ // 50
+#define DIO50_PORT PIOC
+#define DIO50_PIN PIO_PC13 // PIN 50
+#define DIO51_PORT PIOC
+#define DIO51_PIN PIO_PC12 // PIN 51
+#define DIO52_PORT PIOB
+#define DIO52_PIN PIO_PB21 // PIN 52
+#define DIO53_PORT PIOB
+#define DIO53_PIN PIO_PB14 // PIN 53
+
+
+ // 54 .. 65 - Analog pins
+ // ----------------------
+#define DIO54_PORT PIOA
+#define DIO54_PIN PIO_PA16X1_AD7 // AD0
+#define DIO55_PORT PIOA
+#define DIO55_PIN PIO_PA24X1_AD6 // AD1
+#define DIO56_PORT PIOA
+#define DIO56_PIN PIO_PA23X1_AD5 // AD2
+#define DIO57_PORT PIOA
+#define DIO57_PIN PIO_PA22X1_AD4 // AD3
+ // 58
+#define DIO58_PORT PIOA
+#define DIO58_PIN PIO_PA6X1_AD3 // AD4
+#define DIO59_PORT PIOA
+#define DIO59_PIN PIO_PA4X1_AD2 // AD5
+#define DIO60_PORT PIOA
+#define DIO60_PIN PIO_PA3X1_AD1 // AD6
+#define DIO61_PORT PIOA
+#define DIO61_PIN PIO_PA2X1_AD0 // AD7
+ // 62
+#define DIO62_PORT PIOB
+#define DIO62_PIN PIO_PB17X1_AD10 // AD8
+#define DIO63_PORT PIOB
+#define DIO63_PIN PIO_PB18X1_AD11 // AD9
+#define DIO64_PORT PIOB
+#define DIO64_PIN PIO_PB19X1_AD12 // AD10
+#define DIO65_PORT PIOB
+#define DIO65_PIN PIO_PB20X1_AD13 // AD11
+
+ // 66/67 - DAC0/DAC1
+#define DIO66_PORT PIOB
+#define DIO66_PIN PIO_PB15X1_DAC0 // DAC0
+#define DIO67_PORT PIOB
+#define DIO67_PIN PIO_PB16X1_DAC1 // DAC1
+
+ // 68/69 - CANRX0/CANTX0
+#define DIO68_PORT PIOA
+#define DIO68_PIN PIO_PA1A_CANRX0 // CANRX
+#define DIO69_PORT PIOA
+#define DIO69_PIN PIO_PA0A_CANTX0 // CANTX
+
+ // 70/71 - TWI0
+#define DIO70_PORT PIOA
+#define DIO70_PIN PIO_PA17A_TWD0 // TWD0 - SDA1
+#define DIO71_PORT PIOA
+#define DIO71_PIN PIO_PA18A_TWCK0 // TWCK0 - SCL1
+
+ // 72/73 - LEDs
+#define DIO72_PORT PIOC
+#define DIO72_PIN PIO_PC30 // LED AMBER RXL
+#define DIO73_PORT PIOA
+#define DIO73_PIN PIO_PA21 // LED AMBER TXL
+
+ // 74/75/76 - SPI
+#define DIO74_PORT PIOA
+#define DIO74_PIN PIO_PA25A_SPI0_MISO // MISO
+#define DIO75_PORT PIOA
+#define DIO75_PIN PIO_PA26A_SPI0_MOSI // MOSI
+#define DIO76_PORT PIOA
+#define DIO76_PIN PIO_PA27A_SPI0_SPCK // SPCK
+
+ // 77 - SPI CS0
+#define DIO77_PORT PIOA
+#define DIO77_PIN PIO_PA28A_SPI0_NPCS0 // NPCS0
+
+ // 78 - SPI CS3 (unconnected)
+#define DIO78_PORT PIOB
+#define DIO78_PIN PIO_PB23B_SPI0_NPCS3 // NPCS3
+
+ // 79 .. 84 - "All pins" masks
+
+ // 79 - TWI0 all pins
+#define DIO79_PORT PIOA
+#define DIO79_PIN PIO_PA17A_TWD0|PIO_PA18A_TWCK0
+ // 80 - TWI1 all pins
+#define DI80_PORT PIOB
+#define DIO80_PIN PIO_PB12A_TWD1|PIO_PB13A_TWCK1
+ // 81 - UART (Serial) all pins
+#define DIO81_PORT PIOA
+#define DIO81_PIN PIO_PA8A_URXD|PIO_PA9A_UTXD
+ // 82 - USART0 (Serial1) all pins
+#define DIO82_PORT PIOA
+#define DIO82_PIN PIO_PA11A_TXD0|PIO_PA10A_RXD0
+ // 83 - USART1 (Serial2) all pins
+#define DIO83_PORT PIOA
+#define DIO83_PIN PIO_PA13A_TXD1|PIO_PA12A_RXD1
+ // 84 - USART3 (Serial3) all pins
+#define DIO84_PORT PIOD
+#define DIO84_PIN PIO_PD4B_TXD3|PIO_PD5B_RXD3
+
+ // 85 - USB
+#define DIO85_PORT PIOB
+//Davinci Specific
+//#define DIO85_PIN PIO_PB11A_UOTGID|PIO_PB10A_UOTGVBOF // ID - VBOF
+#define DIO85_PIN PIO_PB11A_UOTGID // ID - VBOF
+
+ // 86 - SPI CS2
+#define DIO86_PORT PIOB
+#define DIO86_PIN PIO_PB21B_SPI0_NPCS2 // NPCS2
+
+ // 87 - SPI CS1
+#define DIO87_PORT PIOA
+#define DIO87_PIN PIO_PA29A_SPI0_NPCS1 // NPCS1
+
+ // 88/89 - CANRX1/CANTX1 (same physical pin for 66/53)
+#define DIO88_PORT PIOB
+#define DIO88_PIN PIO_PB15A_CANRX1 // CANRX1
+#define DIO89_PORT PIOB
+#define DIO89_PIN PIO_PB14A_CANTX1 // CANTX1
+
+ // 90 .. 91 - "All CAN pins" masks
+ // 90 - CAN0 all pins
+#define DIO90_PORT PIOA
+#define DIO90_PIN PIO_PA1A_CANRX0|PIO_PA0A_CANTX0
+ // 91 - CAN1 all pins
+#define DIO91_PORT PIOB
+#define DIO91_PIN PIO_PB15A_CANRX1|PIO_PB14A_CANTX1
+
+// Additional Pins for Alligator board
+#if (MOTHERBOARD == 500) || (MOTHERBOARD == 501)
+//92
+#define DIO92_PORT PIOA
+#define DIO92_PIN PIO_PA5
+//93
+#define DIO93_PORT PIOB
+#define DIO93_PIN PIO_PB12X1_AD8
+//94
+#define DIO94_PORT PIOB
+#define DIO94_PIN PIO_PB22
+//95
+#define DIO95_PORT PIOB
+#define DIO95_PIN PIO_PB23
+//96
+#define DIO96_PORT PIOB
+#define DIO96_PIN PIO_PB24
+//97
+#define DIO97_PORT PIOC
+#define DIO97_PIN PIO_PC20
+//98
+#define DIO98_PORT PIOC
+#define DIO98_PIN PIO_PC27
+//99
+#define DIO99_PORT PIOC
+#define DIO99_PIN PIO_PC10
+//100
+#define DIO100_PORT PIOC
+#define DIO100_PIN PIO_PC11
#endif
-#undef PA0
-#define PA0_PIN PINA0
-#define PA0_RPORT PINA
-#define PA0_WPORT PORTA
-#define PA0_PWM NULL
-#define PA0_DDR DDRA
-#undef PA1
-#define PA1_PIN PINA1
-#define PA1_RPORT PINA
-#define PA1_WPORT PORTA
-#define PA1_PWM NULL
-#define PA1_DDR DDRA
-#undef PA2
-#define PA2_PIN PINA2
-#define PA2_RPORT PINA
-#define PA2_WPORT PORTA
-#define PA2_PWM NULL
-#define PA2_DDR DDRA
-#undef PA3
-#define PA3_PIN PINA3
-#define PA3_RPORT PINA
-#define PA3_WPORT PORTA
-#define PA3_PWM NULL
-#define PA3_DDR DDRA
-#undef PA4
-#define PA4_PIN PINA4
-#define PA4_RPORT PINA
-#define PA4_WPORT PORTA
-#define PA4_PWM NULL
-#define PA4_DDR DDRA
-#undef PA5
-#define PA5_PIN PINA5
-#define PA5_RPORT PINA
-#define PA5_WPORT PORTA
-#define PA5_PWM NULL
-#define PA5_DDR DDRA
-#undef PA6
-#define PA6_PIN PINA6
-#define PA6_RPORT PINA
-#define PA6_WPORT PORTA
-#define PA6_PWM NULL
-#define PA6_DDR DDRA
-#undef PA7
-#define PA7_PIN PINA7
-#define PA7_RPORT PINA
-#define PA7_WPORT PORTA
-#define PA7_PWM NULL
-#define PA7_DDR DDRA
-#undef PB0
-#define PB0_PIN PINB0
-#define PB0_RPORT PINB
-#define PB0_WPORT PORTB
-#define PB0_PWM NULL
-#define PB0_DDR DDRB
-#undef PB1
-#define PB1_PIN PINB1
-#define PB1_RPORT PINB
-#define PB1_WPORT PORTB
-#define PB1_PWM NULL
-#define PB1_DDR DDRB
-#undef PB2
-#define PB2_PIN PINB2
-#define PB2_RPORT PINB
-#define PB2_WPORT PORTB
-#define PB2_PWM NULL
-#define PB2_DDR DDRB
-#undef PB3
-#define PB3_PIN PINB3
-#define PB3_RPORT PINB
-#define PB3_WPORT PORTB
-#define PB3_PWM NULL
-#define PB3_DDR DDRB
-#undef PB4
-#define PB4_PIN PINB4
-#define PB4_RPORT PINB
-#define PB4_WPORT PORTB
-#define PB4_PWM NULL
-#define PB4_DDR DDRB
-#undef PB5
-#define PB5_PIN PINB5
-#define PB5_RPORT PINB
-#define PB5_WPORT PORTB
-#define PB5_PWM NULL
-#define PB5_DDR DDRB
-#undef PB6
-#define PB6_PIN PINB6
-#define PB6_RPORT PINB
-#define PB6_WPORT PORTB
-#define PB6_PWM NULL
-#define PB6_DDR DDRB
-#undef PB7
-#define PB7_PIN PINB7
-#define PB7_RPORT PINB
-#define PB7_WPORT PORTB
-#define PB7_PWM NULL
-#define PB7_DDR DDRB
-
-#undef PC0
-#define PC0_PIN PINC0
-#define PC0_RPORT PINC
-#define PC0_WPORT PORTC
-#define PC0_PWM NULL
-#define PC0_DDR DDRC
-#undef PC1
-#define PC1_PIN PINC1
-#define PC1_RPORT PINC
-#define PC1_WPORT PORTC
-#define PC1_PWM NULL
-#define PC1_DDR DDRC
-#undef PC2
-#define PC2_PIN PINC2
-#define PC2_RPORT PINC
-#define PC2_WPORT PORTC
-#define PC2_PWM NULL
-#define PC2_DDR DDRC
-#undef PC3
-#define PC3_PIN PINC3
-#define PC3_RPORT PINC
-#define PC3_WPORT PORTC
-#define PC3_PWM NULL
-#define PC3_DDR DDRC
-#undef PC4
-#define PC4_PIN PINC4
-#define PC4_RPORT PINC
-#define PC4_WPORT PORTC
-#define PC4_PWM NULL
-#define PC4_DDR DDRC
-#undef PC5
-#define PC5_PIN PINC5
-#define PC5_RPORT PINC
-#define PC5_WPORT PORTC
-#define PC5_PWM NULL
-#define PC5_DDR DDRC
-#undef PC6
-#define PC6_PIN PINC6
-#define PC6_RPORT PINC
-#define PC6_WPORT PORTC
-#define PC6_PWM NULL
-#define PC6_DDR DDRC
-#undef PC7
-#define PC7_PIN PINC7
-#define PC7_RPORT PINC
-#define PC7_WPORT PORTC
-#define PC7_PWM NULL
-#define PC7_DDR DDRC
-
-#undef PD0
-#define PD0_PIN PIND0
-#define PD0_RPORT PIND
-#define PD0_WPORT PORTD
-#define PD0_PWM NULL
-#define PD0_DDR DDRD
-#undef PD1
-#define PD1_PIN PIND1
-#define PD1_RPORT PIND
-#define PD1_WPORT PORTD
-#define PD1_PWM NULL
-#define PD1_DDR DDRD
-#undef PD2
-#define PD2_PIN PIND2
-#define PD2_RPORT PIND
-#define PD2_WPORT PORTD
-#define PD2_PWM NULL
-#define PD2_DDR DDRD
-#undef PD3
-#define PD3_PIN PIND3
-#define PD3_RPORT PIND
-#define PD3_WPORT PORTD
-#define PD3_PWM NULL
-#define PD3_DDR DDRD
-#undef PD4
-#define PD4_PIN PIND4
-#define PD4_RPORT PIND
-#define PD4_WPORT PORTD
-#define PD4_PWM NULL
-#define PD4_DDR DDRD
-#undef PD5
-#define PD5_PIN PIND5
-#define PD5_RPORT PIND
-#define PD5_WPORT PORTD
-#define PD5_PWM NULL
-#define PD5_DDR DDRD
-#undef PD6
-#define PD6_PIN PIND6
-#define PD6_RPORT PIND
-#define PD6_WPORT PORTD
-#define PD6_PWM NULL
-#define PD6_DDR DDRD
-#undef PD7
-#define PD7_PIN PIND7
-#define PD7_RPORT PIND
-#define PD7_WPORT PORTD
-#define PD7_PWM NULL
-#define PD7_DDR DDRD
-
-#undef PE0
-#define PE0_PIN PINE0
-#define PE0_RPORT PINE
-#define PE0_WPORT PORTE
-#define PE0_PWM NULL
-#define PE0_DDR DDRE
-#undef PE1
-#define PE1_PIN PINE1
-#define PE1_RPORT PINE
-#define PE1_WPORT PORTE
-#define PE1_PWM NULL
-#define PE1_DDR DDRE
-#undef PE2
-#define PE2_PIN PINE2
-#define PE2_RPORT PINE
-#define PE2_WPORT PORTE
-#define PE2_PWM NULL
-#define PE2_DDR DDRE
-#undef PE3
-#define PE3_PIN PINE3
-#define PE3_RPORT PINE
-#define PE3_WPORT PORTE
-#define PE3_PWM NULL
-#define PE3_DDR DDRE
-#undef PE4
-#define PE4_PIN PINE4
-#define PE4_RPORT PINE
-#define PE4_WPORT PORTE
-#define PE4_PWM NULL
-#define PE4_DDR DDRE
-#undef PE5
-#define PE5_PIN PINE5
-#define PE5_RPORT PINE
-#define PE5_WPORT PORTE
-#define PE5_PWM NULL
-#define PE5_DDR DDRE
-#undef PE6
-#define PE6_PIN PINE6
-#define PE6_RPORT PINE
-#define PE6_WPORT PORTE
-#define PE6_PWM NULL
-#define PE6_DDR DDRE
-#undef PE7
-#define PE7_PIN PINE7
-#define PE7_RPORT PINE
-#define PE7_WPORT PORTE
-#define PE7_PWM NULL
-#define PE7_DDR DDRE
-
-#undef PF0
-#define PF0_PIN PINF0
-#define PF0_RPORT PINF
-#define PF0_WPORT PORTF
-#define PF0_PWM NULL
-#define PF0_DDR DDRF
-#undef PF1
-#define PF1_PIN PINF1
-#define PF1_RPORT PINF
-#define PF1_WPORT PORTF
-#define PF1_PWM NULL
-#define PF1_DDR DDRF
-#undef PF2
-#define PF2_PIN PINF2
-#define PF2_RPORT PINF
-#define PF2_WPORT PORTF
-#define PF2_PWM NULL
-#define PF2_DDR DDRF
-#undef PF3
-#define PF3_PIN PINF3
-#define PF3_RPORT PINF
-#define PF3_WPORT PORTF
-#define PF3_PWM NULL
-#define PF3_DDR DDRF
-#undef PF4
-#define PF4_PIN PINF4
-#define PF4_RPORT PINF
-#define PF4_WPORT PORTF
-#define PF4_PWM NULL
-#define PF4_DDR DDRF
-#undef PF5
-#define PF5_PIN PINF5
-#define PF5_RPORT PINF
-#define PF5_WPORT PORTF
-#define PF5_PWM NULL
-#define PF5_DDR DDRF
-#undef PF6
-#define PF6_PIN PINF6
-#define PF6_RPORT PINF
-#define PF6_WPORT PORTF
-#define PF6_PWM NULL
-#define PF6_DDR DDRF
-#undef PF7
-#define PF7_PIN PINF7
-#define PF7_RPORT PINF
-#define PF7_WPORT PORTF
-#define PF7_PWM NULL
-#define PF7_DDR DDRF
+// Additional Pins for Davinci board
+#if (MOTHERBOARD == 999)
+//101
+#define DIO101_PORT PIOC
+#define DIO101_PIN PIO_PC27
+//108
+#define DIO108_PORT PIOC
+#define DIO108_PIN PIO_PC20
+//117
+#define DIO117_PORT PIOB
+#define DIO117_PIN PIO_PB2A_ETX0
+//118
+#define DIO118_PORT PIOB
+#define DIO118_PIN PIO_PB3A_ETX1
+//119
+#define DIO119_PORT PIOB
+#define DIO119_PIN PIO_PB4A_ECRSDV
+//120
+#define DIO120_PORT PIOB
+#define DIO120_PIN PIO_PB5A_ERX0
+//121
+#define DIO121_PORT PIOB
+#define DIO121_PIN PIO_PB6A_ERX1
+//122
+#define DIO122_PORT PIOB
+#define DIO122_PIN PIO_PB7A_ERXER
+//123
+#define DIO123_PORT PIOB
+#define DIO123_PIN PIO_PB8A_EMDC
+//124
+#define DIO124_PORT PIOB
+#define DIO124_PIN PIO_PB9A_EMDIO
+//125
+#define DIO125_PORT PIOB
+#define DIO125_PIN PIO_PB24
+//128
+#define DIO128_PORT PIOB
+#define DIO128_PIN PIO_PB22
+//129
+#define DIO129_PORT PIOB
+#define DIO129_PIN PIO_PB10B_A18
#endif
#ifndef DIO0_PIN
#error pins for this chip not defined in arduino.h! If you write an appropriate pin definition and have this firmware work on your chip, please submit a pull request
#endif
-#endif /* _ARDUINO_H */
+#endif /* _FASTIO_H */
diff --git a/src/ArduinoDUE/Repetier/gcode.cpp b/src/ArduinoDUE/Repetier/gcode.cpp
index af8b7d0..778e3ca 100644
--- a/src/ArduinoDUE/Repetier/gcode.cpp
+++ b/src/ArduinoDUE/Repetier/gcode.cpp
@@ -43,6 +43,9 @@ int8_t GCode::waitingForResend = -1; ///< Waiting for line to be resend. -1 =
volatile uint8_t GCode::bufferLength = 0; ///< Number of commands stored in gcode_buffer
millis_t GCode::timeOfLastDataPacket = 0; ///< Time, when we got the last data packet. Used to detect missing uint8_ts.
uint8_t GCode::formatErrors = 0;
+PGM_P GCode::fatalErrorMsg = NULL; ///< message unset = no fatal error
+millis_t GCode::lastBusySignal = 0; ///< When was the last busy signal
+uint32_t GCode::keepAliveInterval = KEEP_ALIVE_INTERVAL;
/** \page Repetier-protocol
@@ -149,6 +152,23 @@ uint8_t GCode::computeBinarySize(char *ptr) // unsigned int bitfield) {
return s;
}
+void GCode::keepAlive(enum FirmwareState state) {
+ millis_t now = HAL::timeInMilliseconds();
+
+ if(state != NotBusy && keepAliveInterval != 0) {
+ if(now - lastBusySignal < keepAliveInterval)
+ return;
+ if(state == Paused) {
+ Com::printFLN(PSTR("busy:paused for user interaction"));
+ } else if(state == WaitHeater) {
+ Com::printFLN(PSTR("busy:heating"));
+ } else { // processing and uncaught cases
+ Com::printFLN(PSTR("busy:processing"));
+ }
+ }
+ lastBusySignal = now;
+}
+
void GCode::requestResend()
{
HAL::serialFlush();
@@ -186,6 +206,8 @@ void GCode::checkAndPushCommand()
{
lastLineNumber++;
return;
+ } else if(M == 668) {
+ lastLineNumber = 0; // simulate a reset so lines are out of resend buffer
}
#endif // DEBUG_COM_ERRORS
}
@@ -219,14 +241,32 @@ void GCode::checkAndPushCommand()
return;
}
lastLineNumber = actLineNumber;
- }
- pushCommand();
+ } /*
+ This test is not compatible with all hosts. Replaced by forbidding backward switch of protocols.
+ else if(lastLineNumber && !(hasM() && M == 117)) { // once line number always line number!
+ if(Printer::debugErrors())
+ {
+ Com::printErrorFLN(PSTR("Missing linenumber"));
+ }
+ requestResend();
+ return;
+ }*/
+ if(GCode::hasFatalError() && !(hasM() && M==999)) {
+ GCode::reportFatalError();
+ } else {
+ pushCommand();
+ }
+#ifdef DEBUG_COM_ERRORS
+ if(hasM() && M == 667)
+ return; // omit ok
+#endif
#if ACK_WITH_LINENUMBER
Com::printFLN(Com::tOkSpace, actLineNumber);
#else
Com::printFLN(Com::tOk);
#endif
wasLastCommandReceivedAsBinary = sendAsBinary;
+ keepAlive(NotBusy);
waitingForResend = -1; // everything is ok.
}
@@ -305,8 +345,10 @@ void GCode::executeFString(FSTRINGPARAM(cmd))
buf[buflen++] = c;
}
while(buflen < 79);
- if(buflen == 0) // empty line ignore
+ if(buflen == 0) { // empty line ignore
+ if(!c) return; // Special case \n0
continue;
+ }
buf[buflen] = 0;
// Send command into command buffer
if(code.parseAscii((char *)buf,false) && (code.params & 518)) // Success
@@ -329,14 +371,17 @@ It must be called frequently to empty the incoming buffer.
*/
void GCode::readFromSerial()
{
- if(bufferLength >= GCODE_BUFFER_SIZE) return; // all buffers full
- if(waitUntilAllCommandsAreParsed && bufferLength) return;
+ if(bufferLength >= GCODE_BUFFER_SIZE || (waitUntilAllCommandsAreParsed && bufferLength)) {
+ keepAlive(Processing);
+ return; // all buffers full
+ }
waitUntilAllCommandsAreParsed = false;
millis_t time = HAL::timeInMilliseconds();
if(!HAL::serialByteAvailable())
{
if((waitingForResend >= 0 || commandsReceivingWritePosition > 0) && time - timeOfLastDataPacket > 200)
{
+ // Com::printF(PSTR("WFR:"),waitingForResend);Com::printF(PSTR(" CRWP:"),commandsReceivingWritePosition);commandReceiving[commandsReceivingWritePosition] = 0;Com::printFLN(PSTR(" GOT:"),(char*)commandReceiving);
requestResend(); // Something is wrong, a started line was not continued in the last second
timeOfLastDataPacket = time;
}
@@ -387,13 +432,15 @@ void GCode::readFromSerial()
return;
}
}
- else // Ascii command
+ else // ASCII command
{
char ch = commandReceiving[commandsReceivingWritePosition - 1];
- if(ch == 0 || ch == '\n' || ch == '\r' || (!commentDetected && ch == ':')) // complete line read
+ if(ch == 0 || ch == '\n' || ch == '\r' /*|| (!commentDetected && ch == ':')*/) // complete line read
{
- //Com::printF(PSTR("Parse ascii"));Com::print((char*)commandReceiving);Com::println();
commandReceiving[commandsReceivingWritePosition - 1] = 0;
+#ifdef DEBUG_ECHO_ASCII
+ Com::printF(PSTR("Got:"));Com::print((char*)commandReceiving);Com::println();
+#endif
commentDetected = false;
if(commandsReceivingWritePosition == 1) // empty line ignore
{
@@ -410,7 +457,7 @@ void GCode::readFromSerial()
}
else
{
- if(ch == ';') commentDetected = true; // ignore new data until lineend
+ if(ch == ';') commentDetected = true; // ignore new data until line end
if(commentDetected) commandsReceivingWritePosition--;
}
}
@@ -421,7 +468,7 @@ void GCode::readFromSerial()
}
}
#if SDSUPPORT
- if(sd.sdmode == 0 || commandsReceivingWritePosition != 0) // not reading or incoming serial command
+ if(sd.sdmode == 0 || sd.sdmode >= 100 || commandsReceivingWritePosition != 0) // not reading or incoming serial command
return;
while( sd.filesize > sd.sdpos && commandsReceivingWritePosition < MAX_CMD_SIZE) // consume data until no data or buffer full
{
@@ -493,7 +540,7 @@ void GCode::readFromSerial()
}
else
{
- if(ch == ';') commentDetected = true; // ignore new data until lineend
+ if(ch == ';') commentDetected = true; // ignore new data until line end
if(commentDetected) commandsReceivingWritePosition--;
}
}
@@ -513,7 +560,7 @@ void GCode::readFromSerial()
bool GCode::parseBinary(uint8_t *buffer,bool fromSerial)
{
internalCommand = !fromSerial;
- unsigned int sum1 = 0,sum2 = 0; // for fletcher-16 checksum
+ unsigned int sum1 = 0, sum2 = 0; // for fletcher-16 checksum
// first do fletcher-16 checksum tests see
// http://en.wikipedia.org/wiki/Fletcher's_checksum
uint8_t *p = buffer;
@@ -542,13 +589,13 @@ bool GCode::parseBinary(uint8_t *buffer,bool fromSerial)
return false;
}
p = buffer;
- params = *(unsigned int *)p;
+ params = *(uint16_t *)p;
p += 2;
uint8_t textlen = 16;
if(isV2())
{
- params2 = *(unsigned int *)p;
- p+=2;
+ params2 = *(uint16_t *)p;
+ p += 2;
if(hasString())
textlen = *p++;
}
@@ -556,16 +603,16 @@ bool GCode::parseBinary(uint8_t *buffer,bool fromSerial)
if(params & 1)
{
actLineNumber = N = *(uint16_t *)p;
- p+=2;
+ p += 2;
}
if(isV2()) // Read G,M as 16 bit value
{
- if(params & 2)
+ if(hasM())
{
M = *(uint16_t *)p;
p += 2;
}
- if(params & 4)
+ if(hasG())
{
G = *(uint16_t *)p;
p += 2;
@@ -573,51 +620,51 @@ bool GCode::parseBinary(uint8_t *buffer,bool fromSerial)
}
else
{
- if(params & 2)
+ if(hasM())
{
M = *p++;
}
- if(params & 4)
+ if(hasG())
{
G = *p++;
}
}
//if(code->params & 8) {memcpy(&code->X,p,4);p+=4;}
- if(params & 8)
+ if(hasX())
{
X = *(float *)p;
p += 4;
}
- if(params & 16)
+ if(hasY())
{
Y = *(float *)p;
p += 4;
}
- if(params & 32)
+ if(hasZ())
{
Z = *(float *)p;
p += 4;
}
- if(params & 64)
+ if(hasE())
{
E = *(float *)p;
p += 4;
}
- if(params & 256)
+ if(hasF())
{
F = *(float *)p;
p += 4;
}
- if(params & 512)
+ if(hasT())
{
T = *p++;
}
- if(params & 1024)
+ if(hasS())
{
S = *(int32_t*)p;
p += 4;
}
- if(params & 2048)
+ if(hasP())
{
P = *(int32_t*)p;
p += 4;
@@ -681,14 +728,14 @@ bool GCode::parseBinary(uint8_t *buffer,bool fromSerial)
{
text = (char*)p;
text[textlen] = 0; // Terminate string overwriting checksum
- waitUntilAllCommandsAreParsed=true; // Don't destroy string until executed
+ waitUntilAllCommandsAreParsed = true; // Don't destroy string until executed
}
formatErrors = 0;
return true;
}
/**
- Converts a ascii GCode line into a GCode structure.
+ Converts a ASCII GCode line into a GCode structure.
*/
bool GCode::parseAscii(char *line,bool fromSerial)
{
@@ -696,9 +743,11 @@ bool GCode::parseAscii(char *line,bool fromSerial)
params = 0;
params2 = 0;
internalCommand = !fromSerial;
+ bool hasChecksum = false;
char c;
while ( (c = *(pos++)) )
{
+ if(c == '(' || c == '%') break; // alternative comment or program block
switch(c)
{
case 'N':
@@ -721,10 +770,10 @@ bool GCode::parseAscii(char *line,bool fromSerial)
case 'm':
{
M = parseLongValue(pos) & 0xffff;
- params |=2;
+ params |= 2;
if(M > 255) params |= 4096;
// handle non standard text arguments that some M codes have
- if (M == 23 || M == 28 || M == 29 || M == 30 || M == 32 || M == 117)
+ if (M == 20 || M == 23 || M == 28 || M == 29 || M == 30 || M == 32 || M == 36 || M == 117)
{
// after M command we got a filename or text
char digit;
@@ -737,15 +786,15 @@ bool GCode::parseAscii(char *line,bool fromSerial)
{
if (digit != ' ') break;
pos++;
- // skip leading whitespaces (may be no white space)
+ // skip leading white spaces (may be no white space)
}
text = pos;
while (*pos)
{
- if((M != 117 && *pos==' ') || *pos=='*') break;
+ if((M != 117 && M != 20 && *pos==' ') || *pos=='*') break;
pos++; // find a space as file name end
}
- *pos = 0; // truncate filename by erasing space with nul, also skips checksum
+ *pos = 0; // truncate filename by erasing space with null, also skips checksum
waitUntilAllCommandsAreParsed = true; // don't risk string be deleted
params |= 32768;
}
@@ -839,11 +888,67 @@ bool GCode::parseAscii(char *line,bool fromSerial)
params |= 4096; // Needs V2 for saving
break;
}
+ case 'C':
+ case 'c':
+ {
+ C = parseFloatValue(pos);
+ params2 |= 16;
+ params |= 4096; // Needs V2 for saving
+ break;
+ }
+ case 'H':
+ case 'h':
+ {
+ H = parseFloatValue(pos);
+ params2 |= 32;
+ params |= 4096; // Needs V2 for saving
+ break;
+ }
+ case 'A':
+ case 'a':
+ {
+ A = parseFloatValue(pos);
+ params2 |= 64;
+ params |= 4096; // Needs V2 for saving
+ break;
+ }
+ case 'B':
+ case 'b':
+ {
+ B = parseFloatValue(pos);
+ params2 |= 128;
+ params |= 4096; // Needs V2 for saving
+ break;
+ }
+ case 'K':
+ case 'k':
+ {
+ K = parseFloatValue(pos);
+ params2 |= 256;
+ params |= 4096; // Needs V2 for saving
+ break;
+ }
+ case 'L':
+ case 'l':
+ {
+ L = parseFloatValue(pos);
+ params2 |= 512;
+ params |= 4096; // Needs V2 for saving
+ break;
+ }
+ case 'O':
+ case 'o':
+ {
+ O = parseFloatValue(pos);
+ params2 |= 1024;
+ params |= 4096; // Needs V2 for saving
+ break;
+ }
case '*' : //checksum
{
uint8_t checksum_given = parseLongValue(pos);
uint8_t checksum = 0;
- while(line != (pos-1)) checksum ^= *line++;
+ while(line != (pos - 1)) checksum ^= *line++;
#if FEATURE_CHECKSUM_FORCED
Printer::flag0 |= PRINTER_FLAG0_FORCE_CHECKSUM;
#endif
@@ -855,19 +960,23 @@ bool GCode::parseAscii(char *line,bool fromSerial)
}
return false; // mismatch
}
+ hasChecksum = true;
break;
}
default:
break;
}// end switch
}// end while
-
- if(hasFormatError() || (params & 518)==0) // Must contain G, M or T command and parameter need to have variables!
+ if(wasLastCommandReceivedAsBinary && !hasChecksum && fromSerial && !waitUntilAllCommandsAreParsed) {
+ Com::printErrorFLN("Checksum required when switching back to ASCII protocol.");
+ return false;
+ }
+ if(hasFormatError() /*|| (params & 518) == 0*/) // Must contain G, M or T command and parameter need to have variables!
{
formatErrors++;
if(Printer::debugErrors())
Com::printErrorFLN(Com::tFormatError);
- if(formatErrors<3) return false;
+ if(formatErrors < 3) return false;
}
else formatErrors = 0;
return true;
@@ -878,7 +987,7 @@ void GCode::printCommand()
{
if(hasN()) {
Com::print('N');
- Com::print((long)N);
+ Com::print((int32_t)N);
Com::print(' ');
}
if(hasM())
@@ -945,3 +1054,224 @@ void GCode::printCommand()
}
Com::println();
}
+
+void GCode::fatalError(FSTRINGPARAM(message)) {
+ fatalErrorMsg = message;
+#if SDSUPPORT
+ if(sd.sdmode != 0) { // stop sd print to prevent damage
+ sd.stopPrint();
+ }
+#endif
+ if(Printer::currentPosition[Z_AXIS] < Printer::zMin + Printer::zLength - 15)
+ PrintLine::moveRelativeDistanceInSteps(0, 0, 10 * Printer::axisStepsPerMM[Z_AXIS], 0, Printer::homingFeedrate[Z_AXIS], true, true);
+ EVENT_FATAL_ERROR_OCCURED
+ Commands::waitUntilEndOfAllMoves();
+ reportFatalError();
+ Printer::kill(false);
+}
+
+void GCode::reportFatalError() {
+ Com::printF(Com::tFatal);
+ Com::printF(fatalErrorMsg);
+ Com::printFLN(PSTR(" Printer stopped and heaters disabled due to this error. Fix error and restart with M999."));
+ UI_ERROR_P(fatalErrorMsg)
+}
+
+void GCode::resetFatalError() {
+ TemperatureController::resetAllErrorStates();
+ Printer::debugReset(8); // disable dry run
+ fatalErrorMsg = NULL;
+ UI_ERROR("");
+ EVENT_CONTINUE_FROM_FATAL_ERROR
+ Com::printFLN(PSTR("info:Continue from fatal state"));
+}
+
+#if JSON_OUTPUT
+
+// --------------------------------------------------------------- //
+// Code that gets gcode information is adapted from RepRapFirmware //
+// Originally licensed under GPL //
+// Authors: reprappro, dc42, dcnewman, others //
+// Source: https://github.com/dcnewman/RepRapFirmware //
+// Copy date: 15 Nov 2015 //
+// --------------------------------------------------------------- //
+
+void GCodeFileInfo::init(SdBaseFile &file) {
+ this->fileSize = file.fileSize();
+ this->filamentNeeded = 0.0;
+ this->objectHeight = 0.0;
+ this->layerHeight = 0.0;
+ if (!file.isOpen()) return;
+ bool genByFound = false, layerHeightFound = false, filamentNeedFound = false;
+ #if CPU_ARCH==ARCH_AVR
+ #define GCI_BUF_SIZE 120
+ #else
+ #define GCI_BUF_SIZE 1024
+ #endif
+ // READ 4KB FROM THE BEGINNING
+ char buf[GCI_BUF_SIZE];
+ for (int i = 0; i < 4096; i += GCI_BUF_SIZE-50) {
+ if(!file.seekSet(i)) break;
+ file.read(buf, GCI_BUF_SIZE);
+ if (!genByFound && findGeneratedBy(buf, this->generatedBy)) genByFound = true;
+ if (!layerHeightFound && findLayerHeight(buf, this->layerHeight)) layerHeightFound = true;
+ if (!filamentNeedFound && findFilamentNeed(buf, this->filamentNeeded)) filamentNeedFound = true;
+ if(genByFound && layerHeightFound && filamentNeedFound) goto get_objectHeight;
+ }
+
+ // READ 4KB FROM END
+ for (int i = 0; i < 4096; i += GCI_BUF_SIZE-50) {
+ if(!file.seekEnd(-4096 + i)) break;
+ file.read(buf, GCI_BUF_SIZE);
+ if (!genByFound && findGeneratedBy(buf, this->generatedBy)) genByFound = true;
+ if (!layerHeightFound && findLayerHeight(buf, this->layerHeight)) layerHeightFound = true;
+ if (!filamentNeedFound && findFilamentNeed(buf, this->filamentNeeded)) filamentNeedFound = true;
+ if(genByFound && layerHeightFound && filamentNeedFound) goto get_objectHeight;
+ }
+
+ get_objectHeight:
+ // MOVE FROM END UP IN 1KB BLOCKS UP TO 30KB
+ for (int i = GCI_BUF_SIZE; i < 30000; i += GCI_BUF_SIZE-50) {
+ if(!file.seekEnd(-i)) break;
+ file.read(buf, GCI_BUF_SIZE);
+ if (findTotalHeight(buf, this->objectHeight)) break;
+ }
+ file.seekSet(0);
+}
+
+bool GCodeFileInfo::findGeneratedBy(char *buf, char *genBy) {
+ // Slic3r & S3D
+ const char* generatedByString = PSTR("generated by ");
+ char* pos = strstr_P(buf, generatedByString);
+ if (pos) {
+ pos += strlen_P(generatedByString);
+ size_t i = 0;
+ while (i < GENBY_SIZE - 1 && *pos >= ' ') {
+ char c = *pos++;
+ if (c == '"' || c == '\\') {
+ // Need to escape the quote-mark for JSON
+ if (i > GENBY_SIZE - 3) break;
+ genBy[i++] = '\\';
+ }
+ genBy[i++] = c;
+ }
+ genBy[i] = 0;
+ return true;
+ }
+
+ // CURA
+ const char* slicedAtString = PSTR(";Sliced at: ");
+ pos = strstr_P(buf, slicedAtString);
+ if (pos) {
+ strcpy_P(genBy, PSTR("Cura"));
+ return true;
+ }
+
+ // UNKNOWN
+ strcpy_P(genBy, PSTR("Unknown"));
+ return false;
+}
+
+bool GCodeFileInfo::findLayerHeight(char *buf, float &layerHeight) {
+ // SLIC3R
+ layerHeight = 0;
+ const char* layerHeightSlic3r = PSTR("; layer_height ");
+ char *pos = strstr_P(buf, layerHeightSlic3r);
+ if (pos) {
+ pos += strlen_P(layerHeightSlic3r);
+ while (*pos == ' ' || *pos == 't' || *pos == '=' || *pos == ':') {
+ ++pos;
+ }
+ layerHeight = strtod(pos, NULL);
+ return true;
+ }
+
+ // CURA
+ const char* layerHeightCura = PSTR("Layer height: ");
+ pos = strstr_P(buf, layerHeightCura);
+ if (pos) {
+ pos += strlen_P(layerHeightCura);
+ while (*pos == ' ' || *pos == 't' || *pos == '=' || *pos == ':') {
+ ++pos;
+ }
+ layerHeight = strtod(pos, NULL);
+ return true;
+ }
+
+ return false;
+}
+
+bool GCodeFileInfo::findFilamentNeed(char *buf, float &filament) {
+ const char* filamentUsedStr = PSTR("filament used");
+ const char* pos = strstr_P(buf, filamentUsedStr);
+ filament = 0;
+ if (pos != NULL) {
+ pos += strlen_P(filamentUsedStr);
+ while (*pos == ' ' || *pos == 't' || *pos == '=' || *pos == ':') {
+ ++pos; // this allows for " = " from default slic3r comment and ": " from default Cura comment
+ }
+ if (isDigit(*pos)) {
+ char *q;
+ filament += strtod(pos, &q);
+ if (*q == 'm' && *(q + 1) != 'm') {
+ filament *= 1000.0; // Cura outputs filament used in metres not mm
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+bool GCodeFileInfo::findTotalHeight(char *buf, float &height) {
+ int len = 1024;
+ bool inComment, inRelativeMode = false;
+ unsigned int zPos;
+ for (int i = len - 5; i > 0; i--) {
+ if (inRelativeMode) {
+ inRelativeMode = !(buf[i] == 'G' && buf[i + 1] == '9' && buf[i + 2] == '1' && buf[i + 3] <= ' ');
+ } else if (buf[i] == 'G') {
+ // Ignore G0/G1 codes if absolute mode was switched back using G90 (typical for Cura files)
+ if (buf[i + 1] == '9' && buf[i + 2] == '0' && buf[i + 3] <= ' ') {
+ inRelativeMode = true;
+ } else if ((buf[i + 1] == '0' || buf[i + 1] == '1') && buf[i + 2] == ' ') {
+ // Look for last "G0/G1 ... Z#HEIGHT#" command as generated by common slicers
+ // Looks like we found a controlled move, however it could be in a comment, especially when using slic3r 1.1.1
+ inComment = false;
+ size_t j = i;
+ while (j != 0) {
+ --j;
+ char c = buf[j];
+ if (c == '\n' || c == '\r') break;
+ if (c == ';') {
+ // It is in a comment, so give up on this one
+ inComment = true;
+ break;
+ }
+ }
+ if (inComment) continue;
+
+ // Find 'Z' position and grab that value
+ zPos = 0;
+ for (int j = i + 3; j < len - 2; j++) {
+ char c = buf[j];
+ if (c < ' ') {
+ // Skip all whitespaces...
+ while (j < len - 2 && c <= ' ') {
+ c = buf[++j];
+ }
+ // ...to make sure ";End" doesn't follow G0 .. Z#HEIGHT#
+ if (zPos != 0) {
+ //debugPrintf("Found at offset %u text: %.100s\n", zPos, &buf[zPos + 1]);
+ height = strtod(&buf[zPos + 1], NULL);
+ return true;
+ }
+ break;
+ } else if (c == ';') break;
+ else if (c == 'Z') zPos = j;
+ }
+ }
+ }
+ }
+ return false;
+}
+#endif // JSON_OUTPUT
diff --git a/src/ArduinoDUE/Repetier/gcode.h b/src/ArduinoDUE/Repetier/gcode.h
index 5bf0531..7ec292f 100644
--- a/src/ArduinoDUE/Repetier/gcode.h
+++ b/src/ArduinoDUE/Repetier/gcode.h
@@ -19,22 +19,26 @@
#define _GCODE_H
#define MAX_CMD_SIZE 96
+#define ARRAY_SIZE(_x) (sizeof(_x)/sizeof(_x[0]))
+
+enum FirmwareState {NotBusy=0,Processing,Paused,WaitHeater};
+
class SDCard;
class GCode // 52 uint8_ts per command needed
{
- unsigned int params;
- unsigned int params2;
+ uint16_t params;
+ uint16_t params2;
public:
- unsigned int N; // Line number
- unsigned int M;
- unsigned int G;
+ uint16_t N; // Line number
+ uint16_t M;
+ uint16_t G;
float X;
float Y;
float Z;
float E;
float F;
- long S;
- long P;
+ int32_t S;
+ int32_t P;
float I;
float J;
float R;
@@ -71,14 +75,23 @@ public:
{
return ((params & 8)!=0);
}
+ inline void unsetX() {
+ params &= ~8;
+ }
inline bool hasY()
{
return ((params & 16)!=0);
}
+ inline void unsetY() {
+ params &= ~16;
+ }
inline bool hasZ()
{
return ((params & 32)!=0);
}
+ inline void unsetZ() {
+ params &= ~32;
+ }
inline bool hasNoXYZ()
{
return ((params & 56)==0);
@@ -181,9 +194,17 @@ public:
static void pushCommand();
static void executeFString(FSTRINGPARAM(cmd));
static uint8_t computeBinarySize(char *ptr);
-
+ static void fatalError(FSTRINGPARAM(message));
+ static void reportFatalError();
+ static void resetFatalError();
+ inline static bool hasFatalError() {
+ return fatalErrorMsg != NULL;
+ }
+ static void keepAlive(enum FirmwareState state);
+ static uint32_t keepAliveInterval;
friend class SDCard;
friend class UIDisplay;
+ static FSTRINGPARAM(fatalErrorMsg);
private:
void debugCommandBuffer();
void checkAndPushCommand();
@@ -191,6 +212,7 @@ private:
inline float parseFloatValue(char *s)
{
char *endPtr;
+ while(*s == 32) s++; // skip spaces
float f = (strtod(s, &endPtr));
if(s == endPtr) f=0.0; // treat empty string "x " as "x0"
return f;
@@ -198,6 +220,7 @@ private:
inline long parseLongValue(char *s)
{
char *endPtr;
+ while(*s == 32) s++; // skip spaces
long l = (strtol(s, &endPtr, 10));
if(s == endPtr) l=0; // treat empty string argument "p " as "p0"
return l;
@@ -219,8 +242,29 @@ private:
static volatile uint8_t bufferLength; ///< Number of commands stored in gcode_buffer
static millis_t timeOfLastDataPacket; ///< Time, when we got the last data packet. Used to detect missing uint8_ts.
static uint8_t formatErrors; ///< Number of sequential format errors
+ static millis_t lastBusySignal; ///< When was the last busy signal
};
+#if JSON_OUTPUT
+#include "SdFat.h"
+// Struct to hold Gcode file information 32 bytes
+#define GENBY_SIZE 16
+class GCodeFileInfo {
+public:
+ void init(SdBaseFile &file);
+
+ unsigned long fileSize;
+ float objectHeight;
+ float layerHeight;
+ float filamentNeeded;
+ char generatedBy[GENBY_SIZE];
+
+ bool findGeneratedBy(char *buf, char *genBy);
+ bool findLayerHeight(char *buf, float &layerHeight);
+ bool findFilamentNeed(char *buf, float &filament);
+ bool findTotalHeight(char *buf, float &objectHeight);
+};
+#endif
#endif
diff --git a/src/ArduinoDUE/Repetier/logo.h b/src/ArduinoDUE/Repetier/logo.h
index 87f8623..979aafc 100644
--- a/src/ArduinoDUE/Repetier/logo.h
+++ b/src/ArduinoDUE/Repetier/logo.h
@@ -3,6 +3,7 @@
// http://en.radzio.dxp.pl/bitmap_converter/
//------------------------------------------------------------------------------
+#ifndef CUSTOM_LOGO
#define LOGO_WIDTH 60
#define LOGO_HEIGHT 64
@@ -39,39 +40,7 @@ const unsigned char logo[] PROGMEM = { //AVR-GCC, WinAVR
0x00, 0x07, 0xFF, 0xFF, 0xF8, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFC, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0xF8, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-/*
-0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F,
-0xFF, 0xFF, 0xF7, 0x83, 0xC1, 0xF0, 0x1E, 0x0F, 0xFF, 0xFF, 0x7C, 0x0F, 0x07, 0xC0, 0x78, 0x0F,
-0xFF, 0xFD, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x3F, 0xFF, 0xDF, 0x80, 0x00, 0x00, 0x07, 0xC0, 0x7F,
-0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0xDF, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x0B, 0xFF, 0xFC, 0x03, 0xFF,
-0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF,
-0xF0, 0x50, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0xD0, 0x00, 0x7F, 0x7F,
-0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x7E, 0x7F, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFC, 0x7F,
-0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF8, 0x3F, 0xF1, 0xEF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0x3F,
-0xF9, 0xE0, 0x00, 0x0F, 0xFF, 0xF0, 0xE0, 0x3F, 0xF1, 0xE0, 0x00, 0x00, 0xFF, 0xF8, 0xE0, 0x3F,
-0xF9, 0xE0, 0x00, 0x00, 0x3F, 0xF0, 0xE3, 0x3F, 0xF1, 0xE0, 0x00, 0x00, 0x1F, 0xF8, 0xE3, 0x7F,
-0xF9, 0xE0, 0x00, 0x00, 0x0F, 0xF0, 0xE7, 0x3F, 0xF1, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0xE7, 0x7F,
-0xF9, 0xE0, 0x08, 0x00, 0x0F, 0xF0, 0xE7, 0x7F, 0xF1, 0xE0, 0x0F, 0xE0, 0x07, 0xF8, 0xE7, 0x7F,
-0xF9, 0xE0, 0x0F, 0xE0, 0x07, 0xF0, 0xE7, 0x7F, 0xF1, 0xE0, 0x0F, 0xF0, 0x07, 0xF8, 0xE6, 0x7F,
-0xF9, 0xE0, 0x0F, 0xF0, 0x07, 0xF0, 0xE0, 0x7F, 0xF9, 0xE0, 0x0F, 0xF0, 0x07, 0xF8, 0xE0, 0xFF,
-0xF9, 0xE0, 0x0F, 0xE0, 0x07, 0xF0, 0xE0, 0xFF, 0xF9, 0xE0, 0x00, 0x00, 0x07, 0xF8, 0xE1, 0xFF,
-0xF9, 0xE0, 0x00, 0x00, 0x0F, 0xF0, 0xE3, 0xFF, 0xF9, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0xE3, 0xFF,
-0xF9, 0xE0, 0x00, 0x00, 0x1F, 0xF8, 0xE7, 0xFF, 0xF9, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0xE7, 0xFF,
-0xF9, 0xE0, 0x00, 0x01, 0xFF, 0xF8, 0xE7, 0xFF, 0xF9, 0xE0, 0x0C, 0x01, 0xFF, 0xF8, 0xE7, 0xFF,
-0xF9, 0xE0, 0x0E, 0x00, 0x7F, 0xF8, 0xE7, 0xFF, 0xF9, 0xE0, 0x0F, 0x00, 0x7F, 0xF8, 0xE7, 0xFF,
-0xF9, 0xE0, 0x0F, 0x00, 0x3F, 0xF8, 0xE7, 0xFF, 0xF9, 0xE0, 0x0F, 0x80, 0x1F, 0xF8, 0xE7, 0xFF,
-0xF9, 0xE0, 0x0F, 0x80, 0x1F, 0xF8, 0xE7, 0xFF, 0xF9, 0xE0, 0x0F, 0xC0, 0x0F, 0xF8, 0xE7, 0xFF,
-0xF9, 0xE0, 0x0F, 0xC0, 0x0F, 0xF8, 0xE7, 0xFF, 0xF9, 0xE0, 0x0F, 0xE0, 0x07, 0xF8, 0xEF, 0xFF,
-0xF9, 0xF0, 0x0F, 0xE0, 0x07, 0xF8, 0xEF, 0xFF, 0xF9, 0xE0, 0x0F, 0xF0, 0x03, 0xF8, 0xFF, 0xFF,
-0xF9, 0xF0, 0x0F, 0xF0, 0x03, 0xF8, 0xFF, 0xFF, 0xF9, 0xFE, 0x0F, 0xF8, 0x03, 0xF8, 0xFF, 0xFF,
-0xF9, 0xFF, 0xFF, 0xF8, 0x01, 0xF8, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x81, 0xF8, 0xFF, 0xFF,
-0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xF8, 0x7F, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF,
-0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xF8, 0xDF, 0xFF, 0xF8, 0x00, 0x00, 0xFF, 0xFF, 0xF8, 0x7F, 0xFF,
-0xFF, 0x40, 0x00, 0x00, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xC0, 0x7F, 0xFF,
-0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x80, 0x00, 0xFF, 0xFF,
-0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xAF, 0xFF, 0xFF, 0xFF,
-0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF
-*/
};
-
+#else
+LOGO_BITMAP
+#endif
diff --git a/src/ArduinoDUE/Repetier/motion.cpp b/src/ArduinoDUE/Repetier/motion.cpp
index ba65b4e..7326d73 100644
--- a/src/ArduinoDUE/Repetier/motion.cpp
+++ b/src/ArduinoDUE/Repetier/motion.cpp
@@ -27,7 +27,7 @@
#ifndef STEP_DOUBLER_FREQUENCY
#error Please add new parameter STEP_DOUBLER_FREQUENCY to your configuration.
#else
-#if STEP_DOUBLER_FREQUENCY<10000 || STEP_DOUBLER_FREQUENCY>20000
+#if STEP_DOUBLER_FREQUENCY < 10000 || STEP_DOUBLER_FREQUENCY > 20000
#if CPU_ARCH==ARCH_AVR
#error STEP_DOUBLER_FREQUENCY should be in range 10000-16000.
#endif
@@ -36,9 +36,6 @@
#ifdef EXTRUDER_SPEED
#error EXTRUDER_SPEED is not used any more. Values are now taken from extruder definition.
#endif
-#if MAX_HALFSTEP_INTERVAL<=1900
-#error MAX_HALFSTEP_INTERVAL must be greater then 1900
-#endif
#ifdef ENDSTOPPULLUPS
#error ENDSTOPPULLUPS is now replaced by individual pullup configuration!
#endif
@@ -46,30 +43,30 @@
#error The PID system has changed. Please use the new float number options!
#endif
// ####################################################################################
-// # No configuration below this line - just some errorchecking #
+// # No configuration below this line - just some error checking #
// ####################################################################################
#ifdef SUPPORT_MAX6675
#if !defined SCK_PIN || !defined MOSI_PIN || !defined MISO_PIN
#error For MAX6675 support, you need to define SCK_PIN, MISO_PIN and MOSI_PIN in pins.h
#endif
#endif
-#if X_STEP_PIN<0 || Y_STEP_PIN<0 || Z_STEP_PIN<0
+#if X_STEP_PIN < 0 || Y_STEP_PIN < 0 || Z_STEP_PIN < 0
#error One of the following pins is not assigned: X_STEP_PIN,Y_STEP_PIN,Z_STEP_PIN
#endif
-#if EXT0_STEP_PIN<0 && NUM_EXTRUDER>0
+#if EXT0_STEP_PIN < 0 && NUM_EXTRUDER > 0
#error EXT0_STEP_PIN not set to a pin number.
#endif
-#if EXT0_DIR_PIN<0 && NUM_EXTRUDER>0
+#if EXT0_DIR_PIN < 0 && NUM_EXTRUDER > 0
#error EXT0_DIR_PIN not set to a pin number.
#endif
-#if PRINTLINE_CACHE_SIZE<4
+#if PRINTLINE_CACHE_SIZE < 4
#error PRINTLINE_CACHE_SIZE must be at least 5
#endif
//Inactivity shutdown variables
millis_t previousMillisCmd = 0;
-millis_t maxInactiveTime = MAX_INACTIVE_TIME*1000L;
-millis_t stepperInactiveTime = STEPPER_INACTIVE_TIME*1000L;
+millis_t maxInactiveTime = MAX_INACTIVE_TIME * 1000L;
+millis_t stepperInactiveTime = STEPPER_INACTIVE_TIME * 1000L;
long baudrate = BAUDRATE; ///< Communication speed rate.
#if USE_ADVANCE
#if ENABLE_QUADRATIC_ADVANCE
@@ -78,27 +75,45 @@ int maxadv = 0;
int maxadv2 = 0;
float maxadvspeed = 0;
#endif
-uint8_t pwm_pos[NUM_EXTRUDER+3]; // 0-NUM_EXTRUDER = Heater 0-NUM_EXTRUDER of extruder, NUM_EXTRUDER = Heated bed, NUM_EXTRUDER+1 Board fan, NUM_EXTRUDER+2 = Fan
+uint8_t pwm_pos[NUM_PWM]; // 0-NUM_EXTRUDER = Heater 0-NUM_EXTRUDER of extruder, NUM_EXTRUDER = Heated bed, NUM_EXTRUDER+1 Board fan, NUM_EXTRUDER+2 = Fan
volatile int waitRelax = 0; // Delay filament relax at the end of print, could be a simple timeout
PrintLine PrintLine::lines[PRINTLINE_CACHE_SIZE]; ///< Cache for print moves.
-PrintLine *PrintLine::cur = 0; ///< Current printing line
+PrintLine *PrintLine::cur = NULL; ///< Current printing line
#if CPU_ARCH == ARCH_ARM
volatile bool PrintLine::nlFlag = false;
#endif
-uint8_t PrintLine::linesWritePos = 0; ///< Position where we write the next cached line move.
-volatile uint8_t PrintLine::linesCount = 0; ///< Number of lines cached 0 = nothing to do.
-uint8_t PrintLine::linesPos = 0; ///< Position for executing line movement.
+ufast8_t PrintLine::linesWritePos = 0; ///< Position where we write the next cached line move.
+volatile ufast8_t PrintLine::linesCount = 0; ///< Number of lines cached 0 = nothing to do.
+ufast8_t PrintLine::linesPos = 0; ///< Position for executing line movement.
/**
Move printer the given number of steps. Puts the move into the queue. Used by e.g. homing commands.
+Does not consider rotation but updates position correctly considering rotation.
*/
-void PrintLine::moveRelativeDistanceInSteps(int32_t x,int32_t y,int32_t z,int32_t e,float feedrate,bool waitEnd,bool checkEndstop)
+void PrintLine::moveRelativeDistanceInSteps(int32_t x, int32_t y, int32_t z, int32_t e, float feedrate, bool waitEnd, bool checkEndstop,bool pathOptimize)
{
#if NUM_EXTRUDER > 0
if(Printer::debugDryrun() || (MIN_EXTRUDER_TEMP > 30 && Extruder::current->tempControl.currentTemperatureC < MIN_EXTRUDER_TEMP && !Printer::isColdExtrusionAllowed()))
e = 0; // should not be allowed for current temperature
#endif
+#if MOVE_X_WHEN_HOMED == 1 || MOVE_Y_WHEN_HOMED == 1 || MOVE_Z_WHEN_HOMED == 1
+ if(!Printer::isHoming() && !Printer::isNoDestinationCheck()) {
+#if MOVE_X_WHEN_HOMED
+ if(!Printer::isXHomed())
+ x = 0;
+#endif
+#if MOVE_Y_WHEN_HOMED
+ if(!Printer::isYHomed())
+ y = 0;
+#endif
+#if MOVE_Z_WHEN_HOMED
+ if(!Printer::isZHomed() && !Printer::isZProbingActive())
+ z = 0;
+#endif
+ }
+#endif
+
float savedFeedrate = Printer::feedrate;
Printer::destinationSteps[X_AXIS] = Printer::currentPositionSteps[X_AXIS] + x;
Printer::destinationSteps[Y_AXIS] = Printer::currentPositionSteps[Y_AXIS] + y;
@@ -106,12 +121,12 @@ void PrintLine::moveRelativeDistanceInSteps(int32_t x,int32_t y,int32_t z,int32_
Printer::destinationSteps[E_AXIS] = Printer::currentPositionSteps[E_AXIS] + e;
Printer::feedrate = feedrate;
#if NONLINEAR_SYSTEM
- if (!queueDeltaMove(checkEndstop, false, false))
+ if (!queueNonlinearMove(checkEndstop, pathOptimize, false))
{
Com::printWarningFLN(PSTR("moveRelativeDistanceInSteps / queueDeltaMove returns error"));
}
#else
- queueCartesianMove(checkEndstop, false);
+ queueCartesianMove(checkEndstop, pathOptimize);
#endif
Printer::feedrate = savedFeedrate;
Printer::updateCurrentPosition(false);
@@ -120,8 +135,24 @@ void PrintLine::moveRelativeDistanceInSteps(int32_t x,int32_t y,int32_t z,int32_
previousMillisCmd = HAL::timeInMilliseconds();
}
-void PrintLine::moveRelativeDistanceInStepsReal(int32_t x,int32_t y,int32_t z,int32_t e,float feedrate,bool waitEnd)
+void PrintLine::moveRelativeDistanceInStepsReal(int32_t x, int32_t y, int32_t z, int32_t e, float feedrate, bool waitEnd,bool pathOptimize)
{
+#if MOVE_X_WHEN_HOMED == 1 || MOVE_Y_WHEN_HOMED == 1 || MOVE_Z_WHEN_HOMED == 1
+ if(!Printer::isHoming() && !Printer::isNoDestinationCheck()) { // prevent movements when not homed
+#if MOVE_X_WHEN_HOMED
+ if(!Printer::isXHomed())
+ x = 0;
+#endif
+#if MOVE_Y_WHEN_HOMED
+ if(!Printer::isYHomed())
+ y = 0;
+#endif
+#if MOVE_Z_WHEN_HOMED
+ if(!Printer::isZHomed() && !Printer::isZProbingActive())
+ z = 0;
+#endif
+ }
+#endif
Printer::lastCmdPos[X_AXIS] += x * Printer::invAxisStepsPerMM[X_AXIS];
Printer::lastCmdPos[Y_AXIS] += y * Printer::invAxisStepsPerMM[Y_AXIS];
Printer::lastCmdPos[Z_AXIS] += z * Printer::invAxisStepsPerMM[Z_AXIS];
@@ -134,7 +165,7 @@ void PrintLine::moveRelativeDistanceInStepsReal(int32_t x,int32_t y,int32_t z,in
e = 0; // should not be allowed for current temperature
#endif
Printer::moveToReal(Printer::lastCmdPos[X_AXIS], Printer::lastCmdPos[Y_AXIS], Printer::lastCmdPos[Z_AXIS],
- (Printer::currentPositionSteps[E_AXIS] + e) * Printer::invAxisStepsPerMM[E_AXIS],feedrate);
+ (Printer::currentPositionSteps[E_AXIS] + e) * Printer::invAxisStepsPerMM[E_AXIS],feedrate,pathOptimize);
Printer::updateCurrentPosition();
if(waitEnd)
Commands::waitUntilEndOfAllMoves();
@@ -142,45 +173,214 @@ void PrintLine::moveRelativeDistanceInStepsReal(int32_t x,int32_t y,int32_t z,in
}
#if !NONLINEAR_SYSTEM
+#if DISTORTION_CORRECTION
+ /* Special version which adds distortion correction to z. Gets called from queueCartesianMove if needed. */
+ void PrintLine::queueCartesianSegmentTo(uint8_t check_endstops, uint8_t pathOptimize) {
+
+ // Correct the bumps
+ Printer::zCorrectionStepsIncluded = Printer::distortion.correct(Printer::destinationSteps[X_AXIS],Printer::destinationSteps[Y_AXIS],Printer::destinationSteps[Z_AXIS]);
+ Printer::destinationSteps[Z_AXIS] += Printer::zCorrectionStepsIncluded;
+#if DEBUG_DISTORTION
+ Com::printF(PSTR("zCorr:"),Printer::zCorrectionStepsIncluded*Printer::invAxisStepsPerMM[Z_AXIS],3);
+ Com::printF(PSTR(" atX:"),Printer::destinationSteps[0]*Printer::invAxisStepsPerMM[X_AXIS]);
+ Com::printFLN(PSTR(" atY:"),Printer::destinationSteps[1]*Printer::invAxisStepsPerMM[Y_AXIS]);
+#endif
+ PrintLine::waitForXFreeLines(1);
+ uint8_t newPath = PrintLine::insertWaitMovesIfNeeded(pathOptimize, 0);
+ PrintLine *p = PrintLine::getNextWriteLine();
+
+ float axisDistanceMM[E_AXIS_ARRAY]; // Axis movement in mm
+ p->flags = (check_endstops ? FLAG_CHECK_ENDSTOPS : 0);
+ #if MIXING_EXTRUDER
+ if(Printer::isAllEMotors()) {
+ p->flags |= FLAG_ALL_E_MOTORS;
+ }
+ #endif
+ p->joinFlags = 0;
+ if(!pathOptimize) p->setEndSpeedFixed(true);
+ p->dir = 0;
+ //Find direction
+ Printer::zCorrectionStepsIncluded = 0;
+ for(uint8_t axis = 0; axis < 4; axis++)
+ {
+ p->delta[axis] = Printer::destinationSteps[axis] - Printer::currentPositionSteps[axis];
+ p->secondSpeed = Printer::fanSpeed;
+ if(axis == E_AXIS)
+ {
+ if(Printer::mode == PRINTER_MODE_FFF)
+ {
+ Printer::extrudeMultiplyError += (static_cast(p->delta[E_AXIS]) * Printer::extrusionFactor);
+ p->delta[E_AXIS] = static_cast(Printer::extrudeMultiplyError);
+ Printer::extrudeMultiplyError -= p->delta[E_AXIS];
+ Printer::filamentPrinted += p->delta[E_AXIS] * Printer::invAxisStepsPerMM[axis];
+ }
+ #if defined(SUPPORT_LASER) && SUPPORT_LASER
+ else if(Printer::mode == PRINTER_MODE_LASER)
+ {
+ p->secondSpeed = ((p->delta[X_AXIS] != 0 || p->delta[Y_AXIS] != 0) && (LaserDriver::laserOn || p->delta[E_AXIS] != 0) ? LaserDriver::intensity : 0);
+ p->delta[E_AXIS] = 0;
+ }
+ #endif
+ }
+ if(p->delta[axis] >= 0)
+ p->setPositiveDirectionForAxis(axis);
+ else
+ p->delta[axis] = -p->delta[axis];
+ axisDistanceMM[axis] = p->delta[axis] * Printer::invAxisStepsPerMM[axis];
+ if(p->delta[axis]) p->setMoveOfAxis(axis);
+ Printer::currentPositionSteps[axis] = Printer::destinationSteps[axis];
+ }
+ if(p->isNoMove())
+ {
+ if(newPath) // need to delete dummy elements, otherwise commands can get locked.
+ PrintLine::resetPathPlanner();
+ return; // No steps included
+ }
+ float xydist2;
+ #if ENABLE_BACKLASH_COMPENSATION
+ if((p->isXYZMove()) && ((p->dir & XYZ_DIRPOS)^(Printer::backlashDir & XYZ_DIRPOS)) & (Printer::backlashDir >> 3)) // We need to compensate backlash, add a move
+ {
+ PrintLine::waitForXFreeLines(2);
+ uint8_t wpos2 = PrintLine::linesWritePos + 1;
+ if(wpos2 >= PRINTLINE_CACHE_SIZE) wpos2 = 0;
+ PrintLine *p2 = &PrintLine::lines[wpos2];
+ memcpy(p2,p,sizeof(PrintLine)); // Move current data to p2
+ uint8_t changed = (p->dir & XYZ_DIRPOS)^(Printer::backlashDir & XYZ_DIRPOS);
+ float back_diff[4]; // Axis movement in mm
+ back_diff[E_AXIS] = 0;
+ back_diff[X_AXIS] = (changed & 1 ? (p->isXPositiveMove() ? Printer::backlashX : -Printer::backlashX) : 0);
+ back_diff[Y_AXIS] = (changed & 2 ? (p->isYPositiveMove() ? Printer::backlashY : -Printer::backlashY) : 0);
+ back_diff[Z_AXIS] = (changed & 4 ? (p->isZPositiveMove() ? Printer::backlashZ : -Printer::backlashZ) : 0);
+ p->dir &= XYZ_DIRPOS; // x,y and z are already correct
+ for(uint8_t i = 0; i < 4; i++)
+ {
+ float f = back_diff[i]*Printer::axisStepsPerMM[i];
+ p->delta[i] = abs((long)f);
+ if(p->delta[i]) p->dir |= XSTEP << i;
+ }
+ //Define variables that are needed for the Bresenham algorithm. Please note that Z is not currently included in the Bresenham algorithm.
+ if(p->delta[Y_AXIS] > p->delta[X_AXIS] && p->delta[Y_AXIS] > p->delta[Z_AXIS]) p->primaryAxis = Y_AXIS;
+ else if (p->delta[X_AXIS] > p->delta[Z_AXIS] ) p->primaryAxis = X_AXIS;
+ else p->primaryAxis = Z_AXIS;
+ p->stepsRemaining = p->delta[p->primaryAxis];
+ //Feedrate calc based on XYZ travel distance
+ xydist2 = back_diff[X_AXIS] * back_diff[X_AXIS] + back_diff[Y_AXIS] * back_diff[Y_AXIS];
+ if(p->isZMove())
+ p->distance = sqrt(xydist2 + back_diff[Z_AXIS] * back_diff[Z_AXIS]);
+ else
+ p->distance = sqrt(xydist2);
+ Printer::backlashDir = (Printer::backlashDir & 56) | (p2->dir & XYZ_DIRPOS);
+ p->calculateMove(back_diff,pathOptimize,p->primaryAxis);
+ p = p2; // use saved instance for the real move
+ }
+ #endif
+
+ //Define variables that are needed for the Bresenham algorithm. Please note that Z is not currently included in the Bresenham algorithm.
+ if(p->delta[Y_AXIS] > p->delta[X_AXIS] && p->delta[Y_AXIS] > p->delta[Z_AXIS] && p->delta[Y_AXIS] > p->delta[E_AXIS]) p->primaryAxis = Y_AXIS;
+ else if (p->delta[X_AXIS] > p->delta[Z_AXIS] && p->delta[X_AXIS] > p->delta[E_AXIS]) p->primaryAxis = X_AXIS;
+ else if (p->delta[Z_AXIS] > p->delta[E_AXIS]) p->primaryAxis = Z_AXIS;
+ else p->primaryAxis = E_AXIS;
+ p->stepsRemaining = p->delta[p->primaryAxis];
+ if(p->isXYZMove())
+ {
+ xydist2 = axisDistanceMM[X_AXIS] * axisDistanceMM[X_AXIS] + axisDistanceMM[Y_AXIS] * axisDistanceMM[Y_AXIS];
+ if(p->isZMove())
+ p->distance = RMath::max((float)sqrt(xydist2 + axisDistanceMM[Z_AXIS] * axisDistanceMM[Z_AXIS]),fabs(axisDistanceMM[E_AXIS]));
+ else
+ p->distance = RMath::max((float)sqrt(xydist2),fabs(axisDistanceMM[E_AXIS]));
+ }
+ else
+ p->distance = fabs(axisDistanceMM[E_AXIS]);
+ p->calculateMove(axisDistanceMM,pathOptimize,p->primaryAxis);
+
+ }
+#endif
/**
Put a move to the current destination coordinates into the movement cache.
If the cache is full, the method will wait, until a place gets free. During
wait communication and temperature control is enabled.
@param check_endstops Read endstop during move.
*/
-void PrintLine::queueCartesianMove(uint8_t check_endstops,uint8_t pathOptimize)
+void PrintLine::queueCartesianMove(uint8_t check_endstops, uint8_t pathOptimize)
{
//Davinci Specific, STOP request
Printer::setMenuMode(MENU_MODE_PRINTING,true);
if (Printer::isMenuModeEx(MENU_MODE_STOP_REQUESTED))return;
+ Printer::constrainDestinationCoords();
Printer::unsetAllSteppersDisabled();
+#if DISTORTION_CORRECTION
+ if(Printer::distortion.isEnabled() && Printer::destinationSteps[Z_AXIS] < Printer::distortion.zMaxSteps() && Printer::isZProbingActive() == false && !Printer::isHoming()) {
+ // we are inside correction height so we split all moves in lines of max. 10 mm and add them
+ // including a z correction
+ int32_t deltas[E_AXIS_ARRAY],start[E_AXIS_ARRAY];
+ for(fast8_t i = 0;i < E_AXIS_ARRAY;i++) {
+ deltas[i] = Printer::destinationSteps[i] - Printer::currentPositionSteps[i];
+ start[i] = Printer::currentPositionSteps[i];
+ }
+ float dx = Printer::invAxisStepsPerMM[X_AXIS] * deltas[X_AXIS];
+ float dy = Printer::invAxisStepsPerMM[Y_AXIS] * deltas[Y_AXIS];
+ float len = dx * dx + dy * dy;
+ if(len < 100) { // no splitting required
+ queueCartesianSegmentTo(check_endstops, pathOptimize);
+ return;
+ }
+ // we need to split longer lines to follow bed curvature
+ len = sqrt(len);
+ int segments = (static_cast(len) + 9) / 10;
+#if DEBUG_DISTORTION
+ Com::printF(PSTR("Split line len:"),len);Com::printFLN(PSTR(" segments:"),segments);
+#endif
+ for(int i = 1; i <= segments; i++) {
+ for(fast8_t j = 0; j < E_AXIS_ARRAY; j++) {
+ Printer::destinationSteps[j] = start[j] + (i * deltas[j]) / segments;
+ }
+ queueCartesianSegmentTo(check_endstops, pathOptimize);
+ }
+ return;
+ }
+#endif
waitForXFreeLines(1);
uint8_t newPath = insertWaitMovesIfNeeded(pathOptimize, 0);
PrintLine *p = getNextWriteLine();
- float axis_diff[E_AXIS_ARRAY]; // Axis movement in mm
- if(check_endstops) p->flags = FLAG_CHECK_ENDSTOPS;
- else p->flags = 0;
+ float axisDistanceMM[E_AXIS_ARRAY]; // Axis movement in mm
+ p->flags = (check_endstops ? FLAG_CHECK_ENDSTOPS : 0);
+#if MIXING_EXTRUDER
+ if(Printer::isAllEMotors()) {
+ p->flags |= FLAG_ALL_E_MOTORS;
+ }
+#endif
p->joinFlags = 0;
if(!pathOptimize) p->setEndSpeedFixed(true);
p->dir = 0;
- Printer::constrainDestinationCoords();
//Find direction
+ Printer::zCorrectionStepsIncluded = 0;
for(uint8_t axis = 0; axis < 4; axis++)
{
p->delta[axis] = Printer::destinationSteps[axis] - Printer::currentPositionSteps[axis];
+ p->secondSpeed = Printer::fanSpeed;
if(axis == E_AXIS)
{
- Printer::extrudeMultiplyError += (static_cast(p->delta[E_AXIS]) * Printer::extrusionFactor);
- p->delta[E_AXIS] = static_cast(Printer::extrudeMultiplyError);
- Printer::extrudeMultiplyError -= p->delta[E_AXIS];
- Printer::filamentPrinted += p->delta[E_AXIS] * Printer::invAxisStepsPerMM[axis];
+ if(Printer::mode == PRINTER_MODE_FFF)
+ {
+ Printer::extrudeMultiplyError += (static_cast(p->delta[E_AXIS]) * Printer::extrusionFactor);
+ p->delta[E_AXIS] = static_cast(Printer::extrudeMultiplyError);
+ Printer::extrudeMultiplyError -= p->delta[E_AXIS];
+ Printer::filamentPrinted += p->delta[E_AXIS] * Printer::invAxisStepsPerMM[axis];
+ }
+#if defined(SUPPORT_LASER) && SUPPORT_LASER
+ else if(Printer::mode == PRINTER_MODE_LASER)
+ {
+ p->secondSpeed = ((p->delta[X_AXIS] != 0 || p->delta[Y_AXIS] != 0) && (LaserDriver::laserOn || p->delta[E_AXIS] != 0) ? LaserDriver::intensity : 0);
+ p->delta[E_AXIS] = 0;
+ }
+#endif
}
if(p->delta[axis] >= 0)
p->setPositiveDirectionForAxis(axis);
else
p->delta[axis] = -p->delta[axis];
- axis_diff[axis] = p->delta[axis] * Printer::invAxisStepsPerMM[axis];
+ axisDistanceMM[axis] = p->delta[axis] * Printer::invAxisStepsPerMM[axis];
if(p->delta[axis]) p->setMoveOfAxis(axis);
Printer::currentPositionSteps[axis] = Printer::destinationSteps[axis];
}
@@ -196,7 +396,7 @@ void PrintLine::queueCartesianMove(uint8_t check_endstops,uint8_t pathOptimize)
{
waitForXFreeLines(2);
uint8_t wpos2 = linesWritePos + 1;
- if(wpos2>=PRINTLINE_CACHE_SIZE) wpos2 = 0;
+ if(wpos2 >= PRINTLINE_CACHE_SIZE) wpos2 = 0;
PrintLine *p2 = &lines[wpos2];
memcpy(p2,p,sizeof(PrintLine)); // Move current data to p2
uint8_t changed = (p->dir & XYZ_DIRPOS)^(Printer::backlashDir & XYZ_DIRPOS);
@@ -210,7 +410,7 @@ void PrintLine::queueCartesianMove(uint8_t check_endstops,uint8_t pathOptimize)
{
float f = back_diff[i]*Printer::axisStepsPerMM[i];
p->delta[i] = abs((long)f);
- if(p->delta[i]) p->dir |= XSTEP<delta[i]) p->dir |= XSTEP << i;
}
//Define variables that are needed for the Bresenham algorithm. Please note that Z is not currently included in the Bresenham algorithm.
if(p->delta[Y_AXIS] > p->delta[X_AXIS] && p->delta[Y_AXIS] > p->delta[Z_AXIS]) p->primaryAxis = Y_AXIS;
@@ -225,7 +425,7 @@ void PrintLine::queueCartesianMove(uint8_t check_endstops,uint8_t pathOptimize)
p->distance = sqrt(xydist2);
// 56 seems to be xstep|ystep|e_posdir which just seems odd
Printer::backlashDir = (Printer::backlashDir & 56) | (p2->dir & XYZ_DIRPOS);
- p->calculateMove(back_diff,pathOptimize);
+ p->calculateMove(back_diff,pathOptimize,p->primaryAxis);
p = p2; // use saved instance for the real move
}
#endif
@@ -238,140 +438,162 @@ void PrintLine::queueCartesianMove(uint8_t check_endstops,uint8_t pathOptimize)
p->stepsRemaining = p->delta[p->primaryAxis];
if(p->isXYZMove())
{
- xydist2 = axis_diff[X_AXIS] * axis_diff[X_AXIS] + axis_diff[Y_AXIS] * axis_diff[Y_AXIS];
+ xydist2 = axisDistanceMM[X_AXIS] * axisDistanceMM[X_AXIS] + axisDistanceMM[Y_AXIS] * axisDistanceMM[Y_AXIS];
if(p->isZMove())
- p->distance = RMath::max((float)sqrt(xydist2 + axis_diff[Z_AXIS] * axis_diff[Z_AXIS]),fabs(axis_diff[E_AXIS]));
+ p->distance = RMath::max((float)sqrt(xydist2 + axisDistanceMM[Z_AXIS] * axisDistanceMM[Z_AXIS]),fabs(axisDistanceMM[E_AXIS]));
else
- p->distance = RMath::max((float)sqrt(xydist2),fabs(axis_diff[E_AXIS]));
+ p->distance = RMath::max((float)sqrt(xydist2),fabs(axisDistanceMM[E_AXIS]));
}
else
- p->distance = fabs(axis_diff[E_AXIS]);
- p->calculateMove(axis_diff,pathOptimize);
+ p->distance = fabs(axisDistanceMM[E_AXIS]);
+ p->calculateMove(axisDistanceMM,pathOptimize,p->primaryAxis);
}
#endif
-void PrintLine::calculateMove(float axis_diff[], uint8_t pathOptimize)
+void PrintLine::calculateMove(float axisDistanceMM[], uint8_t pathOptimize,fast8_t drivingAxis)
{
#if NONLINEAR_SYSTEM
long axisInterval[VIRTUAL_AXIS_ARRAY]; // shortest interval possible for that axis
#else
long axisInterval[E_AXIS_ARRAY];
#endif
- float timeForMove = (float)(F_CPU)*distance / (isXOrYMove() ? RMath::max(Printer::minimumSpeed, Printer::feedrate) : Printer::feedrate); // time is in ticks
- bool critical = Printer::isZProbingActive();
+ //float timeForMove = (float)(F_CPU)*distance / (isXOrYMove() ? RMath::max(Printer::minimumSpeed, Printer::feedrate) : Printer::feedrate); // time is in ticks
+ float timeForMove = (float)(F_CPU)*distance / Printer::feedrate; // time is in ticks
+ //bool critical = Printer::isZProbingActive();
if(linesCount < MOVE_CACHE_LOW && timeForMove < LOW_TICKS_PER_MOVE) // Limit speed to keep cache full.
{
- //OUT_P_I("L:",lines_count);
+ //Com::printF(PSTR("L:"),(int)linesCount);
+ //Com::printF(PSTR(" Old "),timeForMove);
timeForMove += (3 * (LOW_TICKS_PER_MOVE - timeForMove)) / (linesCount + 1); // Increase time if queue gets empty. Add more time if queue gets smaller.
- //OUT_P_F_LN("Slow ",time_for_move);
- critical = true;
+ //Com::printFLN(PSTR("Slow "),timeForMove);
+ //critical = true;
}
timeInTicks = timeForMove;
UI_MEDIUM; // do check encoder
- // Compute the solwest allowed interval (ticks/step), so maximum feedrate is not violated
- long limitInterval = timeForMove / stepsRemaining; // until not violated by other constraints it is your target speed
+ // Compute the slowest allowed interval (ticks/step), so maximum feedrate is not violated
+ int32_t limitInterval0;
+ int32_t limitInterval = limitInterval0 = timeForMove / stepsRemaining; // until not violated by other constraints it is your target speed
+ float toTicks = static_cast(F_CPU) / stepsRemaining;
if(isXMove())
{
- axisInterval[X_AXIS] = fabs(axis_diff[X_AXIS]) * F_CPU / (Printer::maxFeedrate[X_AXIS] * stepsRemaining); // mm*ticks/s/(mm/s*steps) = ticks/step
-#if !NONLINEAR_SYSTEM
+ axisInterval[X_AXIS] = axisDistanceMM[X_AXIS] * toTicks / (Printer::maxFeedrate[X_AXIS]); // mm*ticks/s/(mm/s*steps) = ticks/step
+#if !NONLINEAR_SYSTEM || defined(FAST_COREXYZ)
limitInterval = RMath::max(axisInterval[X_AXIS], limitInterval);
#endif
}
else axisInterval[X_AXIS] = 0;
if(isYMove())
{
- axisInterval[Y_AXIS] = fabs(axis_diff[Y_AXIS]) * F_CPU / (Printer::maxFeedrate[Y_AXIS] * stepsRemaining);
-#if !NONLINEAR_SYSTEM
+ axisInterval[Y_AXIS] = axisDistanceMM[Y_AXIS] * toTicks / Printer::maxFeedrate[Y_AXIS];
+#if !NONLINEAR_SYSTEM || defined(FAST_COREXYZ)
limitInterval = RMath::max(axisInterval[Y_AXIS], limitInterval);
#endif
}
else axisInterval[Y_AXIS] = 0;
if(isZMove()) // normally no move in z direction
{
- axisInterval[Z_AXIS] = fabs(axis_diff[Z_AXIS]) * (float)F_CPU / (float)(Printer::maxFeedrate[Z_AXIS] * stepsRemaining); // must prevent overflow!
-#if !NONLINEAR_SYSTEM
+ axisInterval[Z_AXIS] = axisDistanceMM[Z_AXIS] * toTicks / Printer::maxFeedrate[Z_AXIS]; // must prevent overflow!
+#if !NONLINEAR_SYSTEM || defined(FAST_COREXYZ)
limitInterval = RMath::max(axisInterval[Z_AXIS], limitInterval);
#endif
}
else axisInterval[Z_AXIS] = 0;
if(isEMove())
{
- axisInterval[E_AXIS] = fabs(axis_diff[E_AXIS]) * F_CPU / (Printer::maxFeedrate[E_AXIS] * stepsRemaining);
-#if !NONLINEAR_SYSTEM
+ axisInterval[E_AXIS] = axisDistanceMM[E_AXIS] * toTicks / Printer::maxFeedrate[E_AXIS];
limitInterval = RMath::max(axisInterval[E_AXIS], limitInterval);
-#endif
}
else axisInterval[E_AXIS] = 0;
-#if NONLINEAR_SYSTEM
- if(axis_diff[VIRTUAL_AXIS] >= 0)
- axisInterval[VIRTUAL_AXIS] = fabs(axis_diff[VIRTUAL_AXIS]) * F_CPU / (Printer::maxFeedrate[Z_AXIS] * stepsRemaining);
- else
- axisInterval[VIRTUAL_AXIS] = fabs(axis_diff[VIRTUAL_AXIS]) * F_CPU / (Printer::maxFeedrate[E_AXIS] * stepsRemaining);
- limitInterval = RMath::max(axisInterval[VIRTUAL_AXIS], limitInterval);
+#if DRIVE_SYSTEM == DELTA
+ if(axisDistanceMM[VIRTUAL_AXIS] >= 0) {// only for deltas all speeds in all directions have same limit
+ axisInterval[VIRTUAL_AXIS] = axisDistanceMM[VIRTUAL_AXIS] * toTicks / (Printer::maxFeedrate[Z_AXIS]);
+ limitInterval = RMath::max(axisInterval[VIRTUAL_AXIS], limitInterval);
+ }
#endif
-
- fullInterval = limitInterval = limitInterval>LIMIT_INTERVAL ? limitInterval : LIMIT_INTERVAL; // This is our target speed
- // new time at full speed = limitInterval*p->stepsRemaining [ticks]
- timeForMove = (float)limitInterval * (float)stepsRemaining; // for large z-distance this overflows with long computation
- float inv_time_s = (float)F_CPU / timeForMove;
+ fullInterval = limitInterval = limitInterval > LIMIT_INTERVAL ? limitInterval : LIMIT_INTERVAL; // This is our target speed
+ if(limitInterval != limitInterval0) {
+ // new time at full speed = limitInterval*p->stepsRemaining [ticks]
+ timeForMove = (float)limitInterval * (float)stepsRemaining; // for large z-distance this overflows with long computation
+ }
+ float inverseTimeS = (float)F_CPU / timeForMove;
if(isXMove())
{
axisInterval[X_AXIS] = timeForMove / delta[X_AXIS];
- speedX = axis_diff[X_AXIS] * inv_time_s;
+ speedX = axisDistanceMM[X_AXIS] * inverseTimeS;
if(isXNegativeMove()) speedX = -speedX;
}
else speedX = 0;
if(isYMove())
{
axisInterval[Y_AXIS] = timeForMove / delta[Y_AXIS];
- speedY = axis_diff[Y_AXIS] * inv_time_s;
+ speedY = axisDistanceMM[Y_AXIS] * inverseTimeS;
if(isYNegativeMove()) speedY = -speedY;
}
else speedY = 0;
if(isZMove())
{
axisInterval[Z_AXIS] = timeForMove / delta[Z_AXIS];
- speedZ = axis_diff[Z_AXIS] * inv_time_s;
+ speedZ = axisDistanceMM[Z_AXIS] * inverseTimeS;
if(isZNegativeMove()) speedZ = -speedZ;
}
else speedZ = 0;
if(isEMove())
{
axisInterval[E_AXIS] = timeForMove / delta[E_AXIS];
- speedE = axis_diff[E_AXIS] * inv_time_s;
+ speedE = axisDistanceMM[E_AXIS] * inverseTimeS;
if(isENegativeMove()) speedE = -speedE;
}
#if NONLINEAR_SYSTEM
axisInterval[VIRTUAL_AXIS] = limitInterval; //timeForMove/stepsRemaining;
#endif
- fullSpeed = distance * inv_time_s;
+ fullSpeed = distance * inverseTimeS;
//long interval = axis_interval[primary_axis]; // time for every step in ticks with full speed
//If acceleration is enabled, do some Bresenham calculations depending on which axis will lead it.
#if RAMP_ACCELERATION
// slowest time to accelerate from v0 to limitInterval determines used acceleration
// t = (v_end-v_start)/a
- float slowest_axis_plateau_time_repro = 1e15; // repro to reduce division Unit: 1/s
- unsigned long *accel = (isEPositiveMove() ? Printer::maxPrintAccelerationStepsPerSquareSecond : Printer::maxTravelAccelerationStepsPerSquareSecond);
-
- for(uint8_t i = 0; i < 4 ; i++)
+ float slowestAxisPlateauTimeRepro = 1e15; // 1/time to reduce division Unit: 1/s
+ uint32_t *accel = (isEPositiveMove() ? Printer::maxPrintAccelerationStepsPerSquareSecond : Printer::maxTravelAccelerationStepsPerSquareSecond);
+#if defined(INTERPOLATE_ACCELERATION_WITH_Z) && INTERPOLATE_ACCELERATION_WITH_Z != 0
+ uint32_t newAccel[4];
+ float accelFac = (100.0 + (EEPROM::accelarationFactorTop() - 100.0) * Printer::currentPosition[Z_AXIS] / Printer::zLength)*0.01;
+#if INTERPOLATE_ACCELERATION_WITH_Z == 1 || INTERPOLATE_ACCELERATION_WITH_Z == 3
+ newAccel[X_AXIS] = static_cast(accel[X_AXIS] * accelFac);
+ newAccel[Y_AXIS] = static_cast(accel[Y_AXIS] * accelFac);
+#else
+ newAccel[X_AXIS] = accel[X_AXIS];
+ newAccel[Y_AXIS] = accel[Y_AXIS];
+#endif
+#if INTERPOLATE_ACCELERATION_WITH_Z == 2 || INTERPOLATE_ACCELERATION_WITH_Z == 3
+ newAccel[Z_AXIS] = static_cast(accel[Z_AXIS] * accelFac);
+#else
+ newAccel[Z_AXIS] = accel[Z_AXIS];
+#endif
+ newAccel[E_AXIS] = accel[E_AXIS];
+ accel = newAccel;
+#endif // INTERPOLATE_ACCELERATION_WITH_Z
+ for(fast8_t i = 0; i < E_AXIS_ARRAY ; i++)
{
if(isMoveOfAxis(i))
// v = a * t => t = v/a = F_CPU/(c*a) => 1/t = c*a/F_CPU
- slowest_axis_plateau_time_repro = RMath::min(slowest_axis_plateau_time_repro, (float)axisInterval[i] * (float)accel[i]); // steps/s^2 * step/tick Ticks/s^2
+ slowestAxisPlateauTimeRepro = RMath::min(slowestAxisPlateauTimeRepro, (float)axisInterval[i] * (float)accel[i]); // steps/s^2 * step/tick Ticks/s^2
}
+
// Errors for delta move are initialized in timer (except extruder)
#if !NONLINEAR_SYSTEM
- error[X_AXIS] = error[Y_AXIS] = error[Z_AXIS] = delta[primaryAxis] >> 1;
+ error[X_AXIS] = error[Y_AXIS] = error[Z_AXIS] = error[E_AXIS] = delta[primaryAxis] >> 1;
#endif
#if NONLINEAR_SYSTEM
error[E_AXIS] = stepsRemaining >> 1;
#endif
invFullSpeed = 1.0 / fullSpeed;
- accelerationPrim = slowest_axis_plateau_time_repro / axisInterval[primaryAxis]; // a = v/t = F_CPU/(c*t): Steps/s^2
+ accelerationPrim = slowestAxisPlateauTimeRepro / axisInterval[primaryAxis]; // a = v/t = F_CPU/(c*t): Steps/s^2
//Now we can calculate the new primary axis acceleration, so that the slowest axis max acceleration is not violated
fAcceleration = 262144.0 * (float)accelerationPrim / F_CPU; // will overflow without float!
- accelerationDistance2 = 2.0 * distance * slowest_axis_plateau_time_repro * fullSpeed/((float)F_CPU); // mm^2/s^2
- startSpeed = endSpeed = minSpeed = safeSpeed();
+ accelerationDistance2 = 2.0 * distance * slowestAxisPlateauTimeRepro * fullSpeed/((float)F_CPU); // mm^2/s^2
+ startSpeed = endSpeed = minSpeed = safeSpeed(drivingAxis);
+ if(startSpeed > Printer::feedrate)
+ startSpeed = endSpeed = minSpeed = Printer::feedrate;
// Can accelerate to full speed within the line
if (startSpeed * startSpeed + accelerationDistance2 >= fullSpeed * fullSpeed)
setNominalMove();
@@ -423,19 +645,6 @@ void PrintLine::calculateMove(float axis_diff[], uint8_t pathOptimize)
#endif
#endif
- // Correct integers for fixed point math used in bresenham_step
- if(fullInterval < MAX_HALFSTEP_INTERVAL || critical)
- halfStep = 4;
- else
- {
- halfStep = 1;
-#if NONLINEAR_SYSTEM
- // Error 0-2 are used for the towers and set up in the timer
- error[E_AXIS] = stepsRemaining;
-#else
- error[X_AXIS] = error[Y_AXIS] = error[Z_AXIS] = error[E_AXIS] = delta[primaryAxis];
-#endif
- }
#ifdef DEBUG_STEPCOUNT
// Set in delta move calculation
#if !NONLINEAR_SYSTEM
@@ -464,23 +673,30 @@ This is the path planner.
It goes from the last entry and tries to increase the end speed of previous moves in a fashion that the maximum jerk
is never exceeded. If a segment with reached maximum speed is met, the planner stops. Everything left from this
is already optimal from previous updates.
-The first 2 entries in the queue are not checked. The first is the one that is already in print and the following will likely become active.
+The first 2 entries in the queue are not checked. The first is the one that is already in print and the following will likely to become active.
The method is called before lines_count is increased!
*/
void PrintLine::updateTrapezoids()
{
- uint8_t first = linesWritePos;
+ ufast8_t first = linesWritePos;
PrintLine *firstLine;
PrintLine *act = &lines[linesWritePos];
InterruptProtectedBlock noInts;
- uint8_t maxfirst = linesPos; // first non fixed segment
+
+ // First we find out how far back we could go with optimization.
+
+ ufast8_t maxfirst = linesPos; // first non fixed segment we might change
if(maxfirst != linesWritePos)
nextPlannerIndex(maxfirst); // don't touch the line printing
// Now ignore enough segments to gain enough time for path planning
millis_t timeleft = 0;
// Skip as many stored moves as needed to gain enough time for computation
- millis_t minTime = 4500L * RMath::min(PRINTLINE_CACHE_SIZE,10);
+#if PRINTLINE_CACHE_SIZE < 10
+#define minTime 4500L * PRINTLINE_CACHE_SIZE
+#else
+#define minTime 45000L
+#endif
while(timeleft < minTime && maxfirst != linesWritePos)
{
timeleft += lines[maxfirst].timeInTicks;
@@ -491,9 +707,12 @@ void PrintLine::updateTrapezoids()
previousPlannerIndex(first);
if(first != linesWritePos && lines[first].isEndSpeedFixed())
nextPlannerIndex(first);
- if(first == linesWritePos) // Nothing to plan
+ // now first points to last segment before the end speed is fixed
+ // so start speed is also fixed.
+
+ if(first == linesWritePos) // Nothing to plan, only new element present
{
- act->block();
+ act->block(); // Prevent stepper interrupt from using this
noInts.unprotect();
act->setStartSpeedFixed(true);
act->updateStepsParameter();
@@ -507,55 +726,122 @@ void PrintLine::updateTrapezoids()
firstLine = &lines[first];
firstLine->block(); // don't let printer touch this or following segments during update
noInts.unprotect();
- uint8_t previousIndex = linesWritePos;
+ ufast8_t previousIndex = linesWritePos;
previousPlannerIndex(previousIndex);
- PrintLine *previous = &lines[previousIndex];
-#if DRIVE_SYSTEM!=DELTA
+ PrintLine *previous = &lines[previousIndex]; // segment before the one we are inserting
+#if DRIVE_SYSTEM != DELTA
// filters z-move<->not z-move
- if((previous->primaryAxis == Z_AXIS && act->primaryAxis != Z_AXIS) || (previous->primaryAxis != Z_AXIS && act->primaryAxis == Z_AXIS))
+/* if((previous->primaryAxis == Z_AXIS && act->primaryAxis != Z_AXIS) || (previous->primaryAxis != Z_AXIS && act->primaryAxis == Z_AXIS))
{
previous->setEndSpeedFixed(true);
act->setStartSpeedFixed(true);
act->updateStepsParameter();
firstLine->unblock();
return;
- }
+ }*/
#endif // DRIVE_SYSTEM
- computeMaxJunctionSpeed(previous,act); // Set maximum junction speed if we have a real move before
if(previous->isEOnlyMove() != act->isEOnlyMove())
{
+ previous->maxJunctionSpeed = act->startSpeed;
previous->setEndSpeedFixed(true);
act->setStartSpeedFixed(true);
act->updateStepsParameter();
firstLine->unblock();
return;
}
+ else
+ {
+ computeMaxJunctionSpeed(previous, act); // Set maximum junction speed if we have a real move before
+ }
+ // Increase speed if possible neglecting current speed
backwardPlanner(linesWritePos,first);
// Reduce speed to reachable speeds
forwardPlanner(first);
+#ifdef DEBUG_PLANNER
+ Com::printF(PSTR("Planner: "),(int)linesCount);
+ previousPlannerIndex(first);
+ Com::printF(PSTR(" F "),lines[first].startSpeed,1);
+ Com::printF(PSTR(" - "),lines[first].endSpeed,1);
+ Com::printF(PSTR("("),lines[first].maxJunctionSpeed,1);
+ Com::printF(PSTR(","),(int)lines[first].joinFlags);
+ nextPlannerIndex(first);
+#endif
// Update precomputed data
do
{
lines[first].updateStepsParameter();
- noInts.protect();
- lines[first].unblock(); // Flying block to release next used segment as early as possible
+#ifdef DEBUG_PLANNER
+ Com::printF(PSTR(" / "),lines[first].startSpeed,1);
+ Com::printF(PSTR(" - "),lines[first].endSpeed,1);
+ Com::printF(PSTR("("),lines[first].maxJunctionSpeed,1);
+ Com::printF(PSTR(","),(int)lines[first].joinFlags);
+#ifdef DEBUG_QUEUE_MOVE
+ Com::println();
+#endif
+#endif
+ //noInts.protect();
+ lines[first].unblock(); // start with first block to release next used segment as early as possible
nextPlannerIndex(first);
lines[first].block();
- noInts.unprotect();
+ //noInts.unprotect();
}
while(first != linesWritePos);
act->updateStepsParameter();
act->unblock();
+#ifdef DEBUG_PLANNER
+ Com::printF(PSTR(" / "),lines[first].startSpeed,1);
+ Com::printF(PSTR(" - "),lines[first].endSpeed,1);
+ Com::printF(PSTR("("),lines[first].maxJunctionSpeed,1);
+ Com::printFLN(PSTR(","),(int)lines[first].joinFlags);
+#endif
}
+/* Computes the maximum junction speed of the newly added segment under
+optimal conditions. There is no guarantee that the previous move will be able to reach the
+speed at all, but if it could exceed it will never exceed this theoretical limit.
+
+if you define ALTERNATIVE_JERK the new jerk computations are used. These
+use the cosine of the angle and the maximum speed
+Jerk = (1-cos(alpha))*min(v1,v2)
+This sets jerk to 0 on zero angle change.
+
+ Old New
+0°: 0 0
+30°: 51,8 13.4
+45°: 76.53 29.3
+90°: 141 100
+180°: 200 200
+
+
+Speed from 100 to 200
+ Old New(min) New(max)
+0°: 100 0 0
+30°: 123,9 13.4 26.8
+45°: 147.3 29.3 58.6
+90°: 223 100 200
+180°: 300 200 400
+
+*/
inline void PrintLine::computeMaxJunctionSpeed(PrintLine *previous, PrintLine *current)
{
+#if NONLINEAR_SYSTEM
+ /* if (previous->moveID == current->moveID) // Avoid computing junction speed for split nonlinear lines
+ {
+ if(previous->fullSpeed > current->fullSpeed)
+ previous->maxJunctionSpeed = current->fullSpeed;
+ else
+ previous->maxJunctionSpeed = previous->fullSpeed;
+ return;
+ }*/
+#endif
#if USE_ADVANCE
if(Printer::isAdvanceActivated())
{
- if(previous->isEMove() != current->isEMove() && (previous->isXOrYMove() || current->isXOrYMove()))
+ // if we start/stop extrusion we need to do so with lowest possible end speed
+ // or advance would leave a drolling extruder and can not adjust fast enough.
+ if(previous->isEMove() != current->isEMove())
{
previous->setEndSpeedFixed(true);
current->setStartSpeedFixed(true);
@@ -566,28 +852,40 @@ inline void PrintLine::computeMaxJunctionSpeed(PrintLine *previous, PrintLine *c
}
}
#endif // USE_ADVANCE
-#if NONLINEAR_SYSTEM
- if (previous->moveID == current->moveID) // Avoid computing junction speed for split delta lines
- {
- if(previous->fullSpeed > current->fullSpeed)
- previous->maxJunctionSpeed = current->fullSpeed;
- else
- previous->maxJunctionSpeed = previous->fullSpeed;
- return;
- }
-#endif
+ // if we are here we have to identical move types
+ // either pure extrusion -> pure extrusion or
+ // move -> move (with or without extrusion)
// First we compute the normalized jerk for speed 1
+ float factor = 1.0;
+ float lengthFactor = 1.0;
+#ifdef REDUCE_ON_SMALL_SEGMENTS
+ if(previous->distance < MAX_JERK_DISTANCE)
+ lengthFactor = static_cast(MAX_JERK_DISTANCE * MAX_JERK_DISTANCE) / (previous->distance * previous->distance);
+#endif
+ float maxJoinSpeed = RMath::min(current->fullSpeed,previous->fullSpeed);
+#if (DRIVE_SYSTEM == DELTA) // No point computing Z Jerk separately for delta moves
+#ifdef ALTERNATIVE_JERK
+ float jerk = maxJoinSpeed * lengthFactor * (1.0 - (current->speedX * previous->speedX + current->speedY * previous->speedY + current->speedZ * previous->speedZ) / (current->fullSpeed * previous->fullSpeed));
+#else
float dx = current->speedX - previous->speedX;
float dy = current->speedY - previous->speedY;
- float factor = 1;
-#if (DRIVE_SYSTEM == DELTA) // No point computing Z Jerk separately for delta moves
float dz = current->speedZ - previous->speedZ;
- float jerk = sqrt(dx * dx + dy * dy + dz * dz);
+ float jerk = sqrt(dx * dx + dy * dy + dz * dz) * lengthFactor;
+#endif // ALTERNATIVE_JERK
+#else // DELTA
+#ifdef ALTERNATIVE_JERK
+ float jerk = maxJoinSpeed * lengthFactor * (1.0 - (current->speedX * previous->speedX + current->speedY * previous->speedY + current->speedZ * previous->speedZ) / (current->fullSpeed * previous->fullSpeed));
#else
- float jerk = sqrt(dx * dx + dy * dy);
-#endif
- if(jerk > Printer::maxJerk)
- factor = Printer::maxJerk / jerk;
+ float dx = current->speedX - previous->speedX;
+ float dy = current->speedY - previous->speedY;
+ float jerk = sqrt(dx * dx + dy * dy) * lengthFactor;
+#endif // ALTERNATIVE_JERK
+#endif // DELTA
+ if(jerk > Printer::maxJerk) {
+ factor = Printer::maxJerk / jerk; // always < 1.0!
+ if(factor * maxJoinSpeed * 2.0 < Printer::maxJerk)
+ factor = Printer::maxJerk / (2.0 * maxJoinSpeed);
+ }
#if DRIVE_SYSTEM != DELTA
if((previous->dir | current->dir) & ZSTEP)
{
@@ -599,19 +897,20 @@ inline void PrintLine::computeMaxJunctionSpeed(PrintLine *previous, PrintLine *c
float eJerk = fabs(current->speedE - previous->speedE);
if(eJerk > Extruder::current->maxStartFeedrate)
factor = RMath::min(factor, Extruder::current->maxStartFeedrate / eJerk);
- previous->maxJunctionSpeed = RMath::min(previous->fullSpeed * factor, current->fullSpeed);
+
+ previous->maxJunctionSpeed = maxJoinSpeed * factor; // set speed limit
#ifdef DEBUG_QUEUE_MOVE
if(Printer::debugEcho())
{
- Com::printF(PSTR("ID:"),(int)previous);
- Com::printFLN(PSTR(" MJ:"),previous->maxJunctionSpeed);
+ Com::printF(PSTR("ID:"), (int)previous);
+ Com::printFLN(PSTR(" MJ:"), previous->maxJunctionSpeed);
}
#endif // DEBUG_QUEUE_MOVE
}
/** Update parameter used by updateTrapezoids
-Computes the acceleration/decelleration steps and advanced parameter associated.
+Computes the acceleration/deceleration steps and advanced parameter associated.
*/
void PrintLine::updateStepsParameter()
{
@@ -620,6 +919,7 @@ void PrintLine::updateStepsParameter()
float endFactor = endSpeed * invFullSpeed;
vStart = vMax * startFactor; //starting speed
vEnd = vMax * endFactor;
+
#if CPU_ARCH == ARCH_AVR
uint32_t vmax2 = HAL::U16SquaredToU32(vMax);
accelSteps = ((vmax2 - HAL::U16SquaredToU32(vStart)) / (accelerationPrim << 1)) + 1; // Always add 1 for missing precision
@@ -627,7 +927,7 @@ void PrintLine::updateStepsParameter()
#else
uint64_t vmax2 = static_cast(vMax) * static_cast(vMax);
accelSteps = ((vmax2 - static_cast(vStart) * static_cast(vStart)) / (accelerationPrim << 1)) + 1; // Always add 1 for missing precision
- decelSteps = ((vmax2 - static_cast(vEnd) * static_cast(vEnd)) /(accelerationPrim << 1)) + 1;
+ decelSteps = ((vmax2 - static_cast(vEnd) * static_cast(vEnd)) / (accelerationPrim << 1)) + 1;
#endif
#if USE_ADVANCE
@@ -654,8 +954,8 @@ void PrintLine::updateStepsParameter()
Com::printFLN(Com::tSlash,(long)stepsRemaining);
Com::printF(Com::tDBGStartEndSpeed,startSpeed,1);
Com::printFLN(Com::tSlash,endSpeed,1);
- Com::printFLN(Com::tDBGFlags,flags);
- Com::printFLN(Com::tDBGJoinFlags,joinFlags);
+ Com::printFLN(Com::tDBGFlags,(uint32_t)flags);
+ Com::printFLN(Com::tDBGJoinFlags,(uint32_t)joinFlags);
}
#endif
}
@@ -667,7 +967,7 @@ The backwards planner traverses the moves from last to first looking at decelera
start = last line inserted
last = last element until we check
*/
-inline void PrintLine::backwardPlanner(uint8_t start,uint8_t last)
+inline void PrintLine::backwardPlanner(ufast8_t start,ufast8_t last)
{
PrintLine *act = &lines[start], *previous;
float lastJunctionSpeed = act->endSpeed; // Start always with safe speed
@@ -677,14 +977,15 @@ inline void PrintLine::backwardPlanner(uint8_t start,uint8_t last)
{
previousPlannerIndex(start);
previous = &lines[start];
- // Avoid speed calc once crusing in split delta move
+ previous->block();
+ // Avoid speed calculation once cruising in split delta move
#if NONLINEAR_SYSTEM
- if (previous->moveID == act->moveID && lastJunctionSpeed == previous->maxJunctionSpeed)
+ /*if (previous->moveID == act->moveID && lastJunctionSpeed == previous->maxJunctionSpeed)
{
act->startSpeed = RMath::max(act->minSpeed, previous->endSpeed = lastJunctionSpeed);
previous->invalidateParameter();
act->invalidateParameter();
- }
+ }*/
#endif
/* if(prev->isEndSpeedFixed()) // Nothing to update from here on, happens when path optimize disabled
@@ -693,7 +994,7 @@ inline void PrintLine::backwardPlanner(uint8_t start,uint8_t last)
return;
}*/
- // Avoid speed calcs if we know we can accelerate within the line
+ // Avoid speed calculations if we know we can accelerate within the line
lastJunctionSpeed = (act->isNominalMove() ? act->fullSpeed : sqrt(lastJunctionSpeed * lastJunctionSpeed + act->accelerationDistance2)); // acceleration is acceleration*distance*2! What can be reached if we try?
// If that speed is more that the maximum junction speed allowed then ...
if(lastJunctionSpeed >= previous->maxJunctionSpeed) // Limit is reached
@@ -702,21 +1003,21 @@ inline void PrintLine::backwardPlanner(uint8_t start,uint8_t last)
if(previous->endSpeed != previous->maxJunctionSpeed)
{
previous->invalidateParameter(); // Needs recomputation
- previous->endSpeed = RMath::max(previous->minSpeed,previous->maxJunctionSpeed); // possibly unneeded???
+ previous->endSpeed = RMath::max(previous->minSpeed, previous->maxJunctionSpeed); // possibly unneeded???
}
// If actual line start speed has not been updated to maximum speed then do it now
if(act->startSpeed != previous->maxJunctionSpeed)
{
- act->startSpeed = RMath::max(act->minSpeed,previous->maxJunctionSpeed); // possibly unneeded???
+ act->startSpeed = RMath::max(act->minSpeed, previous->maxJunctionSpeed); // possibly unneeded???
act->invalidateParameter();
}
lastJunctionSpeed = previous->endSpeed;
}
else
{
- // Block prev end and act start as calculated speed and recalculate plateau speeds (which could move the speed higher again)
- act->startSpeed = RMath::max(act->minSpeed,lastJunctionSpeed);
- lastJunctionSpeed = previous->endSpeed = RMath::max(lastJunctionSpeed,previous->minSpeed);
+ // Block previous end and act start as calculated speed and recalculate plateau speeds (which could move the speed higher again)
+ act->startSpeed = RMath::max(act->minSpeed, lastJunctionSpeed);
+ lastJunctionSpeed = previous->endSpeed = RMath::max(lastJunctionSpeed, previous->minSpeed);
previous->invalidateParameter();
act->invalidateParameter();
}
@@ -724,7 +1025,7 @@ inline void PrintLine::backwardPlanner(uint8_t start,uint8_t last)
} // while loop
}
-void PrintLine::forwardPlanner(uint8_t first)
+void PrintLine::forwardPlanner(ufast8_t first)
{
PrintLine *act;
PrintLine *next = &lines[first];
@@ -740,18 +1041,18 @@ void PrintLine::forwardPlanner(uint8_t first)
leftSpeed = act->endSpeed;
continue; // Nothing to do here
}*/
- // Avoid speed calc once crusing in split delta move
+ // Avoid speed calculate once cruising in split delta move
#if NONLINEAR_SYSTEM
- if (act->moveID == next->moveID && act->endSpeed == act->maxJunctionSpeed)
+/* if (act->moveID == next->moveID && act->endSpeed == act->maxJunctionSpeed)
{
act->startSpeed = leftSpeed;
leftSpeed = act->endSpeed;
act->setEndSpeedFixed(true);
next->setStartSpeedFixed(true);
continue;
- }
+ }*/
#endif
- // Avoid speed calcs if we know we can accelerate within the line.
+ // Avoid speed calculates if we know we can accelerate within the line.
vmaxRight = (act->isNominalMove() ? act->fullSpeed : sqrt(leftSpeed * leftSpeed + act->accelerationDistance2));
if(vmaxRight > act->endSpeed) // Could be higher next run?
{
@@ -761,7 +1062,7 @@ void PrintLine::forwardPlanner(uint8_t first)
act->endSpeed = sqrt(leftSpeed * leftSpeed + act->accelerationDistance2);
}
act->startSpeed = leftSpeed;
- next->startSpeed = leftSpeed = RMath::max(RMath::min(act->endSpeed,act->maxJunctionSpeed),next->minSpeed);
+ next->startSpeed = leftSpeed = RMath::max(RMath::min(act->endSpeed, act->maxJunctionSpeed), next->minSpeed);
if(act->endSpeed == act->maxJunctionSpeed) // Full speed reached, don't compute again!
{
act->setEndSpeedFixed(true);
@@ -780,42 +1081,47 @@ void PrintLine::forwardPlanner(uint8_t first)
}
act->startSpeed = leftSpeed;
act->endSpeed = RMath::max(act->minSpeed,vmaxRight);
- next->startSpeed = leftSpeed = RMath::max(RMath::min(act->endSpeed,act->maxJunctionSpeed),next->minSpeed);
+ next->startSpeed = leftSpeed = RMath::max(RMath::min(act->endSpeed, act->maxJunctionSpeed), next->minSpeed);
next->setStartSpeedFixed(true);
}
} // While
- next->startSpeed = RMath::max(next->minSpeed,leftSpeed); // This is the new segment, which is updated anyway, no extra flag needed.
+ next->startSpeed = RMath::max(next->minSpeed, leftSpeed); // This is the new segment, which is updated anyway, no extra flag needed.
}
-inline float PrintLine::safeSpeed()
+inline float PrintLine::safeSpeed(fast8_t drivingAxis)
{
float safe(Printer::maxJerk * 0.5);
#if DRIVE_SYSTEM != DELTA
if(isZMove())
{
- if(primaryAxis == Z_AXIS)
+ float mz = Printer::maxZJerk * 0.5;
+ if(isXOrYMove())
{
- safe = Printer::maxZJerk*0.5*fullSpeed/fabs(speedZ);
+ if(fabs(speedZ) > mz)
+ safe = RMath::min(safe,mz * fullSpeed / fabs(speedZ));
+ }
+ else
+ {
+ safe = mz;
}
- else if(fabs(speedZ) > Printer::maxZJerk * 0.5)
- safe = RMath::min(safe,Printer::maxZJerk * 0.5 * fullSpeed / fabs(speedZ));
}
#endif
if(isEMove())
{
if(isXYZMove())
- safe = RMath::min(safe,0.5*Extruder::current->maxStartFeedrate*fullSpeed/fabs(speedE));
+ safe = RMath::min(safe, 0.5 * Extruder::current->maxStartFeedrate * fullSpeed / fabs(speedE));
else
- safe = 0.5*Extruder::current->maxStartFeedrate; // This is a retraction move
+ safe = 0.5 * Extruder::current->maxStartFeedrate; // This is a retraction move
}
- if(DRIVE_SYSTEM == DELTA || primaryAxis == X_AXIS || primaryAxis == Y_AXIS) // enforce minimum speed for numerical stability of explicit speed integration
- safe = RMath::max(Printer::minimumSpeed,safe);
- else if(primaryAxis == Z_AXIS)
+ // Check for minimum speeds needed for numerical robustness
+ /*if(drivingAxis == X_AXIS || drivingAxis == Y_AXIS) // enforce minimum speed for numerical stability of explicit speed integration
+ safe = RMath::max(Printer::minimumSpeed, safe);
+ else if(drivingAxis == Z_AXIS)
{
- safe = RMath::max(Printer::minimumZSpeed,safe);
- }
- return RMath::min(safe,fullSpeed);
+ safe = RMath::max(Printer::minimumZSpeed, safe);
+ }*/
+ return RMath::min(safe, fullSpeed);
}
@@ -825,8 +1131,9 @@ processing.
*/
uint8_t PrintLine::insertWaitMovesIfNeeded(uint8_t pathOptimize, uint8_t waitExtraLines)
{
- if(linesCount == 0 && waitRelax == 0 && pathOptimize) // First line after some time - warmup needed
+ if(linesCount == 0 && waitRelax == 0 && pathOptimize) // First line after some time - warm up needed
{
+ //return 0;
#if NONLINEAR_SYSTEM
uint8_t w = 3;
#else
@@ -840,12 +1147,14 @@ uint8_t PrintLine::insertWaitMovesIfNeeded(uint8_t pathOptimize, uint8_t waitExt
p->dir = 0;
p->setWaitForXLinesFilled(w + waitExtraLines);
#if NONLINEAR_SYSTEM
- p->setWaitTicks(50000);
+ p->setWaitTicks(300000);
+ p->moveID = lastMoveID++;
#else
- p->setWaitTicks(25000);
+ p->setWaitTicks(100000);
#endif // NONLINEAR_SYSTEM
pushLine();
}
+ //Com::printFLN(PSTR("InsertWait"));
return 1;
}
return 0;
@@ -856,8 +1165,8 @@ void PrintLine::logLine()
#ifdef DEBUG_QUEUE_MOVE
Com::printFLN(Com::tDBGId,(int)this);
Com::printArrayFLN(Com::tDBGDelta,delta);
- Com::printFLN(Com::tDBGDir,dir);
- Com::printFLN(Com::tDBGFlags,flags);
+ Com::printFLN(Com::tDBGDir,(uint32_t)dir);
+ Com::printFLN(Com::tDBGFlags,(uint32_t)flags);
Com::printFLN(Com::tDBGFullSpeed,fullSpeed);
Com::printFLN(Com::tDBGVMax,(int32_t)vMax);
Com::printFLN(Com::tDBGAcceleration,accelerationDistance2);
@@ -881,6 +1190,37 @@ void PrintLine::waitForXFreeLines(uint8_t b, bool allowMoves)
}
}
+#ifdef FAST_COREXYZ
+uint8_t transformCartesianStepsToDeltaSteps(int32_t cartesianPosSteps[], int32_t corePosSteps[])
+{
+ #if DRIVE_SYSTEM == XY_GANTRY
+ //1 = z axis + xy H-gantry (x_motor = x+y, y_motor = x-y)
+ corePosSteps[A_TOWER] = cartesianPosSteps[X_AXIS] + cartesianPosSteps[Y_AXIS];
+ corePosSteps[B_TOWER] = cartesianPosSteps[X_AXIS] - cartesianPosSteps[Y_AXIS];
+ corePosSteps[C_TOWER] = cartesianPosSteps[Z_AXIS];
+ #elif DRIVE_SYSTEM == YX_GANTRY
+ // 2 = z axis + xy H-gantry (x_motor = x+y, y_motor = y-x)
+ corePosSteps[A_TOWER] = cartesianPosSteps[X_AXIS] + cartesianPosSteps[Y_AXIS];
+ corePosSteps[B_TOWER] = cartesianPosSteps[Y_AXIS] - cartesianPosSteps[X_AXIS];
+ corePosSteps[C_TOWER] = cartesianPosSteps[Z_AXIS];
+ #elif DRIVE_SYSTEM == XZ_GANTRY
+ // 8 = y axis + xz H-gantry (x_motor = x+z, z_motor = x-z)
+ corePosSteps[A_TOWER] = cartesianPosSteps[X_AXIS] + cartesianPosSteps[Z_AXIS];
+ corePosSteps[C_TOWER] = cartesianPosSteps[X_AXIS] - cartesianPosSteps[Z_AXIS];
+ corePosSteps[B_TOWER] = cartesianPosSteps[Y_AXIS];
+ #elif DRIVE_SYSTEM == ZX_GANTRY
+ //9 = y axis + xz H-gantry (x_motor = x+z, z_motor = z-x)
+ corePosSteps[A_TOWER] = cartesianPosSteps[X_AXIS] + cartesianPosSteps[Z_AXIS];
+ corePosSteps[C_TOWER] = cartesianPosSteps[Z_AXIS] - cartesianPosSteps[X_AXIS];
+ corePosSteps[B_TOWER] = cartesianPosSteps[Y_AXIS];
+ #elif DRIVE_SYSTEM == GANTRY_FAKE
+ corePosSteps[A_TOWER] = cartesianPosSteps[X_AXIS];
+ corePosSteps[B_TOWER] = cartesianPosSteps[Y_AXIS];
+ corePosSteps[C_TOWER] = cartesianPosSteps[Z_AXIS];
+ #endif
+ return 1;
+}
+#endif
#if DRIVE_SYSTEM == DELTA
// pick one for verbose the other silent
@@ -894,10 +1234,10 @@ void PrintLine::waitForXFreeLines(uint8_t b, bool allowMoves)
SHOW(Printer::deltaDiagonalStepsSquaredA.l); return 0; }
*/
/**
- Calculate the delta tower position from a cartesian position
- @param cartesianPosSteps Array containing cartesian coordinates.
+ Calculate the delta tower position from a Cartesian position
+ @param cartesianPosSteps Array containing Cartesian coordinates.
@param deltaPosSteps Result array with tower coordinates.
- @returns 1 if cartesian coordinates have a valid delta tower position 0 if not.
+ @returns 1 if Cartesian coordinates have a valid delta tower position 0 if not.
*/
uint8_t transformCartesianStepsToDeltaSteps(int32_t cartesianPosSteps[], int32_t deltaPosSteps[])
{
@@ -907,19 +1247,19 @@ uint8_t transformCartesianStepsToDeltaSteps(int32_t cartesianPosSteps[], int32_t
static int32_t lastZSteps = 9999999;
static int32_t lastZCorrection = 0;
cnt++;
- if(cnt >= DISTORTION_UPDATE_FREQUENCY || lastZSteps != zSteps) {
+ if(cnt >= DISTORTION_UPDATE_FREQUENCY || lastZSteps != zSteps)
+ {
cnt = 0;
lastZSteps = zSteps;
lastZCorrection = Printer::distortion.correct(cartesianPosSteps[X_AXIS], cartesianPosSteps[Y_AXIS], cartesianPosSteps[Z_AXIS]);
}
zSteps += lastZCorrection;
#endif
- //SHOWA("motion.c transformCart... cartesian ",cartesianPosSteps, 3);
if(Printer::isLargeMachine())
{
#ifdef SUPPORT_64_BIT_MATH
- // 64 bit is better for precision, so we use that if available.
- // A TOWER height
+ // 64 bit is better for precision, so we use that if available.
+ // A TOWER height
uint64_t temp = RMath::absLong(Printer::deltaAPosYSteps - cartesianPosSteps[Y_AXIS]);
uint64_t opt = Printer::deltaDiagonalStepsSquaredA.L;
@@ -933,7 +1273,7 @@ uint8_t transformCartesianStepsToDeltaSteps(int32_t cartesianPosSteps[], int32_t
if (opt < temp)
RETURN_0("Apos x square ");
- deltaPosSteps[A_TOWER] = HAL::integer64Sqrt(opt-temp) + zSteps;
+ deltaPosSteps[A_TOWER] = HAL::integer64Sqrt(opt - temp) + zSteps;
if (deltaPosSteps[A_TOWER] < Printer::deltaFloorSafetyMarginSteps && !Printer::isZProbingActive())
RETURN_0("A hit floor");
@@ -950,7 +1290,7 @@ uint8_t transformCartesianStepsToDeltaSteps(int32_t cartesianPosSteps[], int32_t
if (opt < temp)
RETURN_0("Bpos x square ");
- deltaPosSteps[B_TOWER] = HAL::integer64Sqrt(opt-temp) + zSteps ;
+ deltaPosSteps[B_TOWER] = HAL::integer64Sqrt(opt - temp) + zSteps ;
if (deltaPosSteps[B_TOWER] < Printer::deltaFloorSafetyMarginSteps && !Printer::isZProbingActive())
RETURN_0("B hit floor");
@@ -980,7 +1320,7 @@ uint8_t transformCartesianStepsToDeltaSteps(int32_t cartesianPosSteps[], int32_t
+ zSteps);
else
return 0;
- if (deltaPosSteps[A_TOWER]< Printer::deltaFloorSafetyMarginSteps) return 0;
+ if (deltaPosSteps[A_TOWER] < Printer::deltaFloorSafetyMarginSteps && !Printer::isZProbingActive()) return 0;
temp = Printer::deltaBPosYSteps - cartesianPosSteps[Y_AXIS];
opt = Printer::deltaDiagonalStepsSquaredB.f - temp * temp;
@@ -990,7 +1330,7 @@ uint8_t transformCartesianStepsToDeltaSteps(int32_t cartesianPosSteps[], int32_t
+ zSteps);
else
return 0;
- if (deltaPosSteps[B_TOWER]< Printer::deltaFloorSafetyMarginSteps) return 0;
+ if (deltaPosSteps[B_TOWER] < Printer::deltaFloorSafetyMarginSteps && !Printer::isZProbingActive()) return 0;
temp = Printer::deltaCPosYSteps - cartesianPosSteps[Y_AXIS];
opt = Printer::deltaDiagonalStepsSquaredC.f - temp * temp;
@@ -1000,7 +1340,7 @@ uint8_t transformCartesianStepsToDeltaSteps(int32_t cartesianPosSteps[], int32_t
+ zSteps);
else
return 0;
- if (deltaPosSteps[C_TOWER]< Printer::deltaFloorSafetyMarginSteps) return 0;
+ if (deltaPosSteps[C_TOWER] < Printer::deltaFloorSafetyMarginSteps && !Printer::isZProbingActive()) return 0;
return 1;
#endif
@@ -1124,10 +1464,10 @@ uint8_t transformCartesianStepsToDeltaSteps(int32_t cartesianPosSteps[], int32_t
#if DRIVE_SYSTEM==TUGA
/**
- Calculate the delta tower position from a cartesian position
- @param cartesianPosSteps Array containing cartesian coordinates.
+ Calculate the delta tower position from a Cartesian position
+ @param cartesianPosSteps Array containing Cartesian coordinates.
@param deltaPosSteps Result array with tower coordinates.
- @returns 1 if cartesian coordinates have a valid delta tower position 0 if not.
+ @returns 1 if Cartesian coordinates have a valid delta tower position 0 if not.
X Y
* *
@@ -1169,119 +1509,205 @@ uint8_t transformCartesianStepsToDeltaSteps(int32_t cartesianPosSteps[], int32_t
#if NONLINEAR_SYSTEM
-void DeltaSegment::checkEndstops(PrintLine *cur,bool checkall)
+bool NonlinearSegment::checkEndstops(PrintLine *cur, bool checkall)
{
+ fast8_t r = 0;
if(Printer::isZProbingActive())
{
+ Endstops::update();
#if FEATURE_Z_PROBE
- if(isZNegativeMove() && Printer::isZProbeHit())
+ if(isZNegativeMove() && Endstops::zProbe())
{
+#if DRIVE_SYSTEM == DELTA
cur->setXMoveFinished();
cur->setYMoveFinished();
+#endif
cur->setZMoveFinished();
- dir = 0;
+ //dir = 0;
Printer::stepsRemainingAtZHit = cur->stepsRemaining;
cur->stepsRemaining = 0;
- return;
+ return true;
}
#endif
-#if DRIVE_SYSTEM==DELTA
- if(isZPositiveMove() && isXPositiveMove() && isYPositiveMove() && (Printer::isXMaxEndstopHit() || Printer::isYMaxEndstopHit() || Printer::isZMaxEndstopHit()))
+#if DRIVE_SYSTEM == DELTA
+ if(isZPositiveMove() && isXPositiveMove() && isYPositiveMove() && Endstops::anyXYZMax())
#else
- if(isZPositiveMove() && Printer::isZMaxEndstopHit())
+ if(isZPositiveMove() && Endstops::zMax())
#endif
{
+#if DRIVE_SYSTEM == DELTA
cur->setXMoveFinished();
cur->setYMoveFinished();
+#endif
cur->setZMoveFinished();
- dir = 0;
+ //dir = 0;
Printer::stepsRemainingAtZHit = cur->stepsRemaining;
- return;
+ return true;
}
- }
+ } else if(checkall) {
+ Endstops::update(); // do not test twice
+ if(!Endstops::anyXYZ()) // very quick check for the normal case
+ return false;
+ }
if(checkall)
{
- if(isXPositiveMove() && Printer::isXMaxEndstopHit())
+#if GANTRY
+ // Test axis endstops based on global direction
+ if(cur->isXPositiveMove() && Endstops::xMax())
+ {
+ setXMoveFinished();
+ cur->setXMoveFinished();
+ r = 1;
+ }
+ if(cur->isYPositiveMove() && Endstops::yMax())
+ {
+ setYMoveFinished();
+ cur->setYMoveFinished();
+ r = 1;
+ }
+ if(cur->isXNegativeMove() && Endstops::xMin())
+ {
+ setXMoveFinished();
+ cur->setXMoveFinished();
+ r = 1;
+ }
+ if(cur->isYNegativeMove() && Endstops::yMin())
+ {
+ setYMoveFinished();
+ cur->setYMoveFinished();
+ r = 1;
+ }
+ if(cur->isZPositiveMove() && Endstops::zMax())
+ {
+ setZMoveFinished();
+ cur->setZMoveFinished();
+ r = 1;
+ }
+ if(cur->isZNegativeMove() && Endstops::zMin())
+ {
+ setZMoveFinished();
+ cur->setZMoveFinished();
+ r = 1;
+ }
+#else
+ // endstops are per motor and do not depend on global axis movement
+ if(isXPositiveMove() && Endstops::xMax())
{
#if DRIVE_SYSTEM == DELTA
- Printer::stepsRemainingAtXHit = cur->stepsRemaining;
+ if(Printer::stepsRemainingAtXHit < 0)
+ Printer::stepsRemainingAtXHit = cur->stepsRemaining;
#endif
setXMoveFinished();
cur->setXMoveFinished();
+ r++;
}
- if(isYPositiveMove() && Printer::isYMaxEndstopHit())
+ if(isYPositiveMove() && Endstops::yMax())
{
#if DRIVE_SYSTEM == DELTA
- Printer::stepsRemainingAtYHit = cur->stepsRemaining;
+ if(Printer::stepsRemainingAtYHit < 0)
+ Printer::stepsRemainingAtYHit = cur->stepsRemaining;
#endif
setYMoveFinished();
cur->setYMoveFinished();
- }
- if(isXPositiveMove() && Printer::isXMaxEndstopHit())
- {
- setXMoveFinished();
- cur->setXMoveFinished();
- }
- if(isYPositiveMove() && Printer::isYMaxEndstopHit())
- {
- setYMoveFinished();
- cur->setYMoveFinished();
+ r++;
}
#if DRIVE_SYSTEM != DELTA
- if(isXNegativeMove() && Printer::isXMinEndstopHit())
+ if(isXNegativeMove() && Endstops::xMin())
{
setXMoveFinished();
cur->setXMoveFinished();
+ r++;
}
- if(isYNegativeMove() && Printer::isYMinEndstopHit())
+ if(isYNegativeMove() && Endstops::yMin())
{
setYMoveFinished();
cur->setYMoveFinished();
+ r++;
}
#endif
- if(isZPositiveMove() && Printer::isZMaxEndstopHit())
+ if(isZPositiveMove() && Endstops::zMax())
{
#if MAX_HARDWARE_ENDSTOP_Z
- Printer::stepsRemainingAtZHit = cur->stepsRemaining;
+ if(Printer::stepsRemainingAtZHit)
+ Printer::stepsRemainingAtZHit = cur->stepsRemaining;
#endif
setZMoveFinished();
cur->setZMoveFinished();
+ r++;
}
+ if(isZNegativeMove() && Endstops::zMin())
+ {
+ setZMoveFinished();
+ cur->setZMoveFinished();
+ r++;
+ }
+#if DRIVE_SYSTEM == DELTA
+ if(Printer::isHoming())
+ return r == 3;
+#endif
+#endif // Not gantry
}
- if(isZNegativeMove() && Printer::isZMinEndstopHit())
- {
- setZMoveFinished();
- cur->setZMoveFinished();
- }
-
+ return r != 0;
}
-void PrintLine::calculateDirectionAndDelta(int32_t difference[], flag8_t *dir, int32_t delta[])
+void PrintLine::calculateDirectionAndDelta(int32_t difference[], ufast8_t *dir, int32_t delta[])
{
*dir = 0;
//Find direction
- for(uint8_t i = 0; i < 4; i++)
- {
- if(difference[i] >= 0)
- {
- delta[i] = difference[i];
- *dir |= X_DIRPOS << i;
- }
- else
- {
- delta[i] = -difference[i];
- }
- if(delta[i]) *dir |= XSTEP << i;
- }
+ if(difference[X_AXIS] != 0) {
+ if(difference[X_AXIS] < 0) {
+ delta[X_AXIS] = -difference[X_AXIS];
+ *dir |= XSTEP;
+ } else {
+ delta[X_AXIS] = difference[X_AXIS];
+ *dir |= X_DIRPOS + XSTEP;
+ }
+ } else {
+ delta[X_AXIS] = 0;
+ }
+
+ if(difference[Y_AXIS] != 0) {
+ if(difference[Y_AXIS] < 0) {
+ delta[Y_AXIS] = -difference[Y_AXIS];
+ *dir |= YSTEP;
+ } else {
+ delta[Y_AXIS] = difference[Y_AXIS];
+ *dir |= Y_DIRPOS + YSTEP;
+ }
+ } else {
+ delta[Y_AXIS] = 0;
+ }
+ if(difference[Z_AXIS] != 0) {
+ if(difference[Z_AXIS] < 0) {
+ delta[Z_AXIS] = -difference[Z_AXIS];
+ *dir |= ZSTEP;
+ } else {
+ delta[Z_AXIS] = difference[Z_AXIS];
+ *dir |= Z_DIRPOS + ZSTEP;
+ }
+ } else {
+ delta[Z_AXIS] = 0;
+ }
+ if(difference[E_AXIS] != 0) {
+ if(difference[E_AXIS] < 0) {
+ delta[E_AXIS] = -difference[E_AXIS];
+ *dir |= ESTEP;
+ } else {
+ delta[E_AXIS] = difference[E_AXIS];
+ *dir |= E_DIRPOS + ESTEP;
+ }
+ } else {
+ delta[E_AXIS] = 0;
+ }
}
/**
- Calculate and cache the delta robot positions of the cartesian move in a line.
+ Calculate and cache the delta robot positions of the Cartesian move in a line.
@return The largest delta axis move in a single segment
@param p The line to examine.
*/
-inline uint16_t PrintLine::calculateDeltaSubSegments(uint8_t softEndstop)
+inline uint16_t PrintLine::calculateNonlinearSubSegments(uint8_t softEndstop)
{
- uint8_t i;
+ fast8_t i;
int32_t delta,diff;
int32_t destinationSteps[Z_AXIS_ARRAY], destinationDeltaSteps[TOWER_ARRAY];
// Save current position
@@ -1291,24 +1717,24 @@ inline uint16_t PrintLine::calculateDeltaSubSegments(uint8_t softEndstop)
#else
float dx[Z_AXIS_ARRAY];
for(int i = 0; i < Z_AXIS_ARRAY; i++)
- dx[i] = static_cast(Printer::destinationSteps[i] - Printer::currentPositionSteps[i]) / static_cast(numDeltaSegments);
+ dx[i] = static_cast(Printer::destinationSteps[i] - Printer::currentPositionSteps[i]) / static_cast(numNonlinearSegments);
#endif
// out.println_byte_P(PSTR("Calculate delta segments:"), p->numDeltaSegments);
#ifdef DEBUG_STEPCOUNT
totalStepsRemaining = 0;
#endif
- uint16_t maxAxisMove = 0;
- for (int s = numDeltaSegments; s > 0; s--)
+ uint16_t maxAxisSteps = 0;
+ for (int s = numNonlinearSegments; s > 0; s--)
{
- DeltaSegment *d = &segments[s - 1];
+ NonlinearSegment *d = &segments[s - 1];
#if (CPU_ARCH == ARCH_AVR) && !EXACT_DELTA_MOVES
for(i = 0; i < Z_AXIS_ARRAY; i++)
{
- // End of segment in cartesian steps
+ // End of segment in Cartesian steps
- // This method generates small waves which get larger with increasing number of delta segments. smaller??
+ // This method generates small waves which get larger with increasing number of delta segments. smaller?
diff = Printer::destinationSteps[i] - destinationSteps[i];
if(s == 1)
destinationSteps[i] += diff;
@@ -1316,31 +1742,32 @@ inline uint16_t PrintLine::calculateDeltaSubSegments(uint8_t softEndstop)
destinationSteps[i] += (diff >> 1);
else if(s == 4)
destinationSteps[i] += (diff >> 2);
- else if(diff<0)
+ else if(diff < 0)
destinationSteps[i] -= HAL::Div4U2U(-diff, s);
else
destinationSteps[i] += HAL::Div4U2U(diff, s);
}
#else
- float segment = static_cast(numDeltaSegments - s + 1);
- for(i=0; i < Z_AXIS_ARRAY; i++) // End of segment in cartesian steps
+ float segment = static_cast(numNonlinearSegments - s + 1);
+ for(i = 0; i < Z_AXIS_ARRAY; i++) // End of segment in Cartesian steps
// Perfect approximation, but slower, so we limit it to faster processors like arm
destinationSteps[i] = static_cast(floor(0.5 + dx[i] * segment)) + Printer::currentPositionSteps[i];
#endif
- // Verify that delta calc has a solution
+ // Verify that delta calculation has a solution
if (transformCartesianStepsToDeltaSteps(destinationSteps, destinationDeltaSteps))
{
d->dir = 0;
+#if DRIVE_SYSTEM == DELTA
if (softEndstop)
{
destinationDeltaSteps[A_TOWER] = RMath::min(destinationDeltaSteps[A_TOWER], Printer::maxDeltaPositionSteps);
destinationDeltaSteps[B_TOWER] = RMath::min(destinationDeltaSteps[B_TOWER], Printer::maxDeltaPositionSteps);
destinationDeltaSteps[C_TOWER] = RMath::min(destinationDeltaSteps[C_TOWER], Printer::maxDeltaPositionSteps);
}
-
+#endif
for(i = 0; i < TOWER_ARRAY; i++)
{
- delta = destinationDeltaSteps[i] - Printer::currentDeltaPositionSteps[i];
+ delta = destinationDeltaSteps[i] - Printer::currentNonlinearPositionSteps[i];
if (delta > 0)
{
d->setPositiveMoveOfAxis(i);
@@ -1362,8 +1789,9 @@ inline uint16_t PrintLine::calculateDeltaSubSegments(uint8_t softEndstop)
#ifdef DEBUG_STEPCOUNT
totalStepsRemaining += d->deltaSteps[i];
#endif
- maxAxisMove = RMath::max(maxAxisMove,d->deltaSteps[i]);
- Printer::currentDeltaPositionSteps[i] = destinationDeltaSteps[i];
+ if(d->deltaSteps[i] > maxAxisSteps)
+ maxAxisSteps = d->deltaSteps[i];
+ Printer::currentNonlinearPositionSteps[i] = destinationDeltaSteps[i];
}
}
else
@@ -1381,30 +1809,30 @@ inline uint16_t PrintLine::calculateDeltaSubSegments(uint8_t softEndstop)
#ifdef DEBUG_STEPCOUNT
// out.println_long_P(PSTR("initial StepsRemaining:"), p->totalStepsRemaining);
#endif
- return maxAxisMove;
+ return maxAxisSteps;
}
-uint8_t PrintLine::calculateDistance(float axisDiff[], uint8_t dir, float *distance)
+uint8_t PrintLine::calculateDistance(float axisDistanceMM[], uint8_t dir, float *distance)
{
// Calculate distance depending on direction
if(dir & XYZ_STEP)
{
if(dir & XSTEP)
- *distance = axisDiff[X_AXIS] * axisDiff[X_AXIS];
+ *distance = axisDistanceMM[X_AXIS] * axisDistanceMM[X_AXIS];
else
*distance = 0;
if(dir & YSTEP)
- *distance += axisDiff[Y_AXIS] * axisDiff[Y_AXIS];
+ *distance += axisDistanceMM[Y_AXIS] * axisDistanceMM[Y_AXIS];
if(dir & ZSTEP)
- *distance += axisDiff[Z_AXIS] * axisDiff[Z_AXIS];
- *distance = RMath::max((float)sqrt(*distance),fabs(axisDiff[E_AXIS]));
+ *distance += axisDistanceMM[Z_AXIS] * axisDistanceMM[Z_AXIS];
+ *distance = RMath::max((float)sqrt(*distance), axisDistanceMM[E_AXIS]);
return 1;
}
else
{
if(dir & ESTEP)
{
- *distance = fabs(axisDiff[E_AXIS]);
+ *distance = axisDistanceMM[E_AXIS];
return 1;
}
*distance = 0;
@@ -1433,16 +1861,21 @@ inline void PrintLine::queueEMove(int32_t extrudeDiff,uint8_t check_endstops,uin
waitForXFreeLines(1);
uint8_t newPath = insertWaitMovesIfNeeded(pathOptimize, 1);
PrintLine *p = getNextWriteLine();
- float axisDiff[5]; // Axis movement in mm
+ float axisDistanceMM[VIRTUAL_AXIS_ARRAY]; // Axis movement in mm
if(check_endstops) p->flags = FLAG_CHECK_ENDSTOPS;
else p->flags = 0;
+#if MIXING_EXTRUDER
+ if(Printer::isAllEMotors()) {
+ p->flags |= FLAG_ALL_E_MOTORS;
+ }
+#endif
p->joinFlags = 0;
if(!pathOptimize) p->setEndSpeedFixed(true);
//Find direction
- for(uint8_t i = 0; i < 3; i++)
+ for(uint8_t i = 0; i < Z_AXIS_ARRAY; i++)
{
p->delta[i] = 0;
- axisDiff[i] = 0;
+ axisDistanceMM[i] = 0;
}
if (extrudeDiff >= 0)
{
@@ -1456,47 +1889,60 @@ inline void PrintLine::queueEMove(int32_t extrudeDiff,uint8_t check_endstops,uin
}
Printer::currentPositionSteps[E_AXIS] = Printer::destinationSteps[E_AXIS];
- p->numDeltaSegments = 0;
+ p->numNonlinearSegments = 0;
//Define variables that are needed for the Bresenham algorithm. Please note that Z is not currently included in the Bresenham algorithm.
p->primaryAxis = E_AXIS;
p->stepsRemaining = p->delta[E_AXIS];
- axisDiff[E_AXIS] = p->distance = p->delta[E_AXIS] * Printer::invAxisStepsPerMM[E_AXIS];
- axisDiff[VIRTUAL_AXIS] = -p->distance;
+ axisDistanceMM[E_AXIS] = p->distance = p->delta[E_AXIS] * Printer::invAxisStepsPerMM[E_AXIS];
+ axisDistanceMM[VIRTUAL_AXIS] = -p->distance;
p->moveID = lastMoveID++;
- p->calculateMove(axisDiff,pathOptimize);
+ p->calculateMove(axisDistanceMM,pathOptimize,E_AXIS);
}
/**
Split a line up into a series of lines with at most DELTASEGMENTS_PER_PRINTLINE delta segments.
@param check_endstops Check endstops during the move.
@param pathOptimize Run the path optimizer.
- @param delta_step_rate delta step rate in segments per second for the move.
+ @param softEndstop check if we go out of bounds.
*/
-uint8_t PrintLine::queueDeltaMove(uint8_t check_endstops,uint8_t pathOptimize, uint8_t softEndstop)
+uint8_t PrintLine::queueNonlinearMove(uint8_t check_endstops,uint8_t pathOptimize, uint8_t softEndstop)
{
//if (softEndstop && Printer::destinationSteps[Z_AXIS] < 0) Printer::destinationSteps[Z_AXIS] = 0; // now constrained at entry level including cylinder test
+ EVENT_CONTRAIN_DESTINATION_COORDINATES
int32_t difference[E_AXIS_ARRAY];
- float axis_diff[VIRTUAL_AXIS_ARRAY]; // Axis movement in mm. Virtual axis in 4;
+ float axisDistanceMM[VIRTUAL_AXIS_ARRAY]; // Real cartesian axis movement in mm. Virtual axis in 4;
+ uint8_t secondSpeed = Printer::fanSpeed;
for(fast8_t axis = 0; axis < E_AXIS_ARRAY; axis++)
{
difference[axis] = Printer::destinationSteps[axis] - Printer::currentPositionSteps[axis];
if(axis == E_AXIS)
{
- Printer::extrudeMultiplyError += (static_cast(difference[E_AXIS]) * Printer::extrusionFactor);
- difference[E_AXIS] = static_cast(Printer::extrudeMultiplyError);
- Printer::extrudeMultiplyError -= difference[E_AXIS];
- axis_diff[E_AXIS] = difference[E_AXIS] * Printer::invAxisStepsPerMM[E_AXIS];
- Printer::filamentPrinted += axis_diff[E_AXIS];
- axis_diff[E_AXIS] = fabs(axis_diff[E_AXIS]);
- } else
- axis_diff[axis] = fabs(difference[axis] * Printer::invAxisStepsPerMM[axis]);
+ if(Printer::mode == PRINTER_MODE_FFF)
+ {
+ Printer::extrudeMultiplyError += (static_cast(difference[E_AXIS]) * Printer::extrusionFactor);
+ difference[E_AXIS] = static_cast(Printer::extrudeMultiplyError);
+ Printer::extrudeMultiplyError -= difference[E_AXIS];
+ axisDistanceMM[E_AXIS] = difference[E_AXIS] * Printer::invAxisStepsPerMM[E_AXIS];
+ Printer::filamentPrinted += axisDistanceMM[E_AXIS];
+ axisDistanceMM[E_AXIS] = fabs(axisDistanceMM[E_AXIS]);
+ }
+#if defined(SUPPORT_LASER) && SUPPORT_LASER
+ else if(Printer::mode == PRINTER_MODE_LASER)
+ {
+ secondSpeed = ((axisDistanceMM[X_AXIS] != 0 || axisDistanceMM[Y_AXIS] != 0) && (LaserDriver::laserOn || axisDistanceMM[E_AXIS] != 0) ? LaserDriver::intensity : 0);
+ axisDistanceMM[E_AXIS] = 0;
+ }
+#endif
+ }
+ else
+ axisDistanceMM[axis] = fabs(difference[axis] * Printer::invAxisStepsPerMM[axis]);
}
float cartesianDistance;
- flag8_t cartesianDir;
+ ufast8_t cartesianDir;
int32_t cartesianDeltaSteps[E_AXIS_ARRAY];
calculateDirectionAndDelta(difference, &cartesianDir, cartesianDeltaSteps);
- if (!calculateDistance(axis_diff, cartesianDir, &cartesianDistance))
+ if (!calculateDistance(axisDistanceMM, cartesianDir, &cartesianDistance))
{
// Appears the intent is to do nothing if no distance is detected.
// This apparently is not an error condition, just early exit.
@@ -1510,7 +1956,11 @@ uint8_t PrintLine::queueDeltaMove(uint8_t check_endstops,uint8_t pathOptimize, u
}
int16_t segmentCount;
+#if DRIVE_SYSTEM == DELTA
float feedrate = RMath::min(Printer::feedrate, Printer::maxFeedrate[Z_AXIS]);
+#else
+ float feedrate = Printer::feedrate; // each motor has own max. feedrate here resulting in total feedrate
+#endif
if (cartesianDir & XY_STEP)
{
// Compute number of seconds for move and hence number of segments needed
@@ -1519,14 +1969,14 @@ uint8_t PrintLine::queueDeltaMove(uint8_t check_endstops,uint8_t pathOptimize, u
#ifdef DEBUG_SPLIT
Com::printFLN(Com::tDBGDeltaSeconds, seconds);
#endif
- float sps = static_cast((cartesianDir & E_STEP_DIRPOS) == E_STEP_DIRPOS ? Printer::printMovesPerSecond : Printer::travelMovesPerSecond);
+ float sps = static_cast((cartesianDir & ESTEP) == ESTEP ? Printer::printMovesPerSecond : Printer::travelMovesPerSecond);
segmentCount = RMath::max(1, static_cast