ulisp/builder/avr.lisp

291 lines
8.3 KiB
Common Lisp

;;;-*- Mode: Lisp; Package: cl-user -*-
(in-package :cl-user)
; AVR
(defparameter *title-avr*
#"/* uLisp AVR 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* #"
// 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
// #define extensions
// Includes
// #include "LispLibrary.h"
#include <avr/sleep.h>
#include <setjmp.h>
#include <SPI.h>
#include <limits.h>
#if defined(sdcardsupport)
#include <SD.h>
#define SDSIZE 172
#else
#define SDSIZE 0
#endif"#)
(defparameter *workspace-avr* #"
// Platform specific settings
#define WORDALIGNED __attribute__((aligned (2)))
#define OBJECTALIGNED __attribute__((aligned (4)))
#define BUFFERSIZE 22 /* longest builtin name + 1 */
#if defined(ARDUINO_AVR_MEGA2560)
#include <EEPROM.h>
#define WORKSPACESIZE (1344-SDSIZE) /* Objects (4*bytes) */
#define EEPROMSIZE 4096 /* Bytes */
#define STACKDIFF 320
#define CPU_ATmega2560
#elif defined(__AVR_ATmega1284P__)
#include "optiboot.h"
#define WORKSPACESIZE (2944-SDSIZE) /* Objects (4*bytes) */
// #define EEPROMSIZE 4096 /* Bytes */
#define FLASHWRITESIZE 16384 /* Bytes */
#define CODESIZE 96 /* Bytes <= 256 */
#define STACKDIFF 320
#define CPU_ATmega1284P
#elif defined(__AVR_AVR128DA48__)
#include <Flash.h>
#define Serial Serial1
#define WORKSPACESIZE (2920-SDSIZE) /* Objects (4*bytes) */
#define FLASHWRITESIZE 15872 /* Bytes */
#define CODESIZE 96 /* Bytes <= 512 */
#define STACKDIFF 320
#define CPU_AVR128DX48
#define LED_BUILTIN 20
#elif defined(__AVR_AVR128DB48__)
#include <Flash.h>
#define Serial Serial3
#define WORKSPACESIZE (2920-SDSIZE) /* Objects (4*bytes) */
#define FLASHWRITESIZE 15872 /* Bytes */
#define CODESIZE 96 /* Bytes <= 512 */
#define STACKDIFF 320
#define CPU_AVR128DX48
#define LED_BUILTIN 20
#else
#error "Board not supported!"
#endif"#)
(defparameter *watchdog-avr* #"
// 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* #"
// Check pins - these are board-specific not processor-specific
void checkanalogread (int pin) {
#if defined(ARDUINO_AVR_MEGA2560)
if (!(pin>=0 && pin<=15)) error(invalidpin, number(pin));
#elif defined(__AVR_ATmega1284P__)
if (!(pin>=0 && pin<=7)) error(invalidpin, number(pin));
#elif defined(__AVR_AVR128DA48__)
if (!(pin>=22 && pin<=39)) error(invalidpin, number(pin));
#endif
}
void checkanalogwrite (int pin) {
#if defined(ARDUINO_AVR_MEGA2560)
if (!((pin>=2 && pin<=13) || (pin>=44 && pin<=46))) error(invalidpin, number(pin));
#elif defined(__AVR_ATmega1284P__)
if (!(pin==3 || pin==4 || pin==6 || pin==7 || (pin>=12 && pin<=15))) error(invalidpin, number(pin));
#elif defined(__AVR_AVR128DA48__)
if (!((pin>=4 && pin<=5) || (pin>=8 && pin<=19) || (pin>=38 && pin<=39))) error(invalidpin, number(pin));
#endif
}"#)
(defparameter *note-avr* #"
// Note
#if defined(CPU_AVR128DX48)
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_ATmega2560)
if (pin == 9) {
DDRH = DDRH | 1<<DDH6; // PH6 (Arduino D9) as output
TCCR2A = 0<<COM2A0 | 1<<COM2B0 | 2<<WGM20; // Toggle OC2B on match
} else if (pin == 10) {
DDRB = DDRB | 1<<DDB4; // PB4 (Arduino D10) as output
TCCR2A = 1<<COM2A0 | 0<<COM2B0 | 2<<WGM20; // Toggle OC2A on match
} else error(PSTR("only pins 9 and 10 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_ATmega1284P)
if (pin == 14) {
DDRD = DDRD | 1<<DDD6; // PD6 (Arduino D14) as output
TCCR2A = 0<<COM2A0 | 1<<COM2B0 | 2<<WGM20; // Toggle OC2B on match
} else if (pin == 15) {
DDRD = DDRD | 1<<DDD7; // PD7 (Arduino D15) as output
TCCR2A = 1<<COM2A0 | 0<<COM2B0 | 2<<WGM20; // Toggle OC2A on match
} else error(PSTR("only pins 14 and 15 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_AVR128DX48)
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_AVR128DX48)
noTone(pin);
#else
(void) pin;
TCCR2B = 0<<WGM22 | 0<<CS20;
#endif
}"#)
(defparameter *sleep-avr* #"
// Sleep
#if defined(CPU_ATmega2560) || defined(CPU_ATmega1284P)
// 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_ATmega2560) || defined(CPU_ATmega1284P)
ADCSRA = ADCSRA & ~(1<<ADEN); // Turn off ADC
delay(100); // Give serial time to settle
PRR0 = PRR0 | 1<<PRTIM0; // Turn off Timer/Counter0
sleep_enable();
sleep_cpu();
PRR0 = PRR0 & ~(1<<PRTIM0); // Turn on Timer/Counter0
ADCSRA = ADCSRA | 1<<ADEN; // Turn on ADC
#endif
}
void doze (int secs) {
#if defined(CPU_ATmega2560) || defined(CPU_ATmega1284P)
// 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* #"
// Interrupts
#if 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*
'((nil
((NIL LED_BUILTIN)
(DIGITALWRITE HIGH LOW)
(PINMODE INPUT INPUT_PULLUP OUTPUT)))
("CPU_ATmega1284P"
((ANALOGREFERENCE DEFAULT INTERNAL1V1 INTERNAL2V56 EXTERNAL)
(REGISTER PORTA DDRA PINA PORTB DDRB PINB PORTC DDRC PINC PORTD DDRD PIND)))
("CPU_ATmega2560"
((ANALOGREFERENCE DEFAULT INTERNAL1V1 INTERNAL2V56 EXTERNAL)
(REGISTER PORTA DDRA PINA PORTB DDRB PINB PORTC DDRC PINC PORTD DDRD PIND
PORTE DDRE PINE PORTF DDRF PINF PORTG DDRG PING PORTJ DDRJ PINJ)))
("CPU_AVR128DX48"
((ANALOGREFERENCE DEFAULT VDD INTERNAL1V024 INTERNAL2V048 INTERNAL4V096 INTERNAL2V5 EXTERNAL)
(ANALOGREAD ADC_DAC0 ADC_TEMPERATURE)
(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)))))