984 lines
30 KiB
Common Lisp
984 lines
30 KiB
Common Lisp
;;;-*- 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<<TWINT | 1<<TWEN | ((I2Ccount == 0) ? 0 : (1<<TWEA));
|
|
while (!(TWCR & 1<<TWINT));
|
|
return TWDR;
|
|
#endif
|
|
}
|
|
|
|
bool I2Cwrite (uint8_t data) {
|
|
#if defined(CPU_ATmega4809) || defined(CPU_ATtiny3227) || defined(CPU_AVR64DD28)
|
|
TWI0.MCTRLB = TWI_MCMD_RECVTRANS_gc; // Prime transaction
|
|
TWI0.MDATA = data; // Send data
|
|
while (!(TWI0.MSTATUS & TWI_WIF_bm)); // Wait for write to complete
|
|
|
|
if (TWI0.MSTATUS & (TWI_ARBLOST_bm | TWI_BUSERR_bm)) return false; // Fails if bus error or arblost
|
|
return !(TWI0.MSTATUS & TWI_RXACK_bm); // Returns true if slave gave an ACK
|
|
#else
|
|
TWDR = data;
|
|
TWCR = 1<<TWINT | 1 << TWEN;
|
|
while (!(TWCR & 1<<TWINT));
|
|
return (TWSR & 0xF8) == TWSR_MTX_DATA_ACK;
|
|
#endif
|
|
}
|
|
|
|
bool I2Cstart (uint8_t address, uint8_t read) {
|
|
#if defined(CPU_ATmega4809) || defined(CPU_ATtiny3227) || defined(CPU_AVR64DD28)
|
|
TWI0.MADDR = address<<1 | read; // Send START condition
|
|
while (!(TWI0.MSTATUS & (TWI_WIF_bm | TWI_RIF_bm))); // Wait for write or read interrupt flag
|
|
if (TWI0.MSTATUS & TWI_ARBLOST_bm) { // Arbitration lost or bus error
|
|
while (!((TWI0.MSTATUS & TWI_BUSSTATE_gm) == TWI_BUSSTATE_IDLE_gc)); // Wait for bus to return to idle state
|
|
return false;
|
|
} else if (TWI0.MSTATUS & TWI_RXACK_bm) { // Address not acknowledged by client
|
|
TWI0.MCTRLB |= TWI_MCMD_STOP_gc; // Send stop condition
|
|
while (!((TWI0.MSTATUS & TWI_BUSSTATE_gm) == TWI_BUSSTATE_IDLE_gc)); // Wait for bus to return to idle state
|
|
return false;
|
|
}
|
|
return true; // Return true if slave gave an ACK
|
|
#else
|
|
uint8_t addressRW = address<<1 | read;
|
|
TWCR = 1<<TWINT | 1<<TWSTA | 1<<TWEN; // Send START condition
|
|
while (!(TWCR & 1<<TWINT));
|
|
if ((TWSR & 0xF8) != TWSR_START && (TWSR & 0xF8) != TWSR_REP_START) return false;
|
|
TWDR = addressRW; // send device address and direction
|
|
TWCR = 1<<TWINT | 1<<TWEN;
|
|
while (!(TWCR & 1<<TWINT));
|
|
if (addressRW & I2C_READ) return (TWSR & 0xF8) == TWSR_MRX_ADR_ACK;
|
|
else return (TWSR & 0xF8) == TWSR_MTX_ADR_ACK;
|
|
#endif
|
|
}
|
|
|
|
bool I2Crestart (uint8_t address, uint8_t read) {
|
|
return I2Cstart(address, read);
|
|
}
|
|
|
|
void I2Cstop (uint8_t read) {
|
|
#if defined(CPU_ATmega4809) || defined(CPU_ATtiny3227) || defined(CPU_AVR64DD28)
|
|
(void) read;
|
|
TWI0.MCTRLB |= TWI_MCMD_STOP_gc; // Send STOP
|
|
while (!((TWI0.MSTATUS & TWI_BUSSTATE_gm) == TWI_BUSSTATE_IDLE_gc)); // Wait for bus to return to idle state
|
|
#else
|
|
(void) read;
|
|
TWCR = 1<<TWINT | 1<<TWEN | 1<<TWSTO;
|
|
while (TWCR & 1<<TWSTO); // wait until stop and bus released
|
|
#endif
|
|
}"#
|
|
|
|
#+avr
|
|
#"
|
|
// I2C interface for AVR platforms, uses much less RAM than Arduino Wire
|
|
|
|
#if defined(CPU_AVR128DX48)
|
|
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_AVR128DX48)
|
|
#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_AVR128DX48)
|
|
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<<TWINT | 1<<TWEN | ((I2Ccount == 0) ? 0 : (1<<TWEA));
|
|
while (!(TWCR & 1<<TWINT));
|
|
return TWDR;
|
|
#endif
|
|
}
|
|
|
|
bool I2Cwrite (uint8_t data) {
|
|
#if defined(CPU_AVR128DX48)
|
|
TWI0.MCTRLB = TWI_MCMD_RECVTRANS_gc; // Prime transaction
|
|
TWI0.MDATA = data; // Send data
|
|
while (!(TWI0.MSTATUS & TWI_WIF_bm)); // Wait for write to complete
|
|
|
|
if (TWI0.MSTATUS & (TWI_ARBLOST_bm | TWI_BUSERR_bm)) return false; // Fails if bus error or arblost
|
|
return !(TWI0.MSTATUS & TWI_RXACK_bm); // Returns true if slave gave an ACK
|
|
#else
|
|
TWDR = data;
|
|
TWCR = 1<<TWINT | 1 << TWEN;
|
|
while (!(TWCR & 1<<TWINT));
|
|
return (TWSR & 0xF8) == TWSR_MTX_DATA_ACK;
|
|
#endif
|
|
}
|
|
|
|
bool I2Cstart (uint8_t address, uint8_t read) {
|
|
#if defined(CPU_AVR128DX48)
|
|
TWI0.MADDR = address<<1 | read; // Send START condition
|
|
while (!(TWI0.MSTATUS & (TWI_WIF_bm | TWI_RIF_bm))); // Wait for write or read interrupt flag
|
|
if (TWI0.MSTATUS & TWI_ARBLOST_bm) { // Arbitration lost or bus error
|
|
while (!((TWI0.MSTATUS & TWI_BUSSTATE_gm) == TWI_BUSSTATE_IDLE_gc)); // Wait for bus to return to idle state
|
|
return false;
|
|
} else if (TWI0.MSTATUS & TWI_RXACK_bm) { // Address not acknowledged by client
|
|
TWI0.MCTRLB |= TWI_MCMD_STOP_gc; // Send stop condition
|
|
while (!((TWI0.MSTATUS & TWI_BUSSTATE_gm) == TWI_BUSSTATE_IDLE_gc)); // Wait for bus to return to idle state
|
|
return false;
|
|
}
|
|
return true; // Return true if slave gave an ACK
|
|
#else
|
|
uint8_t addressRW = address<<1 | read;
|
|
TWCR = 1<<TWINT | 1<<TWSTA | 1<<TWEN; // Send START condition
|
|
while (!(TWCR & 1<<TWINT));
|
|
if ((TWSR & 0xF8) != TWSR_START && (TWSR & 0xF8) != TWSR_REP_START) return false;
|
|
TWDR = addressRW; // send device address and direction
|
|
TWCR = 1<<TWINT | 1<<TWEN;
|
|
while (!(TWCR & 1<<TWINT));
|
|
if (addressRW & I2C_READ) return (TWSR & 0xF8) == TWSR_MRX_ADR_ACK;
|
|
else return (TWSR & 0xF8) == TWSR_MTX_ADR_ACK;
|
|
#endif
|
|
}
|
|
|
|
bool I2Crestart (uint8_t address, uint8_t read) {
|
|
return I2Cstart(address, read);
|
|
}
|
|
|
|
void I2Cstop (uint8_t read) {
|
|
#if defined(CPU_AVR128DX48)
|
|
(void) read;
|
|
TWI0.MCTRLB |= TWI_MCMD_STOP_gc; // Send STOP
|
|
while (!((TWI0.MSTATUS & TWI_BUSSTATE_gm) == TWI_BUSSTATE_IDLE_gc)); // Wait for bus to return to idle state
|
|
#else
|
|
(void) read;
|
|
TWCR = 1<<TWINT | 1<<TWEN | 1<<TWSTO;
|
|
while (TWCR & 1<<TWSTO); // wait until stop and bus released
|
|
#endif
|
|
}"#
|
|
|
|
#+(or arm esp)
|
|
#"
|
|
// I2C interface for up to two ports, using Arduino Wire
|
|
|
|
void I2Cinit (TwoWire *port, bool enablePullup) {
|
|
(void) enablePullup;
|
|
port->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<<TWINT | 1<<TWEN | ((I2Ccount == 0) ? 0 : (1<<TWEA));
|
|
while (!(TWCR & 1<<TWINT));
|
|
return TWDR;
|
|
}
|
|
|
|
bool I2Cwrite (uint8_t data) {
|
|
TWDR = data;
|
|
TWCR = 1<<TWINT | 1 << TWEN;
|
|
while (!(TWCR & 1<<TWINT));
|
|
return (TWSR & 0xF8) == TWSR_MTX_DATA_ACK;
|
|
}
|
|
|
|
bool I2Cstart (uint8_t address, uint8_t read) {
|
|
uint8_t addressRW = address<<1 | read;
|
|
TWCR = 1<<TWINT | 1<<TWSTA | 1<<TWEN; // Send START condition
|
|
while (!(TWCR & 1<<TWINT));
|
|
if ((TWSR & 0xF8) != TWSR_START && (TWSR & 0xF8) != TWSR_REP_START) return false;
|
|
TWDR = addressRW; // send device address and direction
|
|
TWCR = 1<<TWINT | 1<<TWEN;
|
|
while (!(TWCR & 1<<TWINT));
|
|
if (addressRW & I2C_READ) return (TWSR & 0xF8) == TWSR_MRX_ADR_ACK;
|
|
else return (TWSR & 0xF8) == TWSR_MTX_ADR_ACK;
|
|
}
|
|
|
|
bool I2Crestart (uint8_t address, uint8_t read) {
|
|
return I2Cstart(address, read);
|
|
}
|
|
|
|
void I2Cstop (uint8_t read) {
|
|
(void) read;
|
|
TWCR = 1<<TWINT | 1<<TWEN | 1<<TWSTO;
|
|
while (TWCR & 1<<TWSTO); // wait until stop and bus released
|
|
}"#))
|
|
|
|
(defparameter *stream-interface* '(
|
|
|
|
#+avr-nano
|
|
#"
|
|
// Streams
|
|
|
|
inline int spiread () { return SPI.transfer(0); }
|
|
#if defined(CPU_AVR64DD28)
|
|
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
|
|
|
|
void serialbegin (int address, int baud) {
|
|
(void) address; (void) baud;
|
|
error(PSTR("port not supported"), number(address));
|
|
}"#
|
|
|
|
#+avr
|
|
#"
|
|
// Streams
|
|
|
|
inline int spiread () { return SPI.transfer(0); }
|
|
#if defined(CPU_ATmega1284P) || defined(CPU_AVR128DX48)
|
|
inline int serial1read () { while (!Serial1.available()) testescape(); return Serial1.read(); }
|
|
#elif defined(CPU_ATmega2560)
|
|
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) {
|
|
(void) address; (void) baud;
|
|
}"#
|
|
|
|
#+(or avr avr-nano)
|
|
#"
|
|
void serialend (int address) {
|
|
(void) 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) 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;
|
|
}"#)) |