;;;-*- Mode: Lisp; Package: cl-user -*- (in-package :cl-user) (defparameter *i2c-interface* '( #+avr-nano #" // I2C interface for AVR platforms, uses much less RAM than Arduino Wire #if defined(CPU_ATmega328P) uint8_t const TWI_SDA_PIN = 18; uint8_t const TWI_SCL_PIN = 19; #elif defined(CPU_ATmega1280) || defined(CPU_ATmega2560) uint8_t const TWI_SDA_PIN = 20; uint8_t const TWI_SCL_PIN = 21; #elif defined(CPU_ATmega644P) || defined(CPU_ATmega1284P) uint8_t const TWI_SDA_PIN = 17; uint8_t const TWI_SCL_PIN = 16; #elif defined(CPU_ATmega32U4) uint8_t const TWI_SDA_PIN = 6; uint8_t const TWI_SCL_PIN = 5; #endif #if defined(CPU_ATmega4809) || defined(CPU_ATtiny3227) || defined(CPU_AVR64DD28) uint32_t const FREQUENCY = 400000L; // Hardware I2C clock in Hz uint32_t const T_RISE = 300L; // Rise time #else uint32_t const F_TWI = 400000L; // Hardware I2C clock in Hz uint8_t const TWSR_MTX_DATA_ACK = 0x28; uint8_t const TWSR_MTX_ADR_ACK = 0x18; uint8_t const TWSR_MRX_ADR_ACK = 0x40; uint8_t const TWSR_START = 0x08; uint8_t const TWSR_REP_START = 0x10; uint8_t const I2C_READ = 1; uint8_t const I2C_WRITE = 0; #endif void I2Cinit (bool enablePullup) { #if defined(CPU_ATmega4809) || defined(CPU_ATtiny3227) || defined(CPU_AVR64DD28) #if defined(CPU_ATmega4809) if (enablePullup) { pinMode(SDA, INPUT_PULLUP); pinMode(SCL, INPUT_PULLUP); } #else (void) enablePullup; #endif uint32_t baud = ((F_CPU/FREQUENCY) - (((F_CPU*T_RISE)/1000)/1000)/1000 - 10)/2; TWI0.MBAUD = (uint8_t)baud; TWI0.MCTRLA = TWI_ENABLE_bm; // Enable as master, no interrupts TWI0.MSTATUS = TWI_BUSSTATE_IDLE_gc; #else TWSR = 0; // no prescaler TWBR = (F_CPU/F_TWI - 16)/2; // set bit rate factor if (enablePullup) { digitalWrite(SDA, HIGH); digitalWrite(SCL, HIGH); } #endif } int I2Cread () { #if defined(CPU_ATmega4809) || defined(CPU_ATtiny3227) || defined(CPU_AVR64DD28) if (I2Ccount != 0) I2Ccount--; while (!(TWI0.MSTATUS & TWI_RIF_bm)); // Wait for read interrupt flag uint8_t data = TWI0.MDATA; // Check slave sent ACK? if (I2Ccount != 0) TWI0.MCTRLB = TWI_MCMD_RECVTRANS_gc; // ACK = more bytes to read else TWI0.MCTRLB = TWI_ACKACT_NACK_gc; // Send NAK return data; #else if (I2Ccount != 0) I2Ccount--; TWCR = 1<begin(); } int I2Cread (TwoWire *port) { return port->read(); } void I2Cwrite (TwoWire *port, uint8_t data) { port->write(data); } bool I2Cstart (TwoWire *port, uint8_t address, uint8_t read) { int ok = true; if (read == 0) { port->beginTransmission(address); ok = (port->endTransmission(true) == 0); port->beginTransmission(address); } else port->requestFrom(address, I2Ccount); return ok; } bool I2Crestart (TwoWire *port, uint8_t address, uint8_t read) { int error = (port->endTransmission(false) != 0); if (read == 0) port->beginTransmission(address); else port->requestFrom(address, I2Ccount); return error ? false : true; } void I2Cstop (TwoWire *port, uint8_t read) { if (read == 0) port->endTransmission(); // Check for error? // Release pins port->end(); }"# #-(or avr avr-nano badge arm esp) #" // I2C interface for one port, using Arduino Wire void I2Cinit (bool enablePullup) { (void) enablePullup; Wire.begin(); } int I2Cread () { return Wire.read(); } void I2Cwrite (uint8_t data) { Wire.write(data); } bool I2Cstart (uint8_t address, uint8_t read) { int ok = true; if (read == 0) { Wire.beginTransmission(address); ok = (Wire.endTransmission(true) == 0); Wire.beginTransmission(address); } else Wire.requestFrom(address, I2Ccount); return ok; } bool I2Crestart (uint8_t address, uint8_t read) { int error = (Wire.endTransmission(false) != 0); if (read == 0) Wire.beginTransmission(address); else Wire.requestFrom(address, I2Ccount); return error ? false : true; } void I2Cstop (uint8_t read) { if (read == 0) Wire.endTransmission(); // Check for error? }"# #+badge #" // I2C interface for AVR platforms, uses much less RAM than Arduino Wire uint8_t const TWI_SDA_PIN = 17; uint8_t const TWI_SCL_PIN = 16; uint32_t const F_TWI = 400000L; // Hardware I2C clock in Hz uint8_t const TWSR_MTX_DATA_ACK = 0x28; uint8_t const TWSR_MTX_ADR_ACK = 0x18; uint8_t const TWSR_MRX_ADR_ACK = 0x40; uint8_t const TWSR_START = 0x08; uint8_t const TWSR_REP_START = 0x10; uint8_t const I2C_READ = 1; uint8_t const I2C_WRITE = 0; void I2Cinit (bool enablePullup) { TWSR = 0; // no prescaler TWBR = (F_CPU/F_TWI - 16)/2; // set bit rate factor if (enablePullup) { digitalWrite(TWI_SDA_PIN, HIGH); digitalWrite(TWI_SCL_PIN, HIGH); } } int I2Cread () { if (I2Ccount != 0) I2Ccount--; TWCR = 1<>8; address = stream & 0xFF; } if (streamtype == I2CSTREAM) gfun = (gfun_t)I2Cread; else if (streamtype == SPISTREAM) gfun = spiread; else if (streamtype == SERIALSTREAM) { if (address == 0) gfun = gserial; #if defined(CPU_ATmega1284P) || defined(CPU_AVR128DX48) else if (address == 1) gfun = serial1read; #elif defined(CPU_ATmega2560) else if (address == 1) gfun = serial1read; else if (address == 2) gfun = serial2read; else if (address == 3) gfun = serial3read; #endif } #if defined(sdcardsupport) else if (streamtype == SDSTREAM) gfun = (gfun_t)SDread; #endif else error2(unknownstreamtype); return gfun; } inline void spiwrite (char c) { SPI.transfer(c); } #if defined(CPU_ATmega1284P) || defined(CPU_AVR128DX48) inline void serial1write (char c) { Serial1.write(c); } #elif defined(CPU_ATmega2560) inline void serial1write (char c) { Serial1.write(c); } inline void serial2write (char c) { Serial2.write(c); } inline void serial3write (char c) { Serial3.write(c); } #endif #if defined(sdcardsupport) inline void SDwrite (char c) { int w = SDpfile.write(c); if (w != 1) { Context = NIL; error2(PSTR("failed to write to file")); } } #endif pfun_t pstreamfun (object *args) { int streamtype = SERIALSTREAM; int address = 0; pfun_t pfun = pserial; if (args != NULL && first(args) != NULL) { int stream = isstream(first(args)); streamtype = stream>>8; address = stream & 0xFF; } if (streamtype == I2CSTREAM) pfun = (pfun_t)I2Cwrite; else if (streamtype == SPISTREAM) pfun = spiwrite; else if (streamtype == SERIALSTREAM) { if (address == 0) pfun = pserial; #if defined(CPU_ATmega1284P) || defined(CPU_AVR128DX48) else if (address == 1) pfun = serial1write; #elif defined(CPU_ATmega2560) else if (address == 1) pfun = serial1write; else if (address == 2) pfun = serial2write; else if (address == 3) pfun = serial3write; #endif } else if (streamtype == STRINGSTREAM) { pfun = pstr; } #if defined(sdcardsupport) else if (streamtype == SDSTREAM) pfun = (pfun_t)SDwrite; #endif else error2(unknownstreamtype); return pfun; }"# #+arm #" // Streams // Simplify board differences #if defined(ARDUINO_NRF52840_CLUE) || defined(ARDUINO_GRAND_CENTRAL_M4) \ || defined(ARDUINO_PYBADGE_M4) || defined(ARDUINO_PYGAMER_M4) || defined(ARDUINO_TEENSY40) \ || defined(ARDUINO_TEENSY41) || defined(ARDUINO_RASPBERRY_PI_PICO) \ || defined(ARDUINO_RASPBERRY_PI_PICO_W) || defined(ARDUINO_RASPBERRY_PI_PICO_2) \ || defined(ARDUINO_PIMORONI_PICO_PLUS_2) #define ULISP_SPI1 #endif #if defined(ARDUINO_WIO_TERMINAL) || defined(ARDUINO_BBC_MICROBIT_V2) \ || defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) || defined(MAX32620) \ || defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_RASPBERRY_PI_PICO_W) \ || defined(ARDUINO_ADAFRUIT_QTPY_RP2040) || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) \ || defined(ARDUINO_RASPBERRY_PI_PICO_2) || defined(ARDUINO_PIMORONI_PICO_PLUS_2) \ || defined(ARDUINO_GRAND_CENTRAL_M4) || defined(ARDUINO_NRF52840_CIRCUITPLAY) #define ULISP_I2C1 #endif #if defined(ARDUINO_SAM_DUE) || defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) #define ULISP_SERIAL3 #elif defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_RASPBERRY_PI_PICO_W) \ || defined(ARDUINO_RASPBERRY_PI_PICO_2) || defined(ARDUINO_PIMORONI_PICO_PLUS_2) #define ULISP_SERIAL2 #elif !defined(CPU_NRF51822) && !defined(CPU_NRF52833) && !defined(ARDUINO_FEATHER_F405) #define ULISP_SERIAL1 #endif #if defined(ARDUINO_RASPBERRY_PI_PICO_W) || defined(ARDUINO_UNOWIFIR4) #define ULISP_WIFI #endif inline int spiread () { return SPI.transfer(0); } #if defined(ULISP_SPI1) inline int spi1read () { return SPI1.transfer(0); } #endif inline int i2cread () { return I2Cread(&Wire); } #if defined(ULISP_I2C1) inline int i2c1read () { return I2Cread(&Wire1); } #endif #if defined(ULISP_SERIAL3) inline int serial3read () { while (!Serial3.available()) testescape(); return Serial3.read(); } #endif #if defined(ULISP_SERIAL3) || defined(ULISP_SERIAL2) inline int serial2read () { while (!Serial2.available()) testescape(); return Serial2.read(); } #endif #if defined(ULISP_SERIAL3) || defined(ULISP_SERIAL2) || defined(ULISP_SERIAL1) inline int serial1read () { while (!Serial1.available()) testescape(); return Serial1.read(); } #endif #if defined(sdcardsupport) File SDpfile, SDgfile; inline int SDread () { if (LastChar) { char temp = LastChar; LastChar = 0; return temp; } return SDgfile.read(); } #endif #if defined(ULISP_WIFI) WiFiClient client; WiFiServer server(80); inline int WiFiread () { if (LastChar) { char temp = LastChar; LastChar = 0; return temp; } while (!client.available()) testescape(); return client.read(); } #endif void serialbegin (int address, int baud) { #if defined(ULISP_SERIAL3) if (address == 1) Serial1.begin((long)baud*100); else if (address == 2) Serial2.begin((long)baud*100); else if (address == 3) Serial3.begin((long)baud*100); #elif defined(ULISP_SERIAL2) if (address == 1) Serial1.begin((long)baud*100); else if (address == 2) Serial2.begin((long)baud*100); #elif defined(ULISP_SERIAL1) if (address == 1) Serial1.begin((long)baud*100); #else (void) baud; if (false); #endif else error("port not supported", number(address)); } void serialend (int address) { #if defined(ULISP_SERIAL3) if (address == 1) {Serial1.flush(); Serial1.end(); } else if (address == 2) {Serial2.flush(); Serial2.end(); } else if (address == 3) {Serial3.flush(); Serial3.end(); } #elif defined(ULISP_SERIAL2) if (address == 1) {Serial1.flush(); Serial1.end(); } else if (address == 2) {Serial2.flush(); Serial2.end(); } #elif defined(ULISP_SERIAL1) if (address == 1) {Serial1.flush(); Serial1.end(); } #else if (false); #endif else error("port not supported", number(address)); } gfun_t gstreamfun (object *args) { int streamtype = SERIALSTREAM; int address = 0; gfun_t gfun = gserial; if (args != NULL) { int stream = isstream(first(args)); streamtype = stream>>8; address = stream & 0xFF; } if (streamtype == I2CSTREAM) { if (address < 128) gfun = i2cread; #if defined(ULISP_I2C1) else gfun = i2c1read; #endif } else if (streamtype == SPISTREAM) { if (address < 128) gfun = spiread; #if defined(ULISP_SPI1) else gfun = spi1read; #endif } else if (streamtype == SERIALSTREAM) { if (address == 0) gfun = gserial; #if defined(ULISP_SERIAL3) else if (address == 1) gfun = serial1read; else if (address == 2) gfun = serial2read; else if (address == 3) gfun = serial3read; #elif defined(ULISP_SERIAL2) else if (address == 1) gfun = serial1read; else if (address == 2) gfun = serial2read; #elif defined(ULISP_SERIAL1) else if (address == 1) gfun = serial1read; #endif } #if defined(sdcardsupport) else if (streamtype == SDSTREAM) gfun = (gfun_t)SDread; #endif #if defined(ULISP_WIFI) else if (streamtype == WIFISTREAM) gfun = (gfun_t)WiFiread; #endif else error2("unknown stream type"); return gfun; } inline void spiwrite (char c) { SPI.transfer(c); } #if defined(ULISP_SPI1) inline void spi1write (char c) { SPI1.transfer(c); } #endif inline void i2cwrite (char c) { I2Cwrite(&Wire, c); } #if defined(ULISP_I2C1) inline void i2c1write (char c) { I2Cwrite(&Wire1, c); } #endif #if defined(ULISP_SERIAL3) inline void serial1write (char c) { Serial1.write(c); } inline void serial2write (char c) { Serial2.write(c); } inline void serial3write (char c) { Serial3.write(c); } #elif defined(ULISP_SERIAL2) inline void serial2write (char c) { Serial2.write(c); } inline void serial1write (char c) { Serial1.write(c); } #elif defined(ULISP_SERIAL1) inline void serial1write (char c) { Serial1.write(c); } #endif #if defined(sdcardsupport) inline void SDwrite (char c) { SDpfile.write(uint8_t(c)); } // Fix for RP2040 #endif #if defined(ULISP_WIFI) inline void WiFiwrite (char c) { client.write(c); } #endif #if defined(gfxsupport) inline void gfxwrite (char c) { tft.write(c); } #endif pfun_t pstreamfun (object *args) { int streamtype = SERIALSTREAM; int address = 0; pfun_t pfun = pserial; if (args != NULL && first(args) != NULL) { int stream = isstream(first(args)); streamtype = stream>>8; address = stream & 0xFF; } if (streamtype == I2CSTREAM) { if (address < 128) pfun = i2cwrite; #if defined(ULISP_I2C1) else pfun = i2c1write; #endif } else if (streamtype == SPISTREAM) { if (address < 128) pfun = spiwrite; #if defined(ULISP_SPI1) else pfun = spi1write; #endif } else if (streamtype == SERIALSTREAM) { if (address == 0) pfun = pserial; #if defined(ULISP_SERIAL3) else if (address == 1) pfun = serial1write; else if (address == 2) pfun = serial2write; else if (address == 3) pfun = serial3write; #elif defined(ULISP_SERIAL2) else if (address == 1) pfun = serial1write; else if (address == 2) pfun = serial2write; #elif defined(ULISP_SERIAL1) else if (address == 1) pfun = serial1write; #endif } else if (streamtype == STRINGSTREAM) { pfun = pstr; } #if defined(sdcardsupport) else if (streamtype == SDSTREAM) pfun = (pfun_t)SDwrite; #endif #if defined(gfxsupport) else if (streamtype == GFXSTREAM) pfun = (pfun_t)gfxwrite; #endif #if defined(ULISP_WIFI) else if (streamtype == WIFISTREAM) pfun = (pfun_t)WiFiwrite; #endif else error2("unknown stream type"); return pfun; }"# #+esp #" // Streams // Simplify board differences #if defined(ARDUINO_ADAFRUIT_QTPY_ESP32S2) #define ULISP_I2C1 #endif inline int spiread () { return SPI.transfer(0); } inline int i2cread () { return I2Cread(&Wire); } #if defined(ULISP_I2C1) inline int i2c1read () { return I2Cread(&Wire1); } #endif inline int serial1read () { while (!Serial1.available()) testescape(); return Serial1.read(); } #if defined(sdcardsupport) File SDpfile, SDgfile; inline int SDread () { if (LastChar) { char temp = LastChar; LastChar = 0; return temp; } return SDgfile.read(); } #endif WiFiClient client; WiFiServer server(80); inline int WiFiread () { if (LastChar) { char temp = LastChar; LastChar = 0; return temp; } while (!client.available()) testescape(); return client.read(); } void serialbegin (int address, int baud) { if (address == 1) Serial1.begin((long)baud*100); else error(PSTR("port not supported"), number(address)); } void serialend (int address) { if (address == 1) {Serial1.flush(); Serial1.end(); } else error(PSTR("port not supported"), number(address)); } gfun_t gstreamfun (object *args) { int streamtype = SERIALSTREAM; int address = 0; gfun_t gfun = gserial; if (args != NULL) { int stream = isstream(first(args)); streamtype = stream>>8; address = stream & 0xFF; } if (streamtype == I2CSTREAM) { if (address < 128) gfun = i2cread; #if defined(ULISP_I2C1) else gfun = i2c1read; #endif } else if (streamtype == SPISTREAM) gfun = spiread; else if (streamtype == SERIALSTREAM) { if (address == 0) gfun = gserial; else if (address == 1) gfun = serial1read; } #if defined(sdcardsupport) else if (streamtype == SDSTREAM) gfun = (gfun_t)SDread; #endif else if (streamtype == WIFISTREAM) gfun = (gfun_t)WiFiread; else error2(PSTR("unknown stream type")); return gfun; } inline void spiwrite (char c) { SPI.transfer(c); } inline void i2cwrite (char c) { I2Cwrite(&Wire, c); } #if defined(ULISP_I2C1) inline void i2c1write (char c) { I2Cwrite(&Wire1, c); } #endif inline void serial1write (char c) { Serial1.write(c); } inline void WiFiwrite (char c) { client.write(c); } #if defined(sdcardsupport) inline void SDwrite (char c) { SDpfile.write(c); } #endif #if defined(gfxsupport) inline void gfxwrite (char c) { tft.write(c); } #endif pfun_t pstreamfun (object *args) { int streamtype = SERIALSTREAM; int address = 0; pfun_t pfun = pserial; if (args != NULL && first(args) != NULL) { int stream = isstream(first(args)); streamtype = stream>>8; address = stream & 0xFF; } if (streamtype == I2CSTREAM) { if (address < 128) pfun = i2cwrite; #if defined(ULISP_I2C1) else pfun = i2c1write; #endif } else if (streamtype == SPISTREAM) pfun = spiwrite; else if (streamtype == SERIALSTREAM) { if (address == 0) pfun = pserial; else if (address == 1) pfun = serial1write; } else if (streamtype == STRINGSTREAM) { pfun = pstr; } #if defined(sdcardsupport) else if (streamtype == SDSTREAM) pfun = (pfun_t)SDwrite; #endif #if defined(gfxsupport) else if (streamtype == GFXSTREAM) pfun = (pfun_t)gfxwrite; #endif else if (streamtype == WIFISTREAM) pfun = (pfun_t)WiFiwrite; else error2(PSTR("unknown stream type")); return pfun; }"# #+riscv #" // Streams inline int spiread () { return SPI.transfer(0); } #if defined(BOARD_SIPEED_MAIX_DUINO) inline int serial1read () { while (!Serial1.available()) testescape(); return Serial1.read(); } inline int serial2read () { while (!Serial2.available()) testescape(); return Serial2.read(); } inline int serial3read () { while (!Serial3.available()) testescape(); return Serial3.read(); } #endif #if defined(sdcardsupport) File SDpfile, SDgfile; inline int SDread () { if (LastChar) { char temp = LastChar; LastChar = 0; return temp; } return SDgfile.read(); } #endif void serialbegin (int address, int baud) { #if defined(BOARD_SIPEED_MAIX_DUINO) if (address == 1) Serial1.begin((long)baud*100); else if (address == 2) Serial2.begin((long)baud*100); else if (address == 3) Serial3.begin((long)baud*100); else error(PSTR("port not supported"), number(address)); #endif } void serialend (int address) { #if defined(BOARD_SIPEED_MAIX_DUINO) if (address == 1) {Serial1.flush(); Serial1.end(); } else if (address == 2) {Serial2.flush(); Serial2.end(); } else if (address == 3) {Serial3.flush(); Serial3.end(); } #endif } gfun_t gstreamfun (object *args) { int streamtype = SERIALSTREAM; int address = 0; gfun_t gfun = gserial; if (args != NULL) { int stream = isstream(first(args)); streamtype = stream>>8; address = stream & 0xFF; } if (streamtype == I2CSTREAM) gfun = (gfun_t)I2Cread; else if (streamtype == SPISTREAM) { if (address < 128) gfun = spiread; } else if (streamtype == SERIALSTREAM) { if (address == 0) gfun = gserial; #if defined(BOARD_SIPEED_MAIX_DUINO) else if (address == 1) gfun = serial1read; else if (address == 2) gfun = serial2read; else if (address == 3) gfun = serial3read; #endif } #if defined(sdcardsupport) else if (streamtype == SDSTREAM) gfun = (gfun_t)SDread; #endif else error2(PSTR("unknown stream type")); return gfun; } inline void spiwrite (char c) { SPI.transfer(c); } #if defined(BOARD_SIPEED_MAIX_DUINO) inline void serial1write (char c) { Serial1.write(c); } inline void serial2write (char c) { Serial2.write(c); } inline void serial3write (char c) { Serial3.write(c); } #endif #if defined(sdcardsupport) inline void SDwrite (char c) { SDpfile.write(c); } #endif #if defined(gfxsupport) inline void gfxwrite (char c) { tft.write(c); } #endif pfun_t pstreamfun (object *args) { int streamtype = SERIALSTREAM; int address = 0; pfun_t pfun = pserial; if (args != NULL && first(args) != NULL) { int stream = isstream(first(args)); streamtype = stream>>8; address = stream & 0xFF; } if (streamtype == I2CSTREAM) pfun = (pfun_t)I2Cwrite; else if (streamtype == SPISTREAM) { if (address < 128) pfun = spiwrite; } else if (streamtype == SERIALSTREAM) { if (address == 0) pfun = pserial; #if defined(BOARD_SIPEED_MAIX_DUINO) else if (address == 1) pfun = serial1write; else if (address == 2) pfun = serial2write; else if (address == 3) pfun = serial3write; #endif } else if (streamtype == STRINGSTREAM) { pfun = pstr; } #if defined(sdcardsupport) else if (streamtype == SDSTREAM) pfun = (pfun_t)SDwrite; #endif #if defined(gfxsupport) else if (streamtype == GFXSTREAM) pfun = (pfun_t)gfxwrite; #endif else error2(PSTR("unknown stream type")); return pfun; }"#))