From 25199750cf3e01c4537b9f2ffafbc3afa3499bc1 Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Thu, 10 Apr 2025 23:10:41 -0700 Subject: [PATCH] various fixups --- lisp/armasm.lsp | 363 ----------------------------- lisp/attiny.lsp | 53 ----- lisp/bels.lsp | 38 --- lisp/edit.lsp | 45 ---- lisp/pkg.lsp | 24 -- lisp/query.lsp | 89 ------- lisp/r5asm.lsp | 395 ------------------------------- lisp/r5asmpi.lsp | 161 ------------- lisp/rtc.lsp | 57 ----- lisp/sync.sh | 22 -- lisp/tak.lsp | 86 ------- lisp/tools.lsp | 30 --- lisp/ulos.lsp | 26 --- ulisp-extensions.ino | 536 +++++++++++++++++++++++++++++++++++++++++-- 14 files changed, 521 insertions(+), 1404 deletions(-) delete mode 100644 lisp/armasm.lsp delete mode 100644 lisp/attiny.lsp delete mode 100644 lisp/bels.lsp delete mode 100644 lisp/edit.lsp delete mode 100644 lisp/pkg.lsp delete mode 100644 lisp/query.lsp delete mode 100644 lisp/r5asm.lsp delete mode 100644 lisp/r5asmpi.lsp delete mode 100644 lisp/rtc.lsp delete mode 100755 lisp/sync.sh delete mode 100644 lisp/tak.lsp delete mode 100644 lisp/tools.lsp delete mode 100644 lisp/ulos.lsp diff --git a/lisp/armasm.lsp b/lisp/armasm.lsp deleted file mode 100644 index 7da9b75..0000000 --- a/lisp/armasm.lsp +++ /dev/null @@ -1,363 +0,0 @@ -; ARM Thumb Assembler for uLisp - Version 10 - 18th November 2024 -; see http://www.ulisp.com/show?2YRU -; - -; Extract register number -(defun regno (sym) - (case sym (sp 13) (lr 14) (pc 15) - (t (read-from-string (subseq (string sym) 1))))) - -; Pack arguments into bit fields -(defun emit (bits &rest args) - (let ((word 0) (shift -28)) - (mapc #'(lambda (value) - (let ((width (logand (ash bits shift) #xf))) - (incf shift 4) - (unless (zerop (ash value (- width))) (error "Won't fit")) - (setq word (logior (ash word width) value)))) - args) - word)) - -(defun offset (label) (ash (- label *pc* 4) -1)) - -; data - -(defun $word (val) - (append - (unless (zerop (mod *pc* 4)) (list ($nop))) - (list (logand val #xffff) (logand (ash val -16) #xffff)))) - -; Shared routines, ordered by first four bits - -; lsl lsr 0 - -(defun lsl-lsr-0 (op argd argm immed5) - (emit #x41533000 0 op immed5 (regno argm) (regno argd))) - -; asr 0 - -(defun asr-0 (op argd argm immed5) - (emit #x41533000 1 op immed5 (regno argm) (regno argd))) - -; add sub 1 - -(defun add-sub-1 (op argd argn argm) - (cond - ((numberp argm) - (emit #x61333000 #b000111 op argm (regno argn) (regno argd))) - ((null argm) - (emit #x61333000 #b000110 op (regno argn) (regno argd) (regno argd))) - (t - (emit #x61333000 #b000110 op (regno argm) (regno argn) (regno argd))))) - -; mov sub 2 3 - -(defun mov-sub-2-3 (op2 op argd immed8) - (emit #x41380000 op2 op (regno argd) immed8)) - -; add mov 4 - -(defun add-mov-4 (op argd argm) - (let ((rd (regno argd)) - (rm (regno argm))) - (cond - ((and (>= rd 8) (>= rm 8)) - (emit #x61333000 #b010001 op #b011 (- rm 8) (- rd 8))) - ((>= rm 8) - (emit #x61333000 #b010001 op #b001 (- rm 8) rd)) - ((>= rd 8) - (emit #x61333000 #b010001 op #b010 rm (- rd 8)))))) - -; reg-reg - -(defun reg-reg (op argd argm) - (emit #xa3300000 op (regno argm) (regno argd))) - -; bx blx 4 - -(defun bx-blx (op argm) - (emit #x81430000 #b01000111 op (regno argm) 0)) - -; str ldr 4, 6, 9 - -(defun str-ldr (op argd arg2) - (cond - ((numberp arg2) - (when (= op 0) (error "str not allowed with label")) - (let ((arg (- (truncate (+ arg2 2) 4) (truncate *pc* 4) 1))) - (emit #x41380000 4 1 (regno argd) (max 0 arg)))) - ((listp arg2) - (let ((argn (first arg2)) - (immed (or (eval (second arg2)) 0))) - (unless (zerop (mod immed 4)) (error "not multiple of 4")) - (cond - ((eq (regno argn) 15) - (when (= op 0) (error "str not allowed with pc")) - (emit #x41380000 4 1 (regno argd) (truncate immed 4))) - ((eq (regno argn) 13) - (emit #x41380000 9 op (regno argd) (truncate immed 4))) - (t - (emit #x41533000 6 op (truncate immed 4) (regno argn) (regno argd)))))) - (t (error "illegal argument")))) - -(defun str-ldr-5 (op argd arg2) - (cond - ((listp arg2) - (let ((argn (first arg2)) - (argm (second arg2))) - (emit #x43333000 5 op (regno argm) (regno argn) (regno argd)))) - (t (error "illegal argument")))) - -; add-10 - -(defun add-10 (op argd immed8) - (emit #x41380000 #b1010 op (regno argd) (truncate immed8 4))) - -; add-sub-11 - -(defun add-sub-11 (op immed7) - (emit #x81700000 #b11010000 op (truncate immed7 4))) - -; push pop 11 - -(defun push-pop (op lst) - (let ((byte 0) - (r 0)) - (mapc #'(lambda (x) - (cond - ((and (= op 0) (eq x 'lr)) (setq r 1)) - ((and (= op 1) (eq x 'pc)) (setq r 1)) - (t (setq byte (logior byte (ash 1 (regno x))))))) lst) - (emit #x41218000 11 op 2 r byte))) - -; b cond 13 - -(defun b-cond-13 (cnd label) - (let ((soff8 (logand (offset label) #xff))) - (emit #x44800000 13 cnd soff8))) - -(defun cpside (op aif) - (emit #xb1130000 #b10110110011 op 0 aif)) - -; Alphabetical list of mnemonics - -(defun $adc (argd argm) - (reg-reg #b0100000101 argd argm)) - -(defun $add (argd argn &optional argm) - (cond - ((numberp argm) - (cond - ((eq (regno argn) 15) - (add-10 0 argd argm)) - ((eq (regno argn) 13) - (add-10 1 argd argm)) - (t (add-sub-1 0 argd argn argm)))) - ((and (numberp argn) (null argm)) - (cond - ((eq (regno argd) 13) - (add-sub-11 0 argn)) - (t - (mov-sub-2-3 3 0 argd argn)))) - (t - (cond - ((or (>= (regno argd) 8) (>= (regno argn) 8)) - (add-mov-4 0 argd argn)) - (t - (add-sub-1 0 argd argn argm)))))) - -(defun $and (argd argm) - (reg-reg #b0100000000 argd argm)) - -(defun $asr (argd argm &optional arg2) - (unless arg2 (setq arg2 argm argm argd)) - (cond - ((numberp arg2) - (asr-0 0 argd argm arg2)) - ((eq argd argm) - (reg-reg #b0100000100 argd arg2)) - (t (error "First 2 registers must be the same")))) - -(defun $b (label) - (emit #x41b00000 #xe 0 (logand (offset label) #x7ff))) - -(defun $bcc (label) - (b-cond-13 3 label)) - -(defun $bcs (label) - (b-cond-13 2 label)) - -(defun $beq (label) - (b-cond-13 0 label)) - -(defun $bge (label) - (b-cond-13 10 label)) - -(defun $bgt (label) - (b-cond-13 12 label)) - -(defun $bhi (label) - (b-cond-13 8 label)) - -(defun $bhs (label) - (b-cond-13 2 label)) - -(defun $ble (label) - (b-cond-13 13 label)) - -(defun $blo (label) - (b-cond-13 3 label)) - -(defun $blt (label) - (b-cond-13 11 label)) - -(defun $bmi (label) - (b-cond-13 4 label)) - -(defun $bne (label) - (b-cond-13 1 label)) - -(defun $bpl (label) - (b-cond-13 5 label)) - -(defun $bic (argd argm) - (reg-reg #b0100001110 argd argm)) - -(defun $bl (label) - (list - (emit #x5b000000 #b11110 (logand (ash (offset label) -11) #x7ff)) - (emit #x5b000000 #b11111 (logand (offset label) #x7ff)))) - -(defun $blx (argm) - (bx-blx 1 argm)) - -(defun $bx (argm) - (bx-blx 0 argm)) - -(defun $cmn (argd argm) - (reg-reg #b0100001011 argd argm)) - -(defun $cmp (argd argm) - (cond - ((numberp argm) - (mov-sub-2-3 2 1 argd argm)) - (t - (reg-reg #b0100001010 argd argm)))) - -(defun $cpsid (aif) - (cpside 1 aif)) - -(defun $cpsie (aif) - (cpside 0 aif)) - -(defun $eor (argd argm) - (reg-reg #b0100000001 argd argm)) - -(defun $ldr (argd arg2) - (str-ldr 1 argd arg2)) - -(defun $ldrb (argd arg2) - (str-ldr-5 6 argd arg2)) - -(defun $ldrh (argd arg2) - (str-ldr-5 5 argd arg2)) - -(defun $ldrsb (argd arg2) - (str-ldr-5 3 argd arg2)) - -(defun $ldrsh (argd arg2) - (str-ldr-5 7 argd arg2)) - -(defun $lsl (argd argm &optional arg2) - (unless arg2 (setq arg2 argm argm argd)) - (cond - ((numberp arg2) - (lsl-lsr-0 0 argd argm arg2)) - ((eq argd argm) - (reg-reg #b0100000010 argd arg2)) - (t (error "First 2 registers must be the same")))) - -(defun $lsr (argd argm &optional arg2) - (unless arg2 (setq arg2 argm argm argd)) - (cond - ((numberp arg2) - (lsl-lsr-0 1 argd argm arg2)) - ((eq argd argm) - (reg-reg #b0100000011 argd arg2)) - (t (error "First 2 registers must be the same")))) - -(defun $mov (argd argm) - (cond - ((numberp argm) - (mov-sub-2-3 2 0 argd argm)) - ((or (>= (regno argd) 8) (>= (regno argm) 8)) - (add-mov-4 1 argd argm)) - (t ; Synonym of LSLS Rd, Rm, #0 - (lsl-lsr-0 0 argd argm 0)))) - -(defun $mul (argd argm) - (reg-reg #b0100001101 argd argm)) - -(defun $mvn (argd argm) - (reg-reg #b0100001111 argd argm)) - -(defun $neg (argd argm) - (reg-reg #b0100001001 argd argm)) - -(defun $nop () ; mov r8,r8 - (add-mov-4 1 'r8 'r8)) - -(defun $orr (argd argm) - (reg-reg #b0100001100 argd argm)) - -(defun $push (lst) - (push-pop 0 lst)) - -(defun $pop (lst) - (push-pop 1 lst)) - -(defun $rev (argd argm) - (reg-reg #b1011101000 argd argm)) - -(defun $rev16 (argd argm) - (reg-reg #b1011101001 argd argm)) - -(defun $revsh (argd argm) - (reg-reg #b1011101010 argd argm)) - -(defun $ror (argd argm) - (reg-reg #b0100000111 argd argm)) - -(defun $sbc (argd argm) - (reg-reg #b0100000110 argd argm)) - -(defun $str (argd arg2) - (str-ldr 0 argd arg2)) - -(defun $strb (argd arg2) - (str-ldr-5 2 argd arg2)) - -(defun $sub (argd argn &optional argm) - (cond - ((not (numberp argn)) - (add-sub-1 1 argd argn argm)) - ((eq (regno argd) 13) - (add-sub-11 1 argn)) - (t - (mov-sub-2-3 3 1 argd argn)))) - -(defun $sxtb (argd argm) - (reg-reg #b1011001001 argd argm)) - -(defun $sxth (argd argm) - (reg-reg #b1011001000 argd argm)) - -(defun $tst (argd argm) - (reg-reg #b0100001000 argd argm)) - -(defun $uxtb (argd argm) - (reg-reg #b1011001011 argd argm)) - -(defun $uxth (argd argm) - (reg-reg #b1011001010 argd argm)) - diff --git a/lisp/attiny.lsp b/lisp/attiny.lsp deleted file mode 100644 index 6f38b32..0000000 --- a/lisp/attiny.lsp +++ /dev/null @@ -1,53 +0,0 @@ -; The ATtiny database v3 - 9th April 2019 -; See http://www.ulisp.com/show?2I60 -; - -(defvar *data* - '((attinyX5 (pins 8) (io 5) (adc 4) (pwm 3) (usi 1) (timer8 2) (crystal) (pll)) - (attiny85 (family attinyx5) (flash 8192) (ram 512) (eeprom 512) (price soic 72) (price pdip 90)) - (attiny45 (family attinyx5) (flash 4096) (ram 256) (eeprom 256) (price soic 77) (price pdip 85)) - (attiny25 (family attinyx5) (flash 2048) (ram 128) (eeprom 128) (price soic 79) (price pdip 83)) - - (attinyX4 (pins 14) (io 11) (adc 8) (pwm 4) (usi 1) (timer8 1) (timer16 1) (crystal)) - (attiny84 (family attinyX4) (flash 8192) (ram 512) (eeprom 512) (price soic 60) (price pdip 87)) - (attiny44 (family attinyX4) (flash 4096) (ram 256) (eeprom 256) (price soic 56) (price pdip 86)) - (attiny24 (family attinyX4) (flash 2048) (ram 128) (eeprom 128) (price soic 52) (price pdip 83)) - - (attinyX313 (pins 20) (io 17) (pwm 3) (uart 1) (usi 1) (timer8 1) (timer16 1) (crystal)) - (attiny4313 (family attinyX313) (flash 4096) (ram 256) (eeprom 256) (price soic 70) (price pdip 98)) - (attiny2313 (family attinyX313) (flash 2048) (ram 128) (eeprom 128) (price soic 82) (price pdip 99)) - - (attinyX41 (pins 14) (io 11) (adc 12) (uart 2) (i2c slave) (timer8 1) (timer16 2) (crystal)) - (attiny841 (family attinyX41) (flash 8192) (ram 512) (eeprom 512) (price soic 78)) - (attiny441 (family attinyX41) (flash 4096) (ram 256) (eeprom 256) (price soic 73)) - - (attinyX61 (pins 20) (io 15) (adc 11) (pwm 3) (usi 1) (timer8 1) (timer16 1) (crystal) (pll)) - (attiny861 (family attinyX61) (flash 8192) (ram 512) (eeprom 512) (price soic 92) (price pdip 110)) - (attiny461 (family attinyX61) (flash 4096) (ram 256) (eeprom 256) (price soic 85) (price pdip 129)) - (attiny261 (family attinyX61) (flash 2048) (ram 128) (eeprom 128) (price soic 83) (price pdip 107)) - - (attinyX7 (pins 20) (io 16) (adc 11) (pwm 3) (uart 1) (usi 1) (timer8 1) (timer16 1) (crystal) (lin)) - (attiny167 (family attinyX7) (flash 16384) (ram 512) (eeprom 512) (price soic 111)) - (attiny87 (family attinyX7) (flash 8192) (ram 512) (eeprom 512) (price soic 124)) - - (attinyX8 (pins 28) (io 27) (adc 8) (pwm 4) (i2c master) (i2c slave) (usi 1) (timer8 1) (timer16 1)) - (attiny88 (family attinyX8) (flash 8192) (ram 512) (eeprom 64) (price tqfp 76) (price pdip 143)) - (attiny48 (family attinyX8) (flash 4096) (ram 256) (eeprom 64) (price tqfp 78) (price pdip 131)) - - (attinyX34 (pins 20) (io 17) (adc 12) (pwm 4) (i2c slave) (uart 2) (usi 1) (timer8 1) (timer16 1) (crystal)) - (attiny1634 (family attinyX34) (flash 16384) (ram 1024) (eeprom 256) (price soic 118)) - - (attinyX28 (pins 32) (io 27) (adc 28) (pwm 4) (i2c slave) (uart 1) (timer8 1) (timer16 1)) - (attiny828 (family attinyX28) (flash 8192) (ram 512) (eeprom 512) (price tqfp 84)) - - (attinyX3 (pins 20) (io 15) (adc 4) (pwm 4) (usi 1) (timer8 1) (timer16 1) (boost)) - (attiny43 (family attinyX3) (flash 4096) (ram 512) (eeprom 64) (price soic 147)) - - (attiny9/10 (pins 6) (io 4) (adc 4) (pwm 2) (timer16 1)) - (attiny4/5 (pins 6) (io 4) (pwm 2) (timer16 1)) - (attiny10 (family attiny9/10) (flash 1024) (ram 32) (price sot 25)) - (attiny9 (family attiny9/10) (flash 512) (ram 32) (price sot 25)) - (attiny5 (family attiny4/5) (flash 1024) (ram 32) (price sot 23)) - (attiny4 (family attiny4/5) (flash 512) (ram 32) (price sot 27)))) - - diff --git a/lisp/bels.lsp b/lisp/bels.lsp deleted file mode 100644 index b5f7e60..0000000 --- a/lisp/bels.lsp +++ /dev/null @@ -1,38 +0,0 @@ -; -; Ringing the changes -; see http://www.ulisp.com/show?1G42 -; - -(defvar *bell-pin* 3) - -(defun fnd (x lst) - (cond - ((null lst) nil) - ((< x (car lst)) (car lst)) - (t (fnd x (cdr lst))))) - -(defun sub (new old lst) - (cond - ((null lst) nil) - ((eq old (car lst)) (cons new (cdr lst))) - (t (cons (car lst) (sub new old (cdr lst)))))) - -(defun nxt (lst) - (cond - ((not (apply > (cdr lst))) (cons (car lst) (nxt (cdr lst)))) - ((> (car lst) (cadr lst)) nil) - (t (let* ((rest (reverse (cdr lst))) - (old (fnd (car lst) rest))) - (cons old (sub (car lst) old rest)))))) - -(defun all (fun lst) - (when lst - (funcall fun lst) - (all fun (nxt lst)))) - -(defun bel (lis) - (mapc - (lambda (x) (note *bell-pin* x 4) (delay 500) (note) (delay 125)) - lis) - (delay 500)) - diff --git a/lisp/edit.lsp b/lisp/edit.lsp deleted file mode 100644 index bb0c6f5..0000000 --- a/lisp/edit.lsp +++ /dev/null @@ -1,45 +0,0 @@ -(defvar *cmds* nil) - -(defun %edit (fun) - (cond - ((null *cmds*) fun) - ((eq (car *cmds*) #\b) (pop *cmds*) fun) - ((eq (car *cmds*) #\e) (pop *cmds*) (%edit (list fun))) - ((eq (car *cmds*) #\h) (pop *cmds*) (%edit (cons 'highlight (list fun)))) - ((consp (car *cmds*)) - (let ((val (cdar *cmds*))) - (case (caar *cmds*) - (#\r (pop *cmds*) (%edit val)) - ((#\c #\i) (pop *cmds*) (%edit (cons val fun))) - (#\f (cond - ((null fun) nil) - ((equal val fun) (pop *cmds*) (%edit fun)) - ((atom fun) fun) - (t (cons (%edit (car fun)) (%edit (cdr fun))))))))) - ((atom fun) (pop *cmds*) (%edit fun)) - ((eq (car *cmds*) #\d) (pop *cmds*) (%edit (cons (car fun) (%edit (cdr fun))))) - ((eq (car *cmds*) #\a) (pop *cmds*) (%edit (cons (%edit (car fun)) (cdr fun)))) - ((eq (car *cmds*) #\x) (pop *cmds*) (%edit (cdr fun))) - (t fun))) - -(defun edit (name) - (let ((fun (eval name)) - cc) - (setq *cmds* nil) - (loop - (write-byte 12) - (setq cc (append cc (list #\h))) - (setq *cmds* cc) - (pprint (%edit fun)) - (setq cc (butlast cc)) - (let ((c (get-key))) - (case c - (#\q (set name fun) (return name)) - (#\s (setq *cmds* cc) (set name (%edit fun)) (return name)) - (#\z (when cc (setq cc (butlast cc)))) - ((#\r #\c #\i #\f #\e) - (write-byte 11) (princ c) (princ #\:) - (setq cc (append cc (list (cons c (read)))))) - ((#\d #\a #\x #\b) - (setq cc (append cc (list c)))) - (t (write-byte 7))))))) diff --git a/lisp/pkg.lsp b/lisp/pkg.lsp deleted file mode 100644 index 1b425e4..0000000 --- a/lisp/pkg.lsp +++ /dev/null @@ -1,24 +0,0 @@ -(defvar *packages* nil) - -(defun load-package (filename) - (let* ((path (concatenate 'string filename ".pkg")) - (forms (load path))) - (setf *packages* (append-to-list - (cons filename forms) - (remove-if (lambda (x) - (string= (car x) filename)) - *packages*))))) - -(defun save-package (filename lst) - (with-sd-card (str filename 2) - (dolist (f lst) - (symbol-def f str)))) - -(defun unload-package (package) - (dolist (sym (cdr (assoc package *packages*))) - (makunbound sym))) - -(defun add-to-package (filename list) - (with-sd-card (str filename 1) - (dolist (f lst) - (symdef str)))) diff --git a/lisp/query.lsp b/lisp/query.lsp deleted file mode 100644 index 0b18eea..0000000 --- a/lisp/query.lsp +++ /dev/null @@ -1,89 +0,0 @@ -; uLisp Query Language - 9th April 2019 -; See http://www.ulisp.com/show?2I60 -; - -; Database - -(defvar *rules* nil) - -(defun add (rule) - (unless (assoc (car rule) *rules*) (push (list (car rule)) *rules*)) - (push (cdr rule) (cdr (assoc (car rule) *rules*))) - t) - -; Match - -(defun match (x y &optional binds) - (cond - ((eq x y) (if binds binds '((t)))) - ((assoc x binds) (match (binding x binds) y binds)) - ((assoc y binds) (match x (binding y binds) binds)) - ((var? x) (cons (cons x y) binds)) - ((var? y) (cons (cons y x) binds)) - (t - (when (and (consp x) (consp y)) - (let ((m (match (car x) (car y) binds))) - (when m (match (cdr x) (cdr y) m))))))) - -(defun var? (x) - (and (symbolp x) (eq (char (string x) 0) #\?))) - -(defun binding (x binds) - (let ((b (assoc x binds))) - (when b - (or (binding (cdr b) binds) - (cdr b))))) - -; Inference - -(defun query (expr &optional binds) - (case (car expr) - (and (query-and (reverse (cdr expr)) binds)) - (or (query-or (cdr expr) binds)) - (not (query-not (second expr) binds)) - (test (query-test (second expr) binds)) - (t (lookup (car expr) (cdr expr) binds)))) - -(defun lookup (pred args &optional binds) - (mapcan - (lambda (x) - (let ((m (match args x binds))) - (when m (list m)))) - (cdr (assoc pred *rules*)))) - -(defun query-and (clauses binds) - (if (null clauses) - (list binds) - (mapcan (lambda (b) (query (car clauses) b)) - (query-and (cdr clauses) binds)))) - -(defun query-or (clauses binds) - (apply 'append (mapcar (lambda (c) (query c binds)) clauses))) - -(defun query-not (clause binds) - (unless (query clause binds) - (list binds))) - -(defun subs (lst binds) - (cond - ((null lst) nil) - ((atom lst) (if (assoc lst binds) (cdr (assoc lst binds)) lst)) - (t (cons (subs (car lst) binds) (subs (cdr lst) binds))))) - -(defun query-test (tst binds) - (when (eval (subs tst binds)) - (list binds))) - -(defun answer (expr output) - (dolist (binds (query expr nil)) - (mapc (lambda (p) (princ p) (princ #\space)) (subs output binds)) - (terpri))) - -(defun read-data () - (dolist (rules *data*) - (let ((pred (first rules)) - (data (cdr rules))) - (mapc (lambda (rule) (add (cons (first rule) (cons pred (cdr rule))))) data))) - t) - - diff --git a/lisp/r5asm.lsp b/lisp/r5asm.lsp deleted file mode 100644 index d0cc127..0000000 --- a/lisp/r5asm.lsp +++ /dev/null @@ -1,395 +0,0 @@ -; RISC-V Assembler - Version 4 - 18th October 2024 -; see http://www.ulisp.com/show?310Z -; - -; Extract register number -(defun regno (sym) - (case sym (zero 0) (ra 1) (sp 2) (gp 3) (tp 4) ((s0 fp) 8) (s1 9) - (t (let* ((s (string sym)) - (c (char s 0)) - (n (read-from-string (subseq s 1)))) - (case c (#\x n) (#\a (+ n 10)) (#\s (+ n 16)) (#\t (if (<= n 2) (+ n 5) (+ n 25)))))))) - -; Short 3-bit register s0, s1, a0 to a5 -(defun cregp (rd) (<= 8 (regno rd) 15)) - -(defun cregno (sym) (logand (regno sym) #x7)) - -; Pack arguments into bit fields -(defun emit (bits &rest args) - (let ((word 0)) - (mapc #'(lambda (width value) - (unless (zerop (ash value (- width))) (error* "Won't fit")) - (setq word (logior (ash word width) value))) - bits args) - word)) - -; 32-bit emit -(defun emit32 (bits &rest args) - (let ((word (apply #'emit bits args))) - (list (logand word #xffff) (logand (ash word -16) #xffff)))) - -; Errors -(defun error* (txt) (format t "(pc=#x~x) ~a~%" *pc* txt)) - -; Test range of immediate signed values -(defun immp (x b) - (<= (- (ash 1 (1- b))) x (1- (ash 1 (1- b))))) - -; Extract bitfield -(defun bits (x a &optional b) - (if b (logand (ash x (- b)) (1- (ash 1 (- a b -1)))) - (logand (ash x (- a)) 1))) - -(defun offset (label) (- label *pc*)) - -; Instruction formats - -(defun reg (funct7 rs2 rs1 funct3 rd op) - (emit32 '(7 5 5 3 5 7) funct7 (regno rs2) (regno rs1) funct3 (regno rd) op)) - -(defun creg (op3 op1 op2 rd op2b rs2) - (cond - ((and (cregp rd) (cregp rs2)) - (emit '(3 1 2 3 2 3 2) op3 op1 op2 (cregno rd) op2b (cregno rs2) 1)) - (t (error* "C won't fit")))) - -(defun immed (imm12 rs1 funct3 rd op) - (cond - ((immp imm12 12) - (emit32 '(12 5 3 5 7) (logand imm12 #xfff) (regno rs1) funct3 (regno rd) op)) - (t - (error* "Immediate value out of range")))) - -(defun cimmed (imm12 rs1 funct3 rd op) - (emit32 '(12 5 3 5 7) imm12 (regno rs1) funct3 (regno rd) op)) - -(defun branch (imm12 rs2 rs1 funct3 funct7) - (let ((off (offset imm12))) - (emit32 '(1 6 5 5 3 4 1 7) - (bits off 12) (bits off 10 5) (regno rs2) - (regno rs1) funct3 (bits off 4 1) (bits off 11) funct7))) - -(defun jump (imm20 imm10-1 imm11 imm19-12 rd op) - (emit32 '(1 10 1 8 5 7) imm20 imm10-1 imm11 imm19-12 rd op)) - -(defun muldiv (rs2 rs1 funct3 rd funct7) - (emit32 '(7 5 5 3 5 7) 1 (regno rs2) (regno rs1) funct3 (regno rd) funct7)) - -(defun store (imm src base op) - (emit32 '(7 5 5 3 5 7) (bits imm 11 5) (regno src) (regno base) op (bits imm 4 0) #x23)) - -(defun cimm6 (rd imm op1 op2) - (emit '(3 1 5 5 2) op1 (bits imm 5) (regno rd) (bits imm 4 0) op2)) - -(defun cimm6* (rd imm op1 op2 op3) - (emit '(3 1 2 3 5 2) op1 (bits imm 5) op2 (cregno rd) (bits imm 4 0) op3)) - -; -; Alphabetical list of mnemonics -; - -(defun $add (rd rs1 rs2) - (cond - ((eq rd rs1) - (emit '(3 1 5 5 2) 4 1 (regno rd) (regno rs2) 2)) - (t (reg 0 rs2 rs1 0 rd #x33)))) - -(defun $addi (rd rs1 imm) - (cond - ((and (eq rd rs1) (immp imm 6)) - (cimm6 rd imm 0 1)) - ((and (= (regno rd) 2) (= (regno rs1) 2) (immp imm 10)) - (emit '(3 1 5 1 1 2 1 2) 3 (bits imm 9) 2 (bits imm 4) (bits imm 6) (bits imm 8 7) (bits imm 5) 1)) - (t (immed imm rs1 0 rd #x13)))) - -(defun $and (rd rs1 rs2) - (cond - ((and (eq rd rs1) (cregp rd) (cregp rs2)) - (creg 4 0 3 rd 3 rs2)) - (t (reg 0 rs2 rs1 7 rd #x33)))) - -(defun $andi (rd rs1 imm) - (cond - ((and (eq rd rs1) (cregp rd) (immp imm 5)) - (cimm6* rd imm 4 2 1)) - (t (immed imm rs1 7 rd #x13)))) - -(defun $auipc (rd imm) - (cond - ((zerop (logand imm #xfff)) - (emit32 '(20 5 7) (bits imm 31 12) (regno rd) #x17)) - (t (error* "auipc no good")))) - -(defun $beq (rs1 rs2 imm12) - (branch imm12 rs2 rs1 0 #x63)) - -(defun $beqz (rs imm) - (let ((off (offset imm))) - (cond - ((and (immp off 8) (cregp rs)) - (emit '(3 1 2 3 2 2 1 2) 6 (bits off 8) (bits off 4 3) - (cregno rs) (bits off 7 6) (bits off 2 1) (bits off 5) 1)) - (t ($beq rs 'x0 imm))))) - -(defun $bge (rs1 rs2 imm12) - (branch imm12 rs2 rs1 5 #x63)) - -(defun $bgeu (rs1 rs2 imm12) - (branch imm12 rs2 rs1 7 #x63)) - -(defun $bgez (rs1 imm12) - ($bge rs1 'x0 imm12)) - -(defun $bgt (rs1 rs2 imm12) - ($blt rs2 rs1 imm12)) - -(defun $bgtu (rs1 rs2 imm12) - ($bltu rs2 rs1 imm12)) - -(defun $bgtz (rs1 imm12) - ($blt 'x0 rs1 imm12)) - -(defun $ble (rs1 rs2 imm12) - ($bge rs2 rs1 imm12)) - -(defun $bleu (rs1 rs2 imm12) - ($bgeu rs2 rs1 imm12)) - -(defun $blez (rs2 imm12) - ($bge 'x0 rs2 imm12)) - -(defun $blt (rs1 rs2 imm12) - (branch imm12 rs2 rs1 4 #x63)) - -(defun $bltu (rs1 rs2 imm12) - (branch imm12 rs2 rs1 6 #x63)) - -(defun $bltz (rs1 imm12) - ($blt rs1 'x0 imm12)) - -(defun $bne (rs1 rs2 imm12) - (branch imm12 rs2 rs1 1 #x63)) - -(defun $bnez (rs imm) - (let ((off (offset imm))) - (cond - ((and (immp off 8) (cregp rs)) - (emit '(3 1 2 3 2 2 1 2) 7 (bits off 8) (bits off 4 3) - (cregno rs) (bits off 7 6) (bits off 2 1) (bits off 5) 1)) - (t ($bne rs 'x0 imm))))) - -(defun $div (rd rs1 rs2) - (muldiv rs2 rs1 4 rd #x33)) - -(defun $divu (rd rs1 rs2) - (muldiv rs2 rs1 5 rd #x33)) - -(defun $divw (rd rs1 rs2) - (muldiv rs2 rs1 4 rd #x3b)) - -(defun $divuw (rd rs1 rs2) - (muldiv rs2 rs1 5 rd #x3b)) - -(defun $fence () (emit32 '(16 16) #x0ff0 #x000f)) - -(defun $j (label) - (let ((off (offset label))) - (emit '(3 1 1 2 1 1 1 3 1 2) 5 (bits off 11) (bits off 4) (bits off 9 8) - (bits off 10) (bits off 6) (bits off 7) (bits off 3 1) (bits off 5) 1))) - -; C.JAL is RV32 only -(defun $jal (rd &optional label) - (when (null label) (setq label rd rd 'ra)) - (let ((off (offset label))) - (emit32 '(1 10 1 8 5 7) (bits off 20) (bits off 10 1) (bits off 11) (bits off 19 12) (regno rd) #x6f))) - -(defun $jalr (label lst) - (let ((off (+ (offset label) 4))) - (emit32 '(12 5 3 5 7) (bits off 11 0) (regno (car lst)) 0 (regno (car lst)) #x67))) - -(defun $jr (rs1) - (emit '(3 1 5 5 2) 4 0 (regno rs1) 0 2)) - -; In next four, imm can be omitted and defaults to 0 -(defun $lb (rd imm &optional lst) - (unless lst (setq lst imm imm 0)) - (immed imm (car lst) 0 rd 3)) - -(defun $lbu (rd imm &optional lst) - (unless lst (setq lst imm imm 0)) - (immed imm (car lst) 4 rd 3)) - -(defun $lh (rd imm &optional lst) - (unless lst (setq lst imm imm 0)) - (immed imm (car lst) 1 rd 3)) - -(defun $lhu (rd imm &optional lst) - (unless lst (setq lst imm imm 0)) - (immed imm (car lst) 5 rd 3)) - -; li pseudoinstruction - will load 32-bit immediates -(defun $li (rd imm) - (cond - ((immp imm 6) ; 16 bit - (cimm6 rd imm 2 1)) - ((immp imm 12) ; 32 bit - ($addi rd 'x0 imm)) - (t (let ((imm12 (logand imm #x00000fff)) ; 64 bit - (imm20 (logand (ash imm -12) #xfffff))) - (append - ($lui rd (if (= (logand imm12 #x800) #x800) (+ imm20 #x1000) imm20)) - ; $addi - (emit32 '(12 5 3 5 7) imm12 (regno rd) 0 (regno rd) #x13)))))) - -(defun $lui (rd imm) - (cond - ((and (immp imm 6) (/= imm 0) (/= (regno rd) 0) (/= (regno rd) 2)) ; 16 bit - (cimm6 rd imm 3 1)) - (t - (emit32 '(20 5 7) imm (regno rd) #x37)) - (t (error* "lui no good")))) - -(defun $lw (rd imm lst) - (cond - ((listp lst) - (let ((base (car lst))) - (cond - ; rs1 = sp - ((and (= (regno base) 2)) - (emit '(3 1 5 3 2 2) 2 (bits imm 5) (regno rd) (bits imm 4 2) (bits imm 7 6) 2)) - ; rs1 = general - ((and (cregp rd) (cregp base)) - (emit '(3 3 3 1 1 3 2) 2 (bits imm 5 3) (cregno base) (bits imm 2) (bits imm 6) (cregno rd) 0)) - (t (immed imm base 2 rd 3))))) - (t (error* "Illegal 3rd arg")))) - -(defun $mul (rd rs1 rs2) - (muldiv rs2 rs1 0 rd #x33)) - -(defun $mulh (rd rs1 rs2) - (muldiv rs2 rs1 1 rd #x33)) - -(defun $mulhsu (rd rs1 rs2) - (muldiv rs2 rs1 2 rd #x33)) - -(defun $mulhu (rd rs1 rs2) - (muldiv rs2 rs1 3 rd #x33)) - -(defun $mv (rd rs1) - (emit '(3 1 5 5 2) 4 0 (regno rd) (regno rs1) 2)) - -(defun $neg (rd rs2) - ($sub rd 'x0 rs2)) - -(defun $nop () - ($addi 'x0 'x0 0)) - -(defun $not (rd rs1) - ($xori rd rs1 -1)) - -(defun $or (rd rs1 rs2) - (cond - ((and (eq rd rs1) (cregp rd) (cregp rs2)) - (creg 4 0 3 rd 2 rs2)) - (t (reg 0 rs2 rs1 6 rd #x33)))) - -(defun $ori (rd rs1 imm) - (immed imm rs1 6 rd #x13)) - -(defun $rem (rd rs1 rs2) - (muldiv rs2 rs1 6 rd #x33)) - -(defun $remu (rd rs1 rs2) - (muldiv rs2 rs1 7 rd #x33)) - -(defun $ret () - ($jr 'ra)) - -; In $sb, $sh, and $sw, imm can be omitted and defaults to 0 -(defun $sb (src imm &optional lst) - (unless lst (setq lst imm imm 0)) - (store imm src (car lst) 0)) - -(defun $seqz (rd rs1) - ($sltiu rd rs1 1)) - -(defun $sgtz (rd rs2) - ($slt rd 'x0 rs2)) - -(defun $sh (src imm &optional lst) - (unless lst (setq lst imm imm 0)) - (store imm src (car lst) 1)) - -(defun $sll (rd rs1 rs2) - (reg 0 rs2 rs1 1 rd #x33)) - -(defun $slli (rd rs1 imm) - (cond - ((and (eq rd rs1)) - (cimm6 rd imm 0 2)) - (t (emit32 '(6 6 5 3 5 7) 0 imm (regno rs1) 1 (regno rd) #x13)))) - -(defun $slt (rd rs1 rs2) - (reg 0 rs2 rs1 2 rd #x33)) - -(defun $slti (rd rs1 imm) - (immed imm rs1 2 rd #x13)) - -(defun $sltiu (rd rs1 imm) - (immed imm rs1 3 rd #x13)) - -(defun $sltu (rd rs1 rs2) - (reg 0 rs2 rs1 3 rd #x33)) - -(defun $sltz (rd rs1) - ($slt rd rs1 'x0)) - -(defun $snez (rd rs2) - ($sltu rd 'x0 rs2)) - -(defun $sra (rd rs1 rs2) - (reg #x20 rs2 rs1 2 rd #x33)) - -(defun $srai (rd rs1 imm) - (cond - ((and (eq rd rs1) (cregp rd)) - (cimm6* rd imm 4 1 1)) - (t (emit32 '(6 6 5 3 5 7) #x10 imm (regno rs1) 5 (regno rd) #x13)))) - -(defun $srl (rd rs1 rs2) - (reg 0 rs2 rs1 5 rd #x33)) - -(defun $srli (rd rs1 imm) - (cond - ((and (eq rd rs1) (cregp rd)) - (cimm6* rd imm 4 0 1)) - (t (emit32 '(6 6 5 3 5 7) 0 imm (regno rs1) 5 (regno rd) #x13)))) - -(defun $sub (rd rs1 rs2) - (cond - ((and (eq rd rs1) (cregp rd) (cregp rs2)) - (creg 4 0 3 rd 0 rs2)) - (t (reg #x20 rs2 rs1 0 rd #x33)))) - -(defun $sw (src imm &optional lst) - (unless lst (setq lst imm imm 0)) - (let ((base (car lst))) - (cond - ; base = sp - ((and (= (regno base) 2)) - (emit '(3 4 2 5 2) 6 (bits imm 5 2) (bits imm 7 6) (regno src) 2)) - ; base = general - ((and (cregp src) (cregp base)) - (emit '(3 3 3 1 1 3 2) 6 (bits imm 5 3) (cregno base) (bits imm 2) (bits imm 6) (cregno src) 0)) - (t (store imm src base 2))))) - -(defun $xor (rd rs1 rs2) - (cond - ((and (eq rd rs1) (cregp rd) (cregp rs2)) - (creg 4 0 3 rd 1 rs2)) - (t (reg 0 rs2 rs1 4 rd #x33)))) - -(defun $xori (rd rs1 imm) - (immed imm rs1 4 rd #x13)) - diff --git a/lisp/r5asmpi.lsp b/lisp/r5asmpi.lsp deleted file mode 100644 index d56d603..0000000 --- a/lisp/r5asmpi.lsp +++ /dev/null @@ -1,161 +0,0 @@ -; RISC-V Assembler extensions for RP2350 - Version 1 - 18th October 2024 -; see http://www.ulisp.com/show?4Y5E -; - -; Instruction formats - -(defun bit13 (op1 op2 rs1 op3 rd) - (emit32 '(7 5 5 3 5 7) op1 op2 (regno rs1) op3 (regno rd) #x13)) - -(defun bitimm5 (op1 imm5 rs1 op2 rd) - (emit32 '(7 5 5 3 5 7) op1 (logand imm5 #x1f) (regno rs1) op2 (regno rd) #x13)) - -; Additional compressed formats - -(defun $mul (rd rs1 rs2) - (cond - ((and (eq rd rs1) (cregp rd) (cregp rs2)) - (emit '(3 3 3 2 3 2) 4 7 (cregno rd) 2 (cregno rs2) 1)) - (t (muldiv rs2 rs1 0 rd #x33)))) - -(defun $sb (src imm &optional lst) - (unless lst (setq lst imm imm 0)) - (cond - ((and (cregp src) (cregp (car lst)) (<= 0 imm 3)) - (emit '(3 3 3 1 1 3 2) 4 2 (cregno (car lst)) (bits imm 0) (bits imm 1) (cregno src) 0)) - (t (store imm src (car lst) 0)))) - -(defun $sh (src imm &optional lst) - (unless lst (setq lst imm imm 0)) - (cond - ((and (cregp src) (cregp (car lst)) (or (= imm 0) (= im 2)) - (emit '(3 3 3 1 1 3 2) 4 3 (cregno (car lst)) 0 (bits imm 1) (cregno src) 0)) - (t (store imm src (car lst) 1))))) - -; Add compressed formats to $lbu, $lh, and $lhu. No $lb compressed format -(defun $lbu (rd imm &optional lst) - (unless lst (setq lst imm imm 0)) - (cond - ((and (cregp rd) (cregp (car lst)) (<= 0 imm 3)) - (emit '(3 3 3 1 1 3 2) 4 0 (cregno (car lst)) (bits imm 0) (bits imm 1) (cregno rd) 0)) - (t (immed imm (car lst) 4 rd 3)))) - -(defun $lh (rd imm &optional lst) - (unless lst (setq lst imm imm 0)) - (cond - ((and (cregp rd) (cregp (car lst)) (or (= imm 0) (= im 2)) - (emit '(3 3 3 1 1 3 2) 4 1 (cregno (car lst)) 1 (bits imm 1) (cregno rd) 0)) - (t (immed imm (car lst) 1 rd 3))))) - -(defun $lhu (rd imm &optional lst) - (unless lst (setq lst imm imm 0)) - (cond - ((and (cregp rd) (cregp (car lst)) (or (= imm 0) (= im 2)) - (emit '(3 3 3 1 1 3 2) 4 1 (cregno (car lst)) 0 (bits imm 1) (cregno rd) 0)) - (t (immed imm (car lst) 5 rd 3))))) - -(defun $xori (rd rs1 imm) - (cond - ((and (eq rd rs1) (cregp rd) (= imm -1)) - (emit '(3 3 3 2 3 2) 4 7 (cregno rd) 3 5 1)) - (t (immed imm rs1 4 rd #x13)))) - -; New instructions - -(defun $andn (rd rs1 rs2) - (reg #x20 rs2 rs1 3 rd #x33)) - -(defun $bclr (rd rs1 rs2) - (reg #x24 rs2 rs1 1 rd #x33)) - -(defun $bclri (rd rs1 imm5) - (bitimm5 #x24 imm5 rs1 1 rd)) - -(defun $bext (rd rs1 rs2) - (reg #x24 rs2 rs1 5 rd #x33)) - -(defun $bexti (rd rs1 imm5) - (bitimm5 #x24 imm5 rs1 5 rd)) - -(defun $binv (rd rs1 rs2) - (reg #x34 rs2 rs1 1 rd #x33)) - -(defun $binvi (rd rs1 imm5) - (bitimm5 #x34 imm5 rs1 1 rd)) - -(defun $brev8 (rd rs1) - (bit13 #x34 7 rs1 5 rd)) - -(defun $bset (rd rs1 rs2) - (reg #x14 rs2 rs1 1 rd #x33)) - -(defun $bseti (rd rs1 imm5) - (bitimm5 #x14 imm5 rs1 1 rd)) - -(defun $clz (rd rs1) - (bit13 #x30 0 rs1 1 rd)) - -(defun $cpop (rd rs1) - (bit13 #x30 2 rs1 1 rd)) - -(defun $ctz (rd rs1) - (bit13 #x30 1 rs1 1 rd)) - -(defun $max (rd rs1 rs2) - (reg #x05 rs2 rs1 6 rd #x33)) - -(defun $maxu (rd rs1 rs2) - (reg #x05 rs2 rs1 7 rd #x33)) - -(defun $min (rd rs1 rs2) - (reg #x05 rs2 rs1 4 rd #x33)) - -(defun $minu (rd rs1 rs2) - (reg #x05 rs2 rs1 5 rd #x33)) - -(defun $orc.b (rd rs1) - (bit13 #x14 7 rs1 5 rd)) - -(defun $orn (rd rs1 rs2) - (reg #x20 rs2 rs1 5 rd #x33)) - -(defun $pack (rd rs1 rs2) - (reg #x04 rs2 rs1 4 rd #x33)) - -(defun $packh (rd rs1 rs2) - (reg #x04 rs2 rs1 7 rd #x33)) - -(defun $rev8 (rd rs1) - (bit13 #x34 #x18 rs1 5 rd)) - -(defun $rol (rd rs1 rs2) - (reg #x30 rs2 rs1 1 rd #x33)) - -(defun $ror (rd rs1 rs2) - (reg #x30 rs2 rs1 5 rd #x33)) - -(defun $rori (rd rs1 imm5) - (bitimm5 #x30 imm5 rs1 5 rd)) - -(defun $sext.b (rd rs1) - (bit13 #x30 #x04 rs1 1 rd)) - -(defun $sext.h (rd rs1) - (bit13 #x30 #x05 rs1 1 rd)) - -(defun $unzip (rd rs1) - (bit13 #x04 #x0f rs1 5 rd)) - -(defun $xnor (rd rs1 rs2) - (reg #x20 rs2 rs1 4 rd #x33)) - -(defun $zext.b (rd rs1) - ($andi rd rs1 #xff))) - -(defun $zext.h (rd rs1) - (emit32 '(7 5 5 3 5 7) #x04 0 (regno rs1) 4 (regno rd) #x33)) - -(defun $zip (rd rs1) - (bit13 #x04 #x0f rs1 1 rd)) - - diff --git a/lisp/rtc.lsp b/lisp/rtc.lsp deleted file mode 100644 index 3f4d7a5..0000000 --- a/lisp/rtc.lsp +++ /dev/null @@ -1,57 +0,0 @@ -(defvar *rtc-port* 0) - -(defun bcd-to-dec (x) - "(bcd-to-dec x) -Convert the BCD-encoded number x to a decimal value." - (+ - (* 10 (ash x -4)) - (logand x #xf))) - -(defun dec-to-bcd (x) - "(dec-to-bcd x) -Converts the decimal value to a BCD-encoded number. -Number must be in the range 0 to 99." - (+ - (ash (floor x 10) 4) - (logand (rem x 10) #xf))) - -(defun rtc-p () - "(rtc-p) -Returns t if the RTC is connected." - (with-i2c (str *rtc-port* #x68) - (streamp str))) - -(defun rtc-set (h m s) - "(rtc-set hr min sec) -Set the time on a DS3231 RTC. Times are in BCD, so use -the appropriate reader macro, e.g. (rtc-set #x12 #x34 #x00) -for 12:34:00." - (let ((h (dec-to-bcd h)) - (m (dec-to-bcd m)) - (s (dec-to-bcd s))) - (with-i2c (str *rtc-port* #x68) - (write-byte 0 str) - (write-byte s str) - (write-byte m str) - (write-byte h str)))) - -(defun rtc-get () - (with-i2c (str *rtc-port* #x68) - (write-byte 0 str) - (restart-i2c str 3) - (mapcar bcd-to-dec - (reverse - (list - (read-byte str) - (read-byte str) - (read-byte str)))))) - -(defun rtc-now () - "(rtc-now) -Set the time using the RTC." - (apply now (rtc-get))) - -(defun now-rtc () - "(now-rtc) -Sets the RTC time using the now function." - (apply rtc-set (now))) diff --git a/lisp/sync.sh b/lisp/sync.sh deleted file mode 100755 index dee2379..0000000 --- a/lisp/sync.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -if [ "$(uname -s)" = "Linux" ] -then - DEFAULT_MOUNT="/media/kyle/ULISP" -else - DEFAULT_MOUNT="/Volumes/ULISP" -fi - -MEDIA="${1:-${DEFAULT_MOUNT}}" - -if [ ! -d "${MEDIA}" ] -then - echo "[!] ${MEDIA} isn't mounted!" - exit 1 -fi - -echo "[+] transferring lisp files to ${MEDIA}..." -cp *.lsp "$MEDIA" -echo "[+] unmounting ${MEDIA}" -umount "$MEDIA" -echo "[+] transfer complete" diff --git a/lisp/tak.lsp b/lisp/tak.lsp deleted file mode 100644 index c92f42d..0000000 --- a/lisp/tak.lsp +++ /dev/null @@ -1,86 +0,0 @@ -(defun tak (x y z) - (if (not (< y x)) - z - (tak - (tak (1- x) y z) - (tak (1- y) z x) - (tak (1- z) x y)))) - -(defun benchmark-tak () - (tak 18 12 6)) - -(defun fib (n) - (if (< n 3) 1 - (+ (fib (- n 1)) (fib (- n 2))))) - -(defun benchmark-fib () - (fib 23)) - -(defun q (n) - (if (<= n 2) 1 - (+ - (q (- n (q (- n 1)))) - (q (- n (q (- n 2))))))) - -(defun benchmark-q () - (q 21)) - -(defun q2 (x y) - (if (or (< x 1) (< y 1)) 1 - (+ (q2 (- x (q2 (1- x) y)) y) - (q2 x (- y (q2 x (1- y))))))) - -(defun benchmark-q2 () - (q2 7 8)) - -(defun factor (n) - (cond - ((zerop (mod n 2)) 2) - ((zerop (mod n 3)) 3) - (t (let ((d 5) (i 2)) - (loop - (when (> (* d d) n) (return n)) - (when (zerop (mod n d)) (return d)) - (incf d i) (setq i (- 6 i))))))) - -(defvar *factor-prime* 2142142141) -(defun benchmark-factor () - (factor *factor-prime*)) - -(defun sieve (size) - (let ((a (make-array size :element-type 'bit)) - max) - (setf (aref a 0) 1 (aref a 1) 1) - (dotimes (i size max) - (when (zerop (aref a i)) - (setq max i) - (do ((j (* 2 i) (+ j i))) ((>= j size)) (setf (aref a j) 1)))))) - -(defun benchmark-sieve () - (sieve 100000)) - -(defun benchmark-check (fun expected) - (let ((answer (fun))) - (unless (eq answer expected) - (error "benchmark failed: have ~a, expected ~a~%" - answer - expected) - t))) - -(defun benchmark-time-it (fun expected) - (time (benchmark-check fun expected))) - -(defun benchmark () - (print '(tak 18 12 6)) - (benchmark-time-it benchmark-tak 7) - (print '(fib 23)) - (benchmark-time-it benchmark-fib 28657) - (print '(q 21)) - (benchmark-time-it benchmark-q 12) - (print '(q2 7 8)) - (benchmark-time-it benchmark-q2 31) - (print '(factor 2142142141)) - (benchmark-time-it benchmark-factor *factor-prime*) - (print '(sieve 100000)) - (benchmark-time-it benchmark-sieve 99991)) - diff --git a/lisp/tools.lsp b/lisp/tools.lsp deleted file mode 100644 index 39b809d..0000000 --- a/lisp/tools.lsp +++ /dev/null @@ -1,30 +0,0 @@ -(defun pprintf (sym str) - "(pprintf sym str) -Pretty-print the function pointed to by sym to -the stream, which follows the 'format directives." - (let ((form (eval sym))) - (format str "(defun ~a ~a~%~{ ~a~^~%~})" - (string sym) - (cadr form) - (cddr form)))) - -(defun copy-file (source dest) - (with-sd-card (writer dest 2) - (with-sd-card (reader source) - (loop - (let ((data (read-byte reader))) - (when (null data) - (return)) - (write-byte data writer)))))) - -(defun i2c-scan (port) - (dotimes (addr 127) - (with-i2c (str port addr) - (when str (print addr))))) - -(defun i2c-scan2 (port) - (dotimes (addr 127) - (with-i2c (str port addr) - (format t "~,20'x: " addr) - (if str (print t) - (print nil))))) diff --git a/lisp/ulos.lsp b/lisp/ulos.lsp deleted file mode 100644 index b64122a..0000000 --- a/lisp/ulos.lsp +++ /dev/null @@ -1,26 +0,0 @@ -; -; ULOS simple object system -; see http://forum.ulisp.com/t/a-simple-object-system-for-ulisp/622 -; - -; Define an object -(defun object (&optional parent slots) - (let ((obj (when parent (list (cons 'parent parent))))) - (loop - (when (null slots) (return obj)) - (push (cons (first slots) (second slots)) obj) - (setq slots (cddr slots))))) - -; Get the value of a slot in an object or its parents -(defun value (obj slot) - (when (symbolp obj) (setq obj (eval obj))) - (let ((pair (assoc slot obj))) - (if pair (cdr pair) - (let ((p (cdr (assoc 'parent obj)))) - (and p (value p slot)))))) - -; Update a slot in an object -(defun update (obj slot value) - (when (symbolp obj) (setq obj (eval obj))) - (let ((pair (assoc slot obj))) - (when pair (setf (cdr pair) value)))) diff --git a/ulisp-extensions.ino b/ulisp-extensions.ino index 95d0c56..5fc0eb8 100644 --- a/ulisp-extensions.ino +++ b/ulisp-extensions.ino @@ -1,7 +1,17 @@ /* User Extensions + + LispBox uLisp Extension - Version 1.0 - June 2024 + Hartmut Grawe - github.com/ersatzmoco - June 2024 + + edited by hasn0life for Lilygo T-Deck - Jan 2025 + + updated by picolisper for LilyGo T-Deck and + PicoCalc - April 2025 + */ + // Utility functions uint8_t dec_to_bcd(uint8_t n) @@ -23,7 +33,7 @@ bcd_to_dec(uint8_t n) } /* - * Standard definitions + * STANDARD DEFINITIONS * * These definitions should be the same on every platform. */ @@ -204,7 +214,6 @@ fn_listlibrary2(object *args, object *env) } - object * fn_lambdap(object *arg, object *env) { @@ -221,6 +230,132 @@ fn_lambdap(object *arg, object *env) return nil; } + +object * +fn_searchstr(object *args, object *env) +{ + (void) env; + + int startpos = 0; + object *pattern = first(args); + object *target = second(args); + args = cddr(args); + + if (pattern == NULL) { + return number(0); + } else if (target == NULL) { + return nil; + } + + if (args != NULL) { + startpos = checkinteger(car(args)); + } + + if (stringp(pattern) && stringp(target)) { + int l = stringlength(target); + int m = stringlength(pattern); + + if (startpos > l) { + error2(indexrange); + } + + for (int i = startpos; i <= l-m; i++) { + int j = 0; + while (j < m && nthchar(target, i+j) == nthchar(pattern, j)) { + j++; + } + + if (j == m) { + return number(i); + } + } + return nil; + } else { + error2("arguments are not both lists or strings"); + } + + return nil; +} + + +object * +fn_searchn(object *args, object *env) +{ + (void) env; + + int matches = 0; + int last_index = 0; + object *pattern = first(args); + object *target = second(args); + + if (cddr(args) != NULL) { + object *num = third(args); + + if (integerp(num)) { + matches = num->integer; + } + } + + if (pattern == NULL) { + return number(0); + } else if (target == NULL) { + return nil; + } else if (listp(pattern) && listp(target)) { + int l = listlength(target); + int m = listlength(pattern); + + for (int i = 0; i <= l-m; i++) { + object *target1 = target; + while (pattern != NULL && eq(car(target1), car(pattern))) { + pattern = cdr(pattern); + target1 = cdr(target1); + } + + if (pattern == NULL){ + last_index = i; + + if (matches-- == 0) { + return number(i); + } + } + pattern = first(args); target = cdr(target); + } + + if (last_index > 0) { + return number(last_index); + } + return nil; + } else if (stringp(pattern) && stringp(target)) { + int l = stringlength(target); + int m = stringlength(pattern); + + for (int i = 0; i <= l-m; i++) { + int j = 0; + while (j < m && nthchar(target, i+j) == nthchar(pattern, j)) { + j++; + } + + if (j == m) { + last_index = i; + if(matches-- == 0){ + return number(i); + } + } + } + + if (last_index > 0) { + return number(last_index); + } + + return nil; + } else { + error2(PSTR("arguments are not both lists or strings")); + } + + return nil; +} + + // SD card standard library. #if defined(sdcardsupport) @@ -378,6 +513,320 @@ fn_sd_list(object *args, object *env) #endif +/* + * PICOCALC-SPECIFIC FUNCTIONS + * + * Only works on the PicoCalc... + */ +#if defined(PLATFORM_PICOCALC) +char +getkey() +{ + PCKeyboard::KeyEvent kevt; + char keypress; + + do { + kevt = pc_kbd.keyEvent(); + + if (kevt.state == PCKeyboard::StatePress) { + if (kevt.key == 6) { + continue; + } + + keypress = kevt.key; + break; + } + } while (pc_kbd.keyCount() == 0); + + + do { + kevt = pc_kbd.keyEvent(); + } while (kevt.state != PCKeyboard::StateRelease); + + switch (keypress) { + case 177: + keypress = 27; + break; + default: + // do nothing + break; + } + + return keypress; +} + +object * +fn_get_key(object *args, object *env) +{ + (void) args; + (void) env; + + return character(getkey()); +} +#endif + + +#if defined(TDECK_PERI_POWERON) +#define touchscreen + +#if defined(touchscreen) +#include "TouchDrvGT911.hpp" +TouchDrvGT911 touch; +#endif + +#define TDECK_TOUCH_INT 16 + +#define TDECK_TRACKBALL_UP 3 +#define TDECK_TRACKBALL_DOWN 15 +#define TDECK_TRACKBALL_LEFT 1 +#define TDECK_TRACKBALL_RIGHT 2 +#define PLATFORM_TDECK + +volatile int ball_val = 0; + +// Touchscreen +void +initTouch() +{ +#if defined (touchscreen) + pinMode(TDECK_TOUCH_INT, INPUT); + touch.setPins(-1, TDECK_TOUCH_INT);\ + //keyboard already initialized the I2C? + if (!touch.begin(Wire1, GT911_SLAVE_ADDRESS_L)) { + while (1) { + Serial.println("Failed to find GT911 - check your wiring!"); + delay(1000); + } + } + // Set touch max xy + touch.setMaxCoordinates(320, 240); + // Set swap xy + touch.setSwapXY(true); + // Set mirror xy + touch.setMirrorXY(false, true); +#endif +} + + +void +ISR_trackball_up() +{ + ball_val = 218; +} + +void +ISR_trackball_down() +{ + ball_val = 217; +} + +void +ISR_trackball_left() +{ + ball_val = 216; +} + +void +ISR_trackball_right () +{ + ball_val = 215; +} + +void +inittrackball() +{ + pinMode(TDECK_TRACKBALL_UP, INPUT_PULLUP); + pinMode(TDECK_TRACKBALL_DOWN, INPUT_PULLUP); + pinMode(TDECK_TRACKBALL_LEFT, INPUT_PULLUP); + pinMode(TDECK_TRACKBALL_RIGHT, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(TDECK_TRACKBALL_UP), ISR_trackball_up, FALLING); + attachInterrupt(digitalPinToInterrupt(TDECK_TRACKBALL_DOWN), ISR_trackball_down, FALLING); + attachInterrupt(digitalPinToInterrupt(TDECK_TRACKBALL_LEFT), ISR_trackball_left, FALLING); + attachInterrupt(digitalPinToInterrupt(TDECK_TRACKBALL_RIGHT), ISR_trackball_right, FALLING); +} + +object * +fn_get_touch_points(object *args, object *env) +{ +#if defined(touchscreen) + int16_t x[5], y[5]; + uint8_t touched = 0; + object *result = nil; + do { + touched = touch.getPoint(x, y, touch.getSupportTouchPoint()); + if (touched > 0) { + //start from the end of the list so we dont have to reverse it + for (int i = touched; i > 0; --i) { + result = cons(cons(number(x[i-1]), number(y[i-1])), result); + } + } + } while(touch.isPressed()); + return result; + +#else + return nil; +#endif +} + +bool +isScreenTouched() +{ + bool received_touch = false; + + // Clear any previous readings since it buffers those. + do { + int16_t x[5], y[5]; + uint8_t touched = touch.getPoint(x, y, touch.getSupportTouchPoint()); + } while(touch.isPressed()); + + // touch.ispressed() will trigger like 5 times if you press it once so + // we have to loop through it and get the touchpoints + do { + int16_t x[5], y[5]; + uint8_t touched = touch.getPoint(x, y, touch.getSupportTouchPoint()); + if (touched > 0) { + received_touch = true; + } + } while(touch.isPressed()); + + return received_touch; +} + + +// T-Deck extras +char +touchKeyModEditor(char temp) +{ +#if defined (touchscreen) + /* t-deck / blackberry keyboard missing symbols + missing mapped alt symbol + ` k ' + ~ p @ + % $ + ^ a * + & q # + = o + + < t ( + > y ) + \ u _ + | g / + + [ alt-t ( + ] alt-y ) + + { n/a + } n/a + tab space + + while holding the touch screen + c --- quit editor and return to REPL + n --- discard current text buffer (i.e. new file) + backspace --- delete line starting at cursor position + trackball left --- move cursor to start of line + trackball right --- move cursor to end of line + ^ --- move cursor to beginning of buffer + trackball up / trackball down --- move one page up or down + + Fn-h --- help menu + Fn-( --- toggle bracket matching on/off + Fn-) --- check if bracket under the cursor has a matching bracket + in the buffer. If so, they are temporarily highlighted. + (Use when continuous bracket matching is off.) + Fn-b --- bind contents of the text buffer to a symbol of your choice and quit editor + Fn-d --- delete a file on the SD card + Fn-s --- save text buffer to SD card + Fn-l --- load text from SD card into buffer, discarding the present one + Fn-i --- show directory of SD card + + */ + + if (isScreenTouched()) { + if (temp == 'k') return '`'; + else if (temp == 'p') return '~'; + else if (temp == '$') return '%'; + else if (temp == 'a') return '^'; + else if (temp == 'q') return '&'; + else if (temp == 'o') return '='; + else if (temp == 't') return '<'; + else if (temp == 'y') return '>'; + else if (temp == 'u') return '\\'; + else if (temp == 'g') return '|'; + else if (temp == '(') return '['; + else if (temp == ')') return ']'; + else if (temp == ' ') return '\t'; + + else if (temp == 'c') return (char)17; //quit + else if (temp == 'n') return (char)24; //new + else if (temp == 8) return (char)12; //delete line + else if (temp == '*') return (char)94; //beginning + else if (temp == 'h') return (char)16; //help + else if (temp == 's') return (char)203; //save + else if (temp == 'l') return (char)204; //load + else if (temp == 'd') return (char)202; //delete + else if (temp == 'b') return (char)198; //bind + else if (temp == 'i') return (char)205; //show dir + else if (temp == '1') return (char)194; //toggle bracket + else if (temp == '2') return (char)195; //highlight + + } +#else + if (temp == '@') temp = '~'; + if (temp == '_') temp = '\\'; +#endif + return temp; +} + + +object * +fn_KeyboardGetKey(object *args, object *env) +{ + (void) env, (void) args; + + Wire1.requestFrom(0x55, 1); + if (Wire1.available()) { + char temp = Wire1.read(); + if ((temp != 0) && (temp !=255)){ + temp = touchKeyModEditor(temp); + //Serial.println((int)temp); + return number(temp); + } + } + + if (ball_val != 0) { + int temp = ball_val; + ball_val = 0; + if (isScreenTouched()) { + // ((or 1 210) (se:linestart)) + // ((or 5 213) (se:lineend)) + // (211 (se:prevpage)) + // (214 (se:nextpage)) + switch(temp){ + case 218: temp = 211; break; //up + case 217: temp = 214; break; //down + case 216: temp = 210; break; //left + case 215: temp = 213; break; //right + } + } + return number(temp); + } + return nil; +} + + +/* + (keyboard-flush) + Discard missing key up/down events. + */ +object * +fn_KeyboardFlush(object *args, object *env) +{ + (void) args, (void) env; + return nil; +} +#endif + + + /* * SYMBOL NAMES * @@ -390,6 +839,8 @@ const char stringbcd_to_dec[] PROGMEM = "bcd-to-dec"; const char stringdec_to_bcd[] PROGMEM = "dec-to-bcd"; const char stringlist_library2[] PROGMEM = "list-library2"; const char stringplatform[] PROGMEM = "platform"; +const char stringSearchStr[] PROGMEM = "search-str"; +const char stringsearchn[] PROGMEM = "searchn"; #if defined(sdcardsupport) const char stringsd_rename[] PROGMEM = "sd-rename"; @@ -400,6 +851,21 @@ const char stringsd_rmdir[] PROGMEM = "sd-remove-dir"; const char stringsd_dir[] PROGMEM = "sd-list"; #endif +#if defined(PLATFORM_PICOCALC) +const char string_get_key[] PROGMEM = "get-key"; +#elif defined(TDECK_PERI_POWERON) +const char string_gettouchpoints[] PROGMEM = "get-touch-points"; +const char stringKeyboardGetKey[] PROGMEM = "keyboard-get-key"; +const char stringKeyboardFlush[] PROGMEM = "keyboard-flush"; +const char stringSearchStr[] PROGMEM = "search-str"; +const char stringsearchn[] PROGMEM = "searchn"; + +#elif defined(TDECK_PERI_POWERON) +const char string_gettouchpoints[] PROGMEM = "get-touch-points"; +const char stringKeyboardGetKey[] PROGMEM = "keyboard-get-key"; +const char stringKeyboardFlush[] PROGMEM = "keyboard-flush"; +#endif + /* * DOCUMENTATION STRINGS * @@ -432,6 +898,17 @@ const char doc_platform[] PROGMEM = "(platform)\n" "Returns a keyword with the current platform. Supports :picocalc,\n" ":t-deck, and :teensy41. Otherwise, returns :unknown."; +const char docSearchStr[] PROGMEM = "(search pattern target [startpos])\n" +"Returns the index of the first occurrence of pattern in target, or nil if it's not found\n" +"starting from startpos"; + +const char docsearchn[] PROGMEM = "(searchn pattern target [n])\n" +"Returns the index of the nth occurrence of pattern in target,\n" +"which can be lists or strings, or nil if it's not found.\n" +"if the pattern occured more than once but less than n times, it returns the last occuring index"; + + +// SD card doc strings #if defined(sdcardsupport) const char docsd_rename[] PROGMEM = "(sd-rename from to)\n" "Renames the file named by 'from' to 'to.'"; @@ -455,23 +932,52 @@ const char docsd_rmdir[] PROGMEM = "(sd-remove-dir directory)\n" #endif +// PicoCalc-specific doc strings +#if defined(PLATFORM_PICOCALC) +const char doc_get_key[] PROGMEM = "(get-key)\n" +"Waits for a keypress event, then returns the key."; + +// T-Deck-specific doc strings +#elif defined(TDECK_PERI_POWERON) +const char doc_gettouchpoints[] PROGMEM = "(get-touch-points)\n" +"Returns all the points being touched on the screen in a list of x,y pairs or an empty list"; + +const char docKeyboardGetKey[] PROGMEM = "(keyboard-get-key [pressed])\n" +"Get key last recognized - default: when released, if [pressed] is t: when pressed)."; +const char docKeyboardFlush[] PROGMEM = "(keyboard-flush)\n" +"Discard missing key up/down events."; + +// End of platform-specific doc strings. +#endif + + // Symbol lookup table const tbl_entry_t lookup_table2[] PROGMEM = { - { stringlambdap, fn_lambdap, 0211, doclambdap }, - { stringnow, fn_now, 0203, docnow }, - { string_sym_def, fn_sym_def, 0212, doc_sym_def }, - { stringbcd_to_dec, fn_bcd_to_dec, 0211, doc_bcd_to_dec }, - { stringdec_to_bcd, fn_dec_to_bcd, 0211, doc_dec_to_bcd }, - { stringlist_library2, fn_listlibrary2, 0200, doc_list_library2 }, - { stringplatform, fn_platform, 0200, doc_platform }, + { stringlambdap, fn_lambdap, 0211, doclambdap }, + { stringnow, fn_now, 0203, docnow }, + { string_sym_def, fn_sym_def, 0212, doc_sym_def }, + { stringbcd_to_dec, fn_bcd_to_dec, 0211, doc_bcd_to_dec }, + { stringdec_to_bcd, fn_dec_to_bcd, 0211, doc_dec_to_bcd }, + { stringlist_library2, fn_listlibrary2, 0200, doc_list_library2 }, + { stringplatform, fn_platform, 0200, doc_platform }, + { stringSearchStr, fn_searchstr, 0224, docSearchStr }, + { stringsearchn, fn_searchn, 0223, docsearchn }, #if defined(sdcardsupport) - { stringsd_rename, fn_sd_rename, 0222, docsd_rename }, - { stringsd_remove, fn_sd_remove, 0211, docsd_remove }, - { stringsd_existsp, fn_sd_existsp, 0211, docsd_existsp }, - { stringsd_dir, fn_sd_list, 0201, docsd_dir }, - { stringsd_mkdir, fn_sd_mkdir, 0211, docsd_mkdir }, - { stringsd_rmdir, fn_sd_rmdir, 0211, docsd_rmdir }, + { stringsd_rename, fn_sd_rename, 0222, docsd_rename }, + { stringsd_remove, fn_sd_remove, 0211, docsd_remove }, + { stringsd_existsp, fn_sd_existsp, 0211, docsd_existsp }, + { stringsd_dir, fn_sd_list, 0201, docsd_dir }, + { stringsd_mkdir, fn_sd_mkdir, 0211, docsd_mkdir }, + { stringsd_rmdir, fn_sd_rmdir, 0211, docsd_rmdir }, +#endif + +#if defined(PLATFORM_PICOCALC) + { string_get_key, fn_get_key, 0200, doc_get_key }, +#elif defined(TDECK_PERI_POWERON) + { string_gettouchpoints, fn_get_touch_points, 0200, doc_gettouchpoints }, + { stringKeyboardGetKey, fn_KeyboardGetKey, 0201, docKeyboardGetKey }, + { stringKeyboardFlush, fn_KeyboardFlush, 0200, docKeyboardFlush }, #endif };