LambLisp 01 Red Fox Alpha
From AI to Actuator
Loading...
Searching...
No Matches
LLArduino – LambLisp's own Arduino API

Classes

struct  LLArduinoBackend
struct  LLGpiodPin
struct  LLGpiodLine

Macros

#define LL_LLA_NPINS   256

Functions

bool ll_gpiod_available ()
void ll_gpiod_pin_mode (int, int)
void ll_gpiod_digital_write (int, int)
int ll_gpiod_digital_read (int)
void ll_gpiod_analog_write (int, int)
int ll_gpiod_analog_read (int)
void ll_gpiod_tone_on (int, unsigned int)
void ll_gpiod_tone_off (int)
int ll_gpiod_pin_mode_get (int)
int ll_gpiod_pin_duty_get (int)
int ll_gpiod_pin_tone_get (int)
int ll_gpiod_npins ()
void pinMode (int pin, int mode)
void digitalWrite (int pin, int val)
int digitalRead (int pin)
void analogWrite (int pin, int val)
int analogRead (int pin)
void tone (int pin, unsigned int freq)
void tone (int pin, unsigned int freq, unsigned long dur)
void noTone (int pin)
int ll_llarduino_pin_mode (int pin)
int ll_llarduino_pin_duty (int pin)
int ll_llarduino_pin_tone (int pin)
int ll_llarduino_npins ()
const char * ll_llarduino_backend ()
virtual size_t Print::write (const uint8_t *buf, size_t n)
size_t Print::write (const char *s)
size_t Print::print (char c)
size_t Print::print (const char *s)
size_t Print::print (const String &s)
size_t Print::print (long n, int base=10)
size_t Print::print (int n, int base=10)
size_t Print::print (unsigned long n, int base=10)
size_t Print::print (double v, int digits=2)
size_t Print::println ()
size_t Print::println (char c)
size_t Print::println (const char *s)
size_t Print::println (const String &s)
size_t Print::println (int n, int base=10)
size_t Print::println (long n, int base=10)
size_t Print::println (unsigned long n, int base=10)
size_t Print::println (double v, int digits=2)
size_t Print::printf (const char *fmt,...) CHECKPRINTF_pos2
void LLArduinoSerial::begin (unsigned long baud=115200)
void LLArduinoSerial::end ()
int LLArduinoSerial::availableForWrite ()
void LLArduinoSerial::flush () override
size_t LLArduinoSerial::write (uint8_t c) override
int LLArduinoSerial::available () override
int LLArduinoSerial::read () override
int LLArduinoSerial::peek () override

Variables

LLArduinoSerial Serial

Detailed Description

The NULL (simulated) backend: pin state in memory, no hardware.

Print / Stream / Serial – REAL character I/O, not a simulation.

libgpiod backend – REAL pins on a Raspberry Pi or Jetson.

This is the backend that runs where there is no GPIO to drive – a developer laptop, an x86 host, a container – so that the 26 commonio procedures (pinMode, digitalWrite, digitalRead, analogRead/Write, tone, ...) can be CALLED AND ASSERTED ON without a board.

WHY THAT MATTERS HERE, concretely: of the seven boards where commonio is compiled in, most are unavailable most of the time – shared with other sessions, unplugged to save power, or in a failed USB port. On one occasion exactly ONE of seven was reachable. Anything that can only be tested with a board in hand is, in practice, tested rarely; a recent Arduino 3.x WiFi ( regression) reached customers as a boot loop for that reason.

IT ANNOUNCES ITSELF AS SIMULATED. A simulated backend is honest only while nobody can mistake it for hardware, so llarduino-backend returns 'null here and the loopback semantics are documented below rather than left to be discovered. The rule – never invent a plausible sensor reading – still binds the REAL backends: on a Pi or Jetson, analogRead has no ADC behind it and must say so instead of returning a number. Here every value is one the caller itself wrote, which is a different thing from a fabricated measurement.

This is what makes LLArduino a port rather than a simulation: (digitalWrite 18 1) in Scheme drives an actual header pin. Selected at RUNTIME (see the dispatch table in ll_llarduino_null.cpp) because whether real pins exist is a property of the MACHINE, not the build – the same aarch64 binary runs on a Jetson with a 40-pin header and on a box whose gpiochips are not header pins at all.

libgpiod v1 API, PINNED DELIBERATELY. v1.6.3 is what both this workstation and the Jetson carry, and libgpiod v2 is SOURCE-INCOMPATIBLE with v1 (different handle types, different request API). A distro upgrade that silently moved to v2 would break this file, which is the same class of trap as the esptool 4.x/5.x subcommand split and the Arduino 2.x/3.x break behind If v2 support is wanted it goes beside this, not through it.

Print and Stream are pure character I/O, and LambStdio already implements exactly that on POSIX, so this is a facade over working plumbing rather than a stand-in. That is the same footing as millis(): genuinely implemented on the host, not faked.

ARDUINO'S QUIRKS ARE MATCHED ON PURPOSE. Each of these is a place where a host test could pass while a device disagrees, which is the failure criterion 3 is designed to catch:

  • println() ends "\r\n", NOT "\n" – Arduino has always done this, and a serial monitor shows it
  • write() returns a BYTE COUNT – callers legitimately sum it
  • print(double) defaults to 2 dp – not g, not full precision
  • print(int, base) takes BIN/OCT/DEC/HEX and prints NO prefix ("ff", not "0xff")

Macro Definition Documentation

◆ LL_LLA_NPINS

#define LL_LLA_NPINS   256

Simulated pin file. LL_LLA_NPINS is generous because pin NUMBERING is board-specific (a Pi's BCM numbers, an ESP32's GPIO numbers) and this backend must not reject a number that is legal somewhere. Out-of-range is CLAMPED AWAY FROM MEMORY, never written: a bad pin number is a caller error, not a reason to corrupt the heap.

Function Documentation

◆ ll_gpiod_available()

bool ll_gpiod_available ( )
extern

The libgpiod backend lives in ll_llarduino_gpiod.cpp; only its entry points are needed here.

◆ ll_gpiod_analog_read()

int ll_gpiod_analog_read ( int pin)
extern

NO ADC AND NO PWM HERE, AND THEY MUST NOT PRETEND. Neither a Pi nor a Jetson has an ADC on the header – analogRead conventionally means an EXTERNAL converter (MCP3008 over SPI, ADS1115 over I2C) – and analogWrite needs a PWM chip wired to that specific pin. The rule holds: a fabricated sensor reading is worse than an error, because it is plausible. -1 says "unsupported on this backend"; it is never a measurement.

◆ pinMode()

void pinMode ( int pin,
int mode )

Public Arduino surface – one line each, straight through the table.

◆ ll_llarduino_pin_mode()

int ll_llarduino_pin_mode ( int pin)

Backend inspection – lets a test assert on state the Arduino API cannot report (mode, duty, tone) and name which backend answered. See ll_llarduino_null.cpp.

◆ print()

size_t Print::print ( double v,
int digits = 2 )

Arduino's default is TWO decimal places, not g and not full precision.

◆ println()

size_t Print::println ( )

CRLF, as Arduino does – not "\n".

CRLF – Arduino's println has always emitted "\r\n". A host that emits bare "\n" looks correct in a terminal and differs from the device, which is exactly the silent divergence to avoid.

◆ printf()

size_t Print::printf ( const char * fmt,
... )

HardwareSerial::printf, used by LL itself.

HardwareSerial::printf is not standard Arduino Print, but LambLisp's own Stdio layer calls it (ll_platform_Stdio.cpp), so the facade owes it.

< truncate, never overrun

◆ write()

size_t LLArduinoSerial::write ( uint8_t c)
overridevirtual

Implements Print.

◆ available()

int LLArduinoSerial::available ( )
override

available() must count the pushed-back byte, or peek() would hide input from a caller that polls available() before reading – the classic Stream bug.

◆ peek()

int LLArduinoSerial::peek ( )
override

One byte of pushback, which is all Stream promises. LambStdioClass has no peek of its own.