diff --git a/ulisp-arm.ino b/ulisp-arm.ino index 27f823e..d1807a7 100644 --- a/ulisp-arm.ino +++ b/ulisp-arm.ino @@ -1,5 +1,5 @@ -/* uLisp ARM Version 2.3 - www.ulisp.com - David Johnson-Davies - www.technoblogy.com - 2nd June 2018 +/* uLisp ARM Version 2.4 - www.ulisp.com + David Johnson-Davies - www.technoblogy.com - 15th September 2018 Licensed under the MIT license: https://opensource.org/licenses/MIT */ @@ -23,6 +23,9 @@ #if defined(sdcardsupport) #include +#define SDSIZE 172 +#else +#define SDSIZE 0 #endif // C Macros @@ -116,22 +119,40 @@ typedef void (*pfun_t)(char); #define BUFFERSIZE 34 // Number of bits+2 #if defined(ARDUINO_SAMD_ZERO) - #define WORKSPACESIZE 3072 /* Cells (8*bytes) */ + #define WORKSPACESIZE 3072-SDSIZE /* Cells (8*bytes) */ #define SYMBOLTABLESIZE 512 /* Bytes */ #define SDCARD_SS_PIN 10 uint8_t _end; #elif defined(ARDUINO_SAM_DUE) - #define WORKSPACESIZE 10240 /* Cells (8*bytes) */ + #define WORKSPACESIZE 3072-SDSIZE /* Cells (8*bytes) */ #define SYMBOLTABLESIZE 512 /* Bytes */ #define SDCARD_SS_PIN 10 extern uint8_t _end; #elif defined(ARDUINO_SAMD_MKRZERO) - #define WORKSPACESIZE 3072 /* Cells (8*bytes) */ + #define WORKSPACESIZE 3072-SDSIZE /* Cells (8*bytes) */ #define SYMBOLTABLESIZE 512 /* Bytes */ uint8_t _end; +#elif defined(ARDUINO_METRO_M4) + #define WORKSPACESIZE 3072-SDSIZE /* Cells (8*bytes) */ + #define FLASHSIZE 65536 /* Bytes */ + #define SYMBOLTABLESIZE 1024 /* Bytes */ + uint8_t _end; + +#elif defined(ARDUINO_ITSYBITSY_M4) + #define WORKSPACESIZE 3072-SDSIZE /* Cells (8*bytes) */ + #define FLASHSIZE 65536 /* Bytes */ + #define SYMBOLTABLESIZE 1024 /* Bytes */ + uint8_t _end; + +#elif defined(ARDUINO_FEATHER_M4) + #define WORKSPACESIZE 3072-SDSIZE /* Cells (8*bytes) */ + #define FLASHSIZE 65536 /* Bytes */ + #define SYMBOLTABLESIZE 1024 /* Bytes */ + uint8_t _end; + #elif defined(_VARIANT_BBC_MICROBIT_) #define WORKSPACESIZE 1024 /* Cells (8*bytes) */ #define SYMBOLTABLESIZE 512 /* Bytes */ @@ -373,14 +394,115 @@ char *MakeFilename (object *arg) { // Save-image and load-image #if defined(sdcardsupport) -void SDWriteInt(File file, int data) { - file.write(data & 0xFF); file.write(data>>8 & 0xFF); -} - -void SDWritePtr(File file, uintptr_t data) { +void SDWriteInt (File file, int data) { file.write(data & 0xFF); file.write(data>>8 & 0xFF); file.write(data>>16 & 0xFF); file.write(data>>24 & 0xFF); } +#elif defined(ARDUINO_METRO_M4) || defined(ARDUINO_ITSYBITSY_M4) || defined(ARDUINO_FEATHER_M4) +// Winbond DataFlash support for Adafruit M4 Express boards +#define PAGEPROG 0x02 +#define READSTATUS 0x05 +#define READDATA 0x03 +#define WRITEENABLE 0x06 +#define BLOCK64K 0xD8 +#define READID 0x90 + +// Arduino pins used for dataflash +#if defined(ARDUINO_ITSYBITSY_M4) +const int sck = 32, ssel = 33, mosi = 34, miso = 35; +#elif defined(ARDUINO_METRO_M4) +const int sck = 41, ssel = 42, mosi = 43, miso = 44; +#elif defined(ARDUINO_FEATHER_M4) +const int sck = 34, ssel = 35, mosi = 36, miso = 37; +#endif + +boolean FlashSetup () { + uint8_t manID, devID; + digitalWrite(ssel, HIGH); pinMode(ssel, OUTPUT); + pinMode(sck, OUTPUT); + pinMode(mosi, OUTPUT); + pinMode(miso, INPUT); + digitalWrite(sck, LOW); digitalWrite(mosi, HIGH); + digitalWrite(ssel, LOW); + FlashWrite(READID); + for(uint8_t i=0; i<4; i++) manID = FlashRead(); + devID = FlashRead(); + digitalWrite(ssel, HIGH); + return (devID == 0x14); // Found correct device +} + +inline void FlashWrite (uint8_t data) { + shiftOut(mosi, sck, MSBFIRST, data); +} + +void FlashBusy () { + digitalWrite(ssel, 0); + FlashWrite(READSTATUS); + while (FlashRead() & 1 != 0); + digitalWrite(ssel, 1); +} + +void FlashWriteEnable () { + digitalWrite(ssel, 0); + FlashWrite(WRITEENABLE); + digitalWrite(ssel, 1); +} + +void FlashBeginRead () { + FlashBusy(); + digitalWrite(ssel, 0); + FlashWrite(READDATA); + FlashWrite(0); FlashWrite(0); FlashWrite(0); +} + +inline uint8_t FlashRead () { + int data; + return shiftIn(miso, sck, MSBFIRST); +} + +inline void FlashEndRead(void) { + digitalWrite(ssel, 1); +} + +void FlashBeginWrite () { + FlashBusy(); + // Erase 64K + FlashWriteEnable(); + digitalWrite(ssel, 0); + FlashWrite(BLOCK64K); + FlashWrite(0); FlashWrite(0); FlashWrite(0); + digitalWrite(ssel, 1); + FlashBusy(); +} + +inline uint8_t FlashReadByte () { + return FlashRead(); +} + +void FlashWriteByte (unsigned int *addr, uint8_t data) { + // New page + if (((*addr) & 0xFF) == 0) { + digitalWrite(ssel, 1); + FlashBusy(); + FlashWriteEnable(); + digitalWrite(ssel, 0); + FlashWrite(PAGEPROG); + FlashWrite((*addr)>>16); + FlashWrite((*addr)>>8); + FlashWrite(0); + } + FlashWrite(data); + (*addr)++; +} + +inline void FlashEndWrite (void) { + digitalWrite(ssel, 1); +} + +void FlashWriteInt (unsigned int *addr, int data) { + FlashWriteByte(addr, data & 0xFF); FlashWriteByte(addr, data>>8 & 0xFF); + FlashWriteByte(addr, data>>16 & 0xFF); FlashWriteByte(addr, data>>24 & 0xFF); +} #endif int saveimage (object *arg) { @@ -393,21 +515,49 @@ int saveimage (object *arg) { } else file = SD.open("ULISP.IMG", O_RDWR | O_CREAT | O_TRUNC); if (!file) error(PSTR("Problem saving to SD card")); unsigned int imagesize = compactimage(&arg); - SDWritePtr(file, (uintptr_t)arg); + SDWriteInt(file, (uintptr_t)arg); SDWriteInt(file, imagesize); - SDWritePtr(file, (uintptr_t)GlobalEnv); - SDWritePtr(file, (uintptr_t)GCStack); + SDWriteInt(file, (uintptr_t)GlobalEnv); + SDWriteInt(file, (uintptr_t)GCStack); #if SYMBOLTABLESIZE > BUFFERSIZE - SDWritePtr(file, (uintptr_t)SymbolTop); + SDWriteInt(file, (uintptr_t)SymbolTop); for (int i=0; i FLASHSIZE) { + pfstring(PSTR("Error: Image size too large: "), pserial); + pint(imagesize, pserial); pln(pserial); + GCStack = NULL; + longjmp(exception, 1); + } + unsigned int addr = 0; + FlashBeginWrite(); + FlashWriteInt(&addr, (uintptr_t)arg); + FlashWriteInt(&addr, imagesize); + FlashWriteInt(&addr, (uintptr_t)GlobalEnv); + FlashWriteInt(&addr, (uintptr_t)GCStack); + #if SYMBOLTABLESIZE > BUFFERSIZE + FlashWriteInt(&addr, (uintptr_t)SymbolTop); + for (int i=0; i BUFFERSIZE - SymbolTop = (char *)SDReadPtr(file); + SymbolTop = (char *)SDReadInt(file); for (int i=0; i BUFFERSIZE + SymbolTop = (char *)FlashReadInt(); + for (int i=0; i>8; address = stream & 0xFF; } @@ -1008,6 +1188,12 @@ void checkanalogread (int pin) { if (!(pin>=14 && pin<=19)) error(PSTR("'analogread' invalid pin")); #elif defined(ARDUINO_SAMD_MKRZERO) if (!(pin>=15 && pin<=21)) error(PSTR("'analogread' invalid pin")); +#elif defined(ARDUINO_METRO_M4) + if (!(pin>=14 && pin<=21)) error(PSTR("'analogread' invalid pin")); +#elif defined(ARDUINO_ITSYBITSY_M4) + if (!(pin>=14 && pin<=19)) error(PSTR("'analogread' invalid pin")); +#elif defined(ARDUINO_FEATHER_M4) + if (!(pin>=14 && pin<=19)) error(PSTR("'analogread' invalid pin")); #elif defined(_VARIANT_BBC_MICROBIT_) if (!((pin>=0 && pin<=4) || pin==10)) error(PSTR("'analogread' invalid pin")); #endif @@ -1020,8 +1206,14 @@ void checkanalogwrite (int pin) { if (!((pin>=3 && pin<=6) || (pin>=8 && pin<=13) || pin==14)) error(PSTR("'analogwrite' invalid pin")); #elif defined(ARDUINO_SAMD_MKRZERO) if (!((pin>=0 && pin<=8) || pin==10 || pin==18 || pin==19)) error(PSTR("'analogwrite' invalid pin")); +#elif defined(ARDUINO_METRO_M4) + if (!(pin>=0 && pin<=15)) error(PSTR("'analogwrite' invalid pin")); +#elif defined(ARDUINO_ITSYBITSY_M4) + if (!(pin==0 || pin==1 || pin==4 || pin==5 || pin==7 || (pin>=9 && pin<=15) || pin==21 || pin==22)) error(PSTR("'analogwrite' invalid pin")); +#elif defined(ARDUINO_FEATHER_M4) + if (!(pin==0 || pin==1 || (pin>=4 && pin<=6) || (pin>=9 && pin<=13) || pin==14 || pin==15 || pin==17 || pin==21 || pin==22)) error(PSTR("'analogwrite' invalid pin")); #elif defined(_VARIANT_BBC_MICROBIT_) - error(PSTR("'analogwrite' not supported")); + if (!(pin>=0 && pin<=2)) error(PSTR("'analogwrite' invalid pin")); #endif } @@ -2320,7 +2512,9 @@ object *fn_round (object *args, object *env) { object *fn_char (object *args, object *env) { (void) env; - char c = nthchar(first(args), integer(second(args))); + object *arg = first(args); + if (!stringp(arg)) error2(arg, PSTR("is not a string")); + char c = nthchar(arg, integer(second(args))); if (c == 0) error(PSTR("'char' index out of range")); return character(c); } @@ -3875,7 +4069,7 @@ void setup () { initworkspace(); initenv(); initsleep(); - pfstring(PSTR("uLisp 2.3 "), pserial); pln(pserial); + pfstring(PSTR("uLisp 2.4 "), pserial); pln(pserial); } // Read/Evaluate/Print loop