diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bb9ad61 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +secrets.lsp diff --git a/armasm.lsp b/armasm.lsp new file mode 100644 index 0000000..7da9b75 --- /dev/null +++ b/armasm.lsp @@ -0,0 +1,363 @@ +; 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/attiny.lsp b/attiny.lsp new file mode 100644 index 0000000..6f38b32 --- /dev/null +++ b/attiny.lsp @@ -0,0 +1,53 @@ +; 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/bels.lsp b/bels.lsp new file mode 100644 index 0000000..b5f7e60 --- /dev/null +++ b/bels.lsp @@ -0,0 +1,38 @@ +; +; 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/edit.lsp b/edit.lsp new file mode 100644 index 0000000..bb0c6f5 --- /dev/null +++ b/edit.lsp @@ -0,0 +1,45 @@ +(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/mand.lsp b/mand.lsp new file mode 100644 index 0000000..1d7a531 --- /dev/null +++ b/mand.lsp @@ -0,0 +1,100 @@ +(defun mandelbrot (x0 y0 scale) + (set-rotation 2) + (fill-screen) + (dotimes (y 240) + (let ((b0 (+ (/ (- y 120) 120 scale) y0))) + (dotimes (x 320) + (let* ((a0 (+ (/ (- x 160) 120 scale) x0)) + (c 80) (a a0) (b b0) a2) + (loop + (setq a2 (+ (- (* a a) (* b b)) a0)) + (setq b (+ (* 2 a b) b0)) + (setq a a2) + (decf c) + (when (or (> (+ (* a a) (* b b)) 4) (zerop c)) (return))) + (draw-pixel x y (if (plusp c) (hsv (* 359 (/ c 80)) 1 1) 0))))))) + +(defvar fern-cd + #2A((0 0 0 0.25 0 -0.14 0.02) + (0.85 0.02 -0.02 0.83 0 1.0 0.84) + (0.09 -0.28 0.3 0.11 0 0.6 0.07) + (-0.09 0.28 0.3 0.09 0 0.7 0.07))) + +(defvar *width* 320) +(defvar *height* 360) +(defvar *factor* (/ *height* 7)) +(defvar *x-offset* (/ *width* 2)) +(defvar *y-offset* (/ *height* 24)) +(defvar *dark-green* #b0000001111100000) +(defvar *fern* fern-cd) + +(defun fn (n) + #'(lambda (x y) + (list (+ (* (aref *fern* n 0) x) + (* (aref *fern* n 1) y) + (aref *fern* n 4)) + (+ (* (aref *fern* n 2) x) + (* (aref *fern* n 3) y) + (aref *fern* n 5))))) + +(defun choose-transform () + (let ((r (random 1.0)) (p 0)) + (dotimes (i 4) + (when (<= r (incf p (aref *fern* i 6))) + (return (fn i)))))) + +(defun plot-pixel (x y) + (let ((xx (round (+ (* *factor* y) *y-offset*))) + (yy (round (- *width* (+ (* *factor* x) *x-offset*))))) + (draw-pixel xx yy *dark-green*))) + +(defun fern (&optional (iterations 50000)) + (fill-screen #xFFFF) + (let ((x 0) (y 0)) + (dotimes (i iterations) + (plot-pixel x y) + (let ((xy (funcall (choose-transform) x y))) + (setq x (first xy)) + (setq y (second xy)))))) + +(defun sierpinski (x0 y0 size gen) + (when (plusp gen) + (let ((s (ash size -1)) + (n (1- gen))) + (fill-rect x0 y0 size size (col gen)) + (sierpinski (+ x0 (ash s -1)) y0 s n) + (sierpinski x0 (+ y0 s) s n) + (sierpinski (+ x0 s) (+ y0 s) s n)))) + +(defun q (n) + (if (<= n 2) 1 + (+ + (q (- n (q (- n 1)))) + (q (- n (q (- n 2))))))) + +(defun speedup (fn) + (let ((c nil)) + (lambda (x) + (or (cdr (assoc x c)) + (let ((r (funcall fn x))) + (setq c (cons (cons x r) c)) + r))))) + +(setq q (speedup q)) + +(defun qplot (width height) + (fill-screen) + (let ((x0 0) (y0 0) x1 y1 + (yellow #b1111111111100000) + (salmon #b1111110000010000)) + (draw-line 10 (- height 10) (1- width) (- height 10)) + (draw-line 10 (- height 10) 10 10) + (dotimes (n 6) + (draw-char 0 (- height (* n (truncate height 6)) 14) (code-char (+ n 48)) yellow)) + (dotimes (n 10) + (draw-char (+ (* n (truncate width 10)) 12) (- height 7) (code-char (+ n 48)) yellow)) + (dotimes (n width) + (setq x1 n y1 (q n)) + (draw-line (+ x0 10) (- height y0 10) (+ x1 10) (- height y1 10) salmon) + (setq x0 x1 y0 y1)))) + diff --git a/pkg.lsp b/pkg.lsp new file mode 100644 index 0000000..1b425e4 --- /dev/null +++ b/pkg.lsp @@ -0,0 +1,24 @@ +(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/query.lsp b/query.lsp new file mode 100644 index 0000000..0b18eea --- /dev/null +++ b/query.lsp @@ -0,0 +1,89 @@ +; 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/r5asm.lsp b/r5asm.lsp new file mode 100644 index 0000000..d0cc127 --- /dev/null +++ b/r5asm.lsp @@ -0,0 +1,395 @@ +; 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/r5asmpi.lsp b/r5asmpi.lsp new file mode 100644 index 0000000..d56d603 --- /dev/null +++ b/r5asmpi.lsp @@ -0,0 +1,161 @@ +; 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/rtc.lsp b/rtc.lsp new file mode 100644 index 0000000..3f4d7a5 --- /dev/null +++ b/rtc.lsp @@ -0,0 +1,57 @@ +(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/sync.sh b/sync.sh new file mode 100755 index 0000000..dee2379 --- /dev/null +++ b/sync.sh @@ -0,0 +1,22 @@ +#!/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/tak.lsp b/tak.lsp new file mode 100644 index 0000000..c92f42d --- /dev/null +++ b/tak.lsp @@ -0,0 +1,86 @@ +(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/tools.lsp b/tools.lsp new file mode 100644 index 0000000..39b809d --- /dev/null +++ b/tools.lsp @@ -0,0 +1,30 @@ +(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/ulos.lsp b/ulos.lsp new file mode 100644 index 0000000..b64122a --- /dev/null +++ b/ulos.lsp @@ -0,0 +1,26 @@ +; +; 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/wifi.lsp b/wifi.lsp new file mode 100644 index 0000000..96638e3 --- /dev/null +++ b/wifi.lsp @@ -0,0 +1,34 @@ +(defvar *http-use-tls* t) + +(defun toggle-http-tls () + (setf *http-use-tls* (not *http-use-tls*))) + +(defun get-http-port () + (if *http-use-tls* 443 8000)) + +(defun wifi-dial () + (wifi-connect *wifi-ssid* *wifi-password*)) + +(defun curl (host url) + (let ((println #'(lambda (x s) (format s "~a~a~%" x #\return)))) + (with-client (s host (get-http-port)) + (println (format nil "GET ~a HTTP/1.0" url) s) + (println (format nil "Host: ~a" host) s) + (println "Connection: close" s) + (println "" s) + (loop (unless (zerop (available s)) (return))) + (loop + (delay 100) + (when (zerop (available s)) (return)) + (princ (read-line s)) + (terpri))))) + +(defun nc-read (host port) + (with-client (s host port) + (loop (unless (zerop (available s)) (return))) + (loop + (delay 100) + (when (zerop (available s)) (return)) + (princ (read-line s)) + (terpri)))) +