ulisp/builder/avr-nano.lisp

288 lines
8.2 KiB
Common Lisp

;;;-*- Mode: Lisp; Package: cl-user -*-
(in-package :cl-user)
; AVR
(defparameter *title-avr-nano*
#"/* uLisp AVR-Nano Release ~a - www.ulisp.com
David Johnson-Davies - www.technoblogy.com - ~a
Licensed under the MIT license: https://opensource.org/licenses/MIT
*/"#)
(defparameter *header-avr-nano* #"
// Lisp Library
const char LispLibrary[] PROGMEM = "";
// Compile options
#define checkoverflow
// #define resetautorun
#define printfreespace
// #define printgcs
// #define sdcardsupport
// #define lisplibrary
#define assemblerlist
// #define lineeditor
// #define vt100
// Includes
// #include "LispLibrary.h"
#include <avr/sleep.h>
#include <setjmp.h>
#include <SPI.h>
#include <limits.h>
#include <EEPROM.h>
#if defined(sdcardsupport)
#include <SD.h>
#define SDSIZE 172
#else
#define SDSIZE 0
#endif"#)
(defparameter *workspace-avr-nano* #"
// Platform specific settings
#define WORDALIGNED __attribute__((aligned (2)))
#define OBJECTALIGNED __attribute__((aligned (4)))
#define BUFFERSIZE 22 /* longest builtin name + 1 */
#if defined(ARDUINO_AVR_UNO)
#define WORKSPACESIZE (320-SDSIZE) /* Objects (4*bytes) */
#define EEPROMSIZE 1024 /* Bytes */
#define STACKDIFF 1
#define CPU_ATmega328P
#elif defined(ARDUINO_AVR_NANO_EVERY)
#define WORKSPACESIZE (1060-SDSIZE) /* Objects (4*bytes) */
#define EEPROMSIZE 256 /* Bytes */
#define STACKDIFF 160
#define CPU_ATmega4809
#elif defined(ARDUINO_AVR_ATmega4809) /* Curiosity Nano using MegaCoreX */
#define Serial Serial3
#define WORKSPACESIZE (1065-SDSIZE) /* Objects (4*bytes) */
#define EEPROMSIZE 256 /* Bytes */
#define STACKDIFF 320
#define CPU_ATmega4809
#elif defined(ARDUINO_AVR_ATtiny3227)
#define WORKSPACESIZE (514-SDSIZE) /* Objects (4*bytes) */
// #define EEPROMSIZE 256 /* Bytes */
#define STACKDIFF 1
#define CPU_ATtiny3227
#elif defined(__AVR_AVR64DD28__)
#include <Flash.h>
#define WORKSPACESIZE (1440-SDSIZE) /* Objects (4*bytes) */
#define FLASHWRITESIZE 6144 /* Bytes */
#define STACKDIFF 1
#define CPU_AVR64DD28
#else
#error "Board not supported!"
#endif"#)
(defparameter *watchdog-avr-nano* #"
// Watchdog
void watchdogenable (int interval) {
int i = 5;
while (interval) { interval = interval>>1; i++; }
wdt_enable(i);
}
void watchdogreset () {
wdt_reset();
}"#)
(defparameter *check-pins-avr-nano* #"
// Check pins - these are board-specific not processor-specific
void checkanalogread (int pin) {
#if defined(ARDUINO_AVR_UNO)
if (!(pin>=0 && pin<=5)) error(invalidpin, number(pin));
#elif defined(ARDUINO_AVR_NANO_EVERY)
if (!((pin>=14 && pin<=21))) error(invalidpin, number(pin));
#elif defined(ARDUINO_AVR_ATmega4809) /* MegaCoreX core */
if (!((pin>=22 && pin<=33) || (pin>=36 && pin<=39))) error(invalidpin, number(pin));
#elif defined(ARDUINO_AVR_ATtiny3227)
if (!((pin>=0 && pin<=3) || (pin>=6 && pin<=7) || (pin>=10 && pin<=11) || pin==18)) error(invalidpin, number(pin));
#endif
}
void checkanalogwrite (int pin) {
#if defined(ARDUINO_AVR_UNO)
if (!(pin==3 || pin==5 || pin==6 || (pin>=9 && pin<=11))) error(invalidpin, number(pin));
#elif defined(ARDUINO_AVR_NANO_EVERY)
if (!(pin==3 || pin==5 || pin==6 || pin==9 || pin==10)) error(invalidpin, number(pin));
#elif defined(ARDUINO_AVR_ATmega4809) /* MegaCoreX core */
if (!((pin>=16 && pin<=19) || (pin>=38 && pin<=39))) error(invalidpin, number(pin));
#elif defined(ARDUINO_AVR_ATtiny3227)
if (!((pin>=0 && pin<=1) || (pin>=9 && pin<=11) || pin==20)) error(invalidpin, number(pin));
#endif
}"#)
(defparameter *note-avr-nano* #"
// Note
#if defined(CPU_ATtiny3227) || defined(CPU_AVR64DD28)
const int scale[] PROGMEM = {4186,4435,4699,4978,5274,5588,5920,6272,6645,7040,7459,7902};
#else
const uint8_t scale[] PROGMEM = {239,226,213,201,190,179,169,160,151,142,134,127};
#endif
void playnote (int pin, int note, int octave) {
#if defined(CPU_ATmega328P)
if (pin == 3) {
DDRD = DDRD | 1<<DDD3; // PD3 (Arduino D3) as output
TCCR2A = 0<<COM2A0 | 1<<COM2B0 | 2<<WGM20; // Toggle OC2B on match
} else if (pin == 11) {
DDRB = DDRB | 1<<DDB3; // PB3 (Arduino D11) as output
TCCR2A = 1<<COM2A0 | 0<<COM2B0 | 2<<WGM20; // Toggle OC2A on match
} else error(PSTR("only pins 3 and 11 supported"), number(pin));
int oct = octave + note/12;
int prescaler = 9 - oct;
if (prescaler<3 || prescaler>6) error(PSTR("octave out of range"), number(oct));
OCR2A = pgm_read_byte(&scale[note%12]) - 1;
TCCR2B = 0<<WGM22 | prescaler<<CS20;
#elif defined(CPU_ATmega4809) || defined(CPU_ATtiny3227)
int oct = octave + note/12;
int prescaler = 8 - oct;
if (prescaler<0 || prescaler>8) error(PSTR("octave out of range"), number(oct));
tone(pin, scale[note%12]>>prescaler);
#elif defined(CPU_AVR64DD28)
int oct = octave + note/12;
int prescaler = 8 - oct;
if (prescaler<0 || prescaler>8) error(PSTR("octave out of range"), number(oct));
tone(pin, pgm_read_word(&scale[note%12])>>prescaler);
#endif
}
void nonote (int pin) {
#if defined(CPU_ATmega4809) || defined(CPU_ATtiny3227) || defined(CPU_AVR64DD28)
noTone(pin);
#else
(void) pin;
TCCR2B = 0<<WGM22 | 0<<CS20;
#endif
}"#)
(defparameter *sleep-avr-nano* #"
// Sleep
#if defined(CPU_ATmega328P)
// Interrupt vector for sleep watchdog
ISR(WDT_vect) {
WDTCSR |= 1<<WDIE;
}
#endif
void initsleep () {
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
}
void sleep () {
#if defined(CPU_ATtiny3227) || defined(CPU_AVR64DD28)
ADC0.CTRLA = ADC0.CTRLA & ~1; // Turn off ADC
delay(100); // Give serial time to settle
sleep_enable();
sleep_cpu();
ADC0.CTRLA = ADC0.CTRLA | 1; // Turn on ADC
#elif defined(CPU_ATmega328P)
ADCSRA = ADCSRA & ~(1<<ADEN); // Turn off ADC
delay(100); // Give serial time to settle
sleep_enable();
sleep_cpu();
ADCSRA = ADCSRA | 1<<ADEN; // Turn on ADC
#endif
}
void doze (int secs) {
#if defined(CPU_ATmega328P)
// Set up Watchdog timer for 1 Hz interrupt
WDTCSR = 1<<WDCE | 1<<WDE;
WDTCSR = 1<<WDIE | 6<<WDP0; // 1 sec interrupt
while (secs > 0) { sleep(); secs--; }
WDTCSR = 1<<WDCE | 1<<WDE; // Disable watchdog
WDTCSR = 0;
#else
delay(1000*secs);
#endif
}"#)
(defparameter *interrupts-avr-nano* #"
// Interrupts
#if defined(CPU_ATmega328P)
#define NINTERRUPTS 2+1
#elif defined(CPU_ATmega2560)
#define NINTERRUPTS 8+1
#elif defined(CPU_ATmega1284P)
#define NINTERRUPTS 3+1
#endif
unsigned int InterruptCount[NINTERRUPTS];
void handleInterrupts () {
if (tstflag(BUSY)) return;
object *nullenv = NULL;
setflag(BUSY);
int ints, flag;
cli(); flag = tstflag(INTERRUPT); clrflag(INTERRUPT); sei();
if (flag) {
for (int i=0; i<NINTERRUPTS; i++) {
cli(); ints = InterruptCount[i]; InterruptCount[i] = 0; sei();
if (ints) {
object *pair = assoc(number(i),Events);
object *arg = cons(number(ints), NULL);
push(arg, GCStack);
if (pair != NULL) apply(cdr(pair), arg, &nullenv);
pop(GCStack);
}
}
}
clrflag(BUSY);
}
void interrupt (int n) {
setflag(INTERRUPT);
if (InterruptCount[n] < 0xFFFF) InterruptCount[n]++;
}
//ISR(TIMER1_OVF_vect) { interrupt(0); }
ISR(INT0_vect) { interrupt(0); }
ISR(INT1_vect) { interrupt(1); }
#if defined(CPU_ATmega1284P)
ISR(INT2_vect) { interrupt(2); }
#elif defined(CPU_ATmega2560)
ISR(INT2_vect) { interrupt(2); }
ISR(INT3_vect) { interrupt(3); }
ISR(INT4_vect) { interrupt(4); }
ISR(INT5_vect) { interrupt(5); }
ISR(INT6_vect) { interrupt(6); }
ISR(INT7_vect) { interrupt(7); }
#endif"#)
(defparameter *keywords-avr-nano*
'((nil
((NIL LED_BUILTIN)
(DIGITALWRITE HIGH LOW)
(PINMODE INPUT INPUT_PULLUP OUTPUT)))
("CPU_ATmega328P"
((ANALOGREFERENCE DEFAULT INTERNAL EXTERNAL)
(REGISTER PORTB DDRB PINB PORTC DDRC PINC PORTD DDRD PIND)))
("CPU_ATmega4809"
((ANALOGREFERENCE DEFAULT INTERNAL VDD INTERNAL0V55 INTERNAL1V1 INTERNAL1V5 INTERNAL2V5 INTERNAL4V3 EXTERNAL)
(REGISTER PORTA_DIR PORTA_OUT PORTA_IN PORTB_DIR PORTB_OUT PORTB_IN PORTC_DIR PORTC_OUT PORTC_IN
PORTD_DIR PORTD_OUT PORTD_IN PORTE_DIR PORTE_OUT PORTE_IN PORTF_DIR PORTF_OUT PORTF_IN)))
("CPU_ATtiny3227"
((REGISTER FLAG)))
("CPU_AVR64DD28"
((REGISTER FLAG)))))