Here’s the starting point for a project I’ve been working on. It’s a calculator, written in uLisp, with an 8-digit 7-segment display. It lets you do something like:
(show (acos -1))
to display the result of the calculation, pi:
The display is a very low-cost 8-digit display with an SPI interface, available on sites such as AliExpress for under a dollar/pound; for example: MAX7219 8 Digit LED Display. The program will run on any uLisp platform, but to display floating-point calculations you need a 32-bit platform, such as the Adafruit ItsyBitsy M0.
Connecting the display
Connect the display using the appropriate SPI pins as follows:
For details of which pins are used for the SPI interface on different processors see Language reference: with-spi.
You can use any suitable pin as the Enable pin; specify it as follows:
(defvar en 2)
The routine cmd writes a display command to the display, consisting of an address or command code followed by a data value:
(defun cmd (a d) (with-spi (str en) (write-byte a str) (write-byte d str)))
Initialising the display
The following routine on turns on the display and sets the brightness; the parameter can be from 0 (dimmest) to 15 (brightest):
(defun on (bri) (cmd #xF 0) ; Test mode off (cmd #xB 7) ; 8 digits (cmd #xC 1) ; Enable display (cmd #xA bri))
Defining the segment definitions
The following list gives the segment definitions for the digits 0 to 9, the hexadecimal digits A to F, and space and minus:
(defvar seg '(#x7e #x30 #x6d #x79 #x33 #x5b #x5f #x70 #x7f #x7b #x77 #x1f #x4e #x3d #x4f #x47 #x00 #x01))
Clearing the display
This routine clr clears the display:
(defun clr () (dotimes (d 8) (cmd d 0)))
Showing a value
Finally this routine show writes a value to the display:
(defun show (val) (clr) (let ((str (princ-to-string val)) (d 8) b) (dotimes (i (length str)) (let ((c (char-code (char str i)))) (setq b (cond ((= (char-code #\.) c) (incf d) (+ b #x80)) (t (nth (cond ((<= (char-code #\0) c (char-code #\9)) (- c (char-code #\0))) ((<= (char-code #\A) c (char-code #\F)) (+ (- c (char-code #\A)) 10)) ((<= (char-code #\a) c (char-code #\f)) (+ (- c (char-code #\a)) 10)) ((= (char-code #\-) c) 17) (t 16)) seg))))) (cmd d b) (decf d))))
It works by converting the value to a string, using the uLisp function princ-to-string, converts each digit to the appropriate seven-segment pattern from the list seg, and then writes this to the appropriate display digit. If it encounters a decimal point in the value it sets the top bit of the previous digit, to display a decimal point after it.
With the addition of a small keypad this could form the basis of a custom scientific calculator, written in Lisp.