Compare commits

...

3 Commits

Author SHA1 Message Date
Virgil Dupras
f4871d4d58 recipes/ti84: add upload instructions
ref #41
2019-11-07 13:42:40 -05:00
Virgil Dupras
a13a94bbc7 fix typos 2019-11-07 12:13:00 -05:00
Virgil Dupras
ca84b5dac8 recipes/ti84: first step
This was mostly lifted from my "tihello" example, but it required significant
adjustments.

This commit also introduces a font management system. A lot of fonts are
available online, but sources aren't always clear so to avoid copyright
landmines, I re-created my first 5x7 font from scratch.

As it is now, this resulting ROM gets "Collapse OS>" to be displayed on the
LCD screen. Much work still left to do.

ref #41
2019-11-07 11:52:29 -05:00
16 changed files with 1087 additions and 0 deletions

658
fonts/5x7.txt Normal file
View File

@ -0,0 +1,658 @@
.
.
.
.
.
.
. .
. .
. .
.....
. .
.....
. .
.
....
.
...
.
....
.
. .
.
.
.
. .
..
. .
..
.. .
. .
... .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. . .
...
.....
...
. . .
.
.
.....
.
.
.
.
.....
..
..
.
.
.
.
...
. .
. ..
. . .
.. .
. .
...
..
. .
.
.
.
.
....
...
. .
.
.
.
.
.....
...
. .
.
..
.
. .
...
..
. .
. .
.....
.
.
.
.....
.
....
.
.
. .
...
...
.
.
...
. .
. .
...
.....
.
.
.
.
.
.
...
. .
. .
...
. .
. .
...
...
. .
. .
...
.
.
...
.
.
.
.
.
.
.
.
.
..
..
.
..
..
.
.....
.....
.
..
..
.
..
..
.
...
. .
.
.
.
.
...
. .
. ..
. ..
.
. .
...
...
. .
. .
.....
. .
. .
. .
....
. .
. .
....
. .
. .
....
...
. .
.
.
.
. .
...
....
. .
. .
. .
. .
. .
....
.....
.
.
....
.
.
.....
.....
.
.
....
.
.
.
...
. .
.
. ..
. .
. .
...
. .
. .
. .
.....
. .
. .
. .
...
.
.
.
.
.
...
..
.
.
.
.
. .
...
. .
. .
..
.
..
. .
. .
.
.
.
.
.
.
.....
. .
.. ..
. . .
. .
. .
. .
. .
. .
.. .
.. .
. . .
. ..
. ..
. .
...
. .
. .
. .
. .
. .
...
....
. .
. .
....
.
.
.
...
. .
. .
. .
. . .
. ..
....
....
. .
. .
....
. .
. .
. .
...
. .
.
...
.
. .
...
.....
.
.
.
.
.
.
. .
. .
. .
. .
. .
. .
...
. .
. .
. .
. .
. .
. .
.
. .
. .
. .
. .
. . .
. . .
. .
. .
. .
. .
.
. .
. .
. .
. .
. .
. .
.
.
.
.
.....
. .
.
.
.
. .
.....
...
.
.
.
.
.
...
.
.
.
.
.
...
.
.
.
.
.
...
.
. .
. .
.....
.
.
...
. .
. .
.....
. .
. .
. .
....
. .
. .
....
. .
. .
....
...
. .
.
.
.
. .
...
....
. .
. .
. .
. .
. .
....
.....
.
.
....
.
.
.....
.....
.
.
....
.
.
.
...
. .
.
. ..
. .
. .
...
. .
. .
. .
.....
. .
. .
. .
...
.
.
.
.
.
...
..
.
.
.
.
. .
...
. .
. .
..
.
..
. .
. .
.
.
.
.
.
.
.....
. .
.. ..
. . .
. .
. .
. .
. .
. .
.. .
.. .
. . .
. ..
. ..
. .
...
. .
. .
. .
. .
. .
...
....
. .
. .
....
.
.
.
...
. .
. .
. .
. . .
. ..
....
....
. .
. .
....
. .
. .
. .
...
. .
.
...
.
. .
...
.....
.
.
.
.
.
.
. .
. .
. .
. .
. .
. .
...
. .
. .
. .
. .
. .
. .
.
. .
. .
. .
. .
. .
.. ..
. . .
. .
. .
. .
.
. .
. .
. .
. .
. .
. .
.
.
.
.
.....
. .
.
.
.
. .
.....
..
.
.
.
.
.
..
.
.
.
.
.
.
.
..
.
.
.
.
.
..
. .
. .

15
fonts/README.md Normal file
View File

@ -0,0 +1,15 @@
# fonts
This folder contains bitmap fonts that are then converted to ASM data tables.
The format for them is straightforward: dots and spaces. Each line is a line in
the letter (for example, in a 6x8 font, each character is 8 lines of 6
characters each, excluding newline).
They cover the 0x21 to 0x7e range and are placed sequentially in the file.
Dots and spaces allow easy visualisation of the result and is thus rather handy.
Padding is excluded from fonts. For example, 5x7.txt is actually a 6x8 font, but
because characters are always padded, it's useless to keep systematic blank
lines or rows around.

BIN
kernel/fnt/5x7.bin Normal file

Binary file not shown.

32
kernel/fnt/mgm.asm Normal file
View File

@ -0,0 +1,32 @@
; Font management
;
; There can only ever be one active font.
;
; *** Defines ***
; FNT_DATA: Pointer to the beginning of the binary font data to work with.
; FNT_WIDTH: Width of the font.
; FNT_HEIGHT: Height of the font.
;
; *** Code ***
; If A is in the range 0x20-0x7e, make HL point to the beginning of the
; corresponding glyph and set Z to indicate success.
; If A isn't in the range, do nothing and unset Z.
fntGet:
cp 0x20
ret c ; A < 0x20. Z was unset by cp
cp 0x7f
jp nc, unsetZ ; A >= 0x7f. Z might be set
push af ; --> lvl 1
push bc ; --> lvl 2
sub 0x20
ld hl, FNT_DATA
ld b, FNT_HEIGHT
.loop:
call addHL
djnz .loop
pop bc ; <-- lvl 2
pop af ; <-- lvl 1
cp a ; set Z
ret

27
kernel/ti/kbd.asm Normal file
View File

@ -0,0 +1,27 @@
; kbd
;
; Control TI-84+'s keyboard.
;
; *** Constants ***
.equ KBD_PORT 0x01
; *** Code ***
; Sending 0xff to the port resets the keyboard, and then we have to send groups
; we want to "listen" to, with a 0 in the group bit. Thus, to know if *any* key
; is pressed, we send 0xff to reset the keypad, then 0x00 to select all groups,
; if the result isn't 0xff, at least one key is pressed.
waitForKey:
push af
ld a, 0xff
out (KBD_PORT), a
ld a, 0x00
out (KBD_PORT), a
.loop:
in a, (KBD_PORT)
inc a ; if a was 0xff, will become 0 (z test)
jr z, .loop ; zero? nothing pressed
pop af
ret

139
kernel/ti/lcd.asm Normal file
View File

@ -0,0 +1,139 @@
; lcd
;
; Implement PutC on TI-84+ (for now)'s LCD screen.
;
; *** Requirements ***
; fnt/mgm
;
; *** Constants ***
.equ LCD_PORT_CMD 0x10
.equ LCD_PORT_DATA 0x11
.equ LCD_CMD_6BIT 0x00
.equ LCD_CMD_DISABLE 0x02
.equ LCD_CMD_ENABLE 0x03
.equ LCD_CMD_XINC 0x05
.equ LCD_CMD_YINC 0x07
.equ LCD_CMD_COL 0x20
.equ LCD_CMD_ROW 0x80
.equ LCD_CMD_CONTRAST 0xc0
; *** Code ***
lcdInit:
; Enable the LCD
ld a, LCD_CMD_ENABLE
call lcdWait
out (LCD_PORT_CMD), a
; Hack to get LCD to work. According to WikiTI, we're to sure why TIOS
; sends these, but it sends it, and it is required to make the LCD
; work. So...
ld a, 0x17
call lcdWait
out (LCD_PORT_CMD), a
ld a, 0x0b
call lcdWait
out (LCD_PORT_CMD), a
; Set some usable contrast
ld a, LCD_CMD_CONTRAST+0x34
call lcdWait
out (LCD_PORT_CMD), a
; Enable 6-bit mode.
ld a, LCD_CMD_6BIT
call lcdWait
out (LCD_PORT_CMD), a
; Enable X-increment mode
ld a, LCD_CMD_XINC
call lcdWait
out (LCD_PORT_CMD), a
ret
; Wait until the lcd is ready to receive a command
lcdWait:
push af
.loop:
in a, (LCD_PORT_CMD)
; When 7th bit is cleared, we can send a new command
rla
jr c, .loop
pop af
ret
; Turn LCD off
lcdOff:
ld a, LCD_CMD_DISABLE
call lcdWait
out (LCD_PORT_CMD), a
ret
; Set LCD's current column to A
lcdSetCol:
; The col index specified in A is compounded with LCD_CMD_COL
add a, LCD_CMD_COL
call lcdWait
out (LCD_PORT_CMD), a
ret
; Set LCD's current row to A
lcdSetRow:
; The col index specified in A is compounded with LCD_CMD_COL
add a, LCD_CMD_ROW
call lcdWait
out (LCD_PORT_CMD), a
ret
; Send the 5x7 glyph that HL points to to the LCD, at its current position.
; After having called this, the LCD's position will have advanced by one
; position
lcdSendGlyph:
push af
push bc
push hl
; For the purpose of this program, we only write on the first line.
; We can assume that we always start at row 0.
xor a
call lcdSetRow
ld b, 7
.loop:
ld a, (hl)
inc hl
call lcdWait
out (LCD_PORT_DATA), a
djnz .loop
; Now that we've sent our 7 rows of pixels, let's go in "Y-increment"
; mode to let the LCD increase by one column after we've sent our 8th
; line, which is blank (padding).
ld a, LCD_CMD_YINC
call lcdWait
out (LCD_PORT_CMD), a
; send blank line
xor a
call lcdWait
out (LCD_PORT_DATA), a
; go back in X-increment mode
ld a, LCD_CMD_XINC
call lcdWait
out (LCD_PORT_CMD), a
pop hl
pop bc
pop af
ret
lcdPutC:
push hl
call fntGet
jr nz, .end
call lcdSendGlyph
.end:
pop hl
ret

3
recipes/.gitignore vendored
View File

@ -2,3 +2,6 @@
*.cfs
*.hex
*.obj
*.rom
*.8xu
*.sms

17
recipes/ti84/Makefile Normal file
View File

@ -0,0 +1,17 @@
TARGET = os.rom
ZASM = ../../tools/zasm.sh
KERNEL = ../../kernel
MKTIUPGRADE = mktiupgrade
.PHONY: all
all: $(TARGET)
$(TARGET): glue.asm
$(ZASM) $(KERNEL) < $< > $@
truncate -s 1M $@
os.8xu: $(TARGET)
$(MKTIUPGRADE) -p -k keys/0A.key -d TI-84+ $< $@ 00
.PHONY: send
send: os.8xu
tilp -n --calc ti84+ --cable DirectLink $<

57
recipes/ti84/README.md Normal file
View File

@ -0,0 +1,57 @@
# TI-84+
**This is a work-in-progress, this is far from complete.**
## Recipe
This recipe gets the Collapse OS shell to run on the TI-84+, using its LCD
screen as output and its builtin keyboard as input.
## Build the ROM
Running `make` will result in `os.rom` being created.
## Emulate through z80e
[KnightOS][knightos] has a handy emulator, [z80e][z80e] for TI calculators and
it also emulates the screen. It is recommended to use this tool.
Once z80e is installed (build it with SDL support) and `os.rom` is created,
you can run the emulator with:
z80e-sdl -d TI84p --no-rom-check os.rom
You will start with a blank screen, it's normal, you haven't pressed the "ON"
key yet. This key is mapped to F12 in the emulator. Once you press it, the
Collapse OS prompt will appear.
**WIP: the keyboard does nothing else than halting the CPU for now.**
## Upload to the calculator
**WARNING: the instructions below will wipe all the contents of your calculator,
including TI-OS.**
To send your ROM to the calculator, you'll need two more tools:
[mktiupgrade][mktiupgrade] and [tilp][tilp].
Once you have them, you need to place your calculator in "bootloader mode",
that is, in a mode where it's ready to receive a new binary from its USB cable.
To do that you need to:
1. Shut down the calculator by removing one of the battery.
2. Hold the DEL key
3. But the battery back.
4. A "Waiting... Please install operating system now" message will appear.
Once this is done, you can plug the USB cable in your computer and run
`make send`. This will create an "upgrade file" with `mktiupgrade` and then
push that upgrade file with `tilp`. `tilp` will prompt you at some point.
Press "1" to continue.
When this is done, you can press the ON button to see Collapse OS' prompt!
[knightos]: https://knightos.org/
[z80e]: https://github.com/KnightOS/z80e
[mktiupgrade]: https://github.com/KnightOS/mktiupgrade
[tilp]: http://lpg.ticalc.org/prj_tilp/

96
recipes/ti84/glue.asm Normal file
View File

@ -0,0 +1,96 @@
.equ RAMSTART 0x8000
.equ RAMEND 0xbfff
.equ PORT_INT_MASK 0x03
.equ INT_MASK_ON 0x00
.equ PORT_INT_TRIG 0x04
.equ INT_TRIG_ON 0x00
.equ PORT_BANKB 0x07
jp boot
.fill 0x18-$
jp boot ; reboot
.fill 0x38-$
jp handleInterrupt
.fill 0x53-$
jp boot
; 0x0056
.db 0xFF, 0xA5, 0xFF
.fill 0x64-$
.inc "err.h"
.inc "core.asm"
.equ FNT_WIDTH 5
.equ FNT_HEIGHT 7
.inc "fnt/mgm.asm"
.inc "ti/lcd.asm"
.inc "ti/kbd.asm"
.equ STDIO_RAMSTART RAMSTART
.equ STDIO_GETC GetC
.equ STDIO_PUTC lcdPutC
.inc "stdio.asm"
.inc "parse.asm"
.equ SHELL_RAMSTART STDIO_RAMEND
.equ SHELL_EXTRA_CMD_COUNT 0
.inc "shell.asm"
boot:
di
ld hl, RAMEND
ld sp, hl
im 1
; enable ON key interrupt
in a, (PORT_INT_MASK)
set INT_MASK_ON, a
out (PORT_INT_MASK), a
ld a, 0x80
out (PORT_BANKB), a
ei
call lcdOff
; sleep until we press ON
halt
main:
call lcdInit
xor a
call lcdSetCol
call shellInit
jp shellLoop
GetC:
call waitForKey
jr boot
handleInterrupt:
di
push af
; did we push the ON button?
in a, (PORT_INT_TRIG)
bit INT_TRIG_ON, a
jp z, .done ; no? we're done
; yes? acknowledge and boot
in a, (PORT_INT_MASK)
res INT_MASK_ON, a ; acknowledge interrupt
out (PORT_INT_MASK), a
pop af
ei
jp main
.done:
pop af
ei
reti
FNT_DATA:
.bin "fnt/5x7.bin"

3
recipes/ti84/keys/02.key Normal file
View File

@ -0,0 +1,3 @@
4081396D55C0989BC949FA30821FFE61C9441EDC3827D0E89EEE16DDEF697634B8E10B8B7F42FE7CC1A7478606D6D09F6FE96365E71E3D2AAA7C8D91068F1DFAF3
20E1A6FD4557AB2234E92FACBBADD9E7FA2452B5C238F1EF296AFB2BFE67BACC1E
21A106BE04DC99B4F389D3B96951224E064F417E34EEF53130E9BEDC9A721EE1EB07

3
recipes/ti84/keys/04.key Normal file
View File

@ -0,0 +1,3 @@
408FE528B340EB1C88B505B2354BAADF47F3616D92CB532E7E5A2A0DFF1C4E4283CEEA2B2F7AD5F28B7E4BE4F3F4C99CABA0D98A8E5F2BE15E2AAC7CED0940EF82
20CDFF9610024DB1B7AD46D691E0E538BB00A1D840F5CCAF8EC0FED20C3A9D700B
21CB4662A9084F5076B117892EBA3FB0DF9EB24988A62A83890B5A0B4E18BD07720B

3
recipes/ti84/keys/0A.key Normal file
View File

@ -0,0 +1,3 @@
40B11C71D4EA2C13C9AB2E501C6085FEC87FF3B88BFD783EAC43351E1B10F65AD31C79C1268F75051DC8FC008EBF593AE5912E8B653975C13127E2B60A0BEF5FEF
204DD5B4E544CACBC4EF869CDA30A6908FF7D1BDDB92B1ADE1E1C93CC614904894
21F5E2DFBCA3D5C86F4815DC69452E4FC7D122D650374E880B62294279F21A439D01

3
recipes/ti84/keys/0F.key Normal file
View File

@ -0,0 +1,3 @@
40B11C71D4EA2C13C9AB2E501C6085FEC87FF3B88BFD783EAC43351E1B10F65AD31C79C1268F75051DC8FC008EBF593AE5912E8B653975C13127E2B60A0BEF5FEF
204DD5B4E544CACBC4EF869CDA30A6908FF7D1BDDB92B1ADE1E1C93CC614904894
21F5E2DFBCA3D5C86F4815DC69452E4FC7D122D650374E880B62294279F21A439D01

30
tools/font_compile.pl Executable file
View File

@ -0,0 +1,30 @@
#!/usr/bin/perl
use strict;
# This script converts "space-dot" fonts to binary "glyph rows". One byte for
# each row. In a 5x7 font, each glyph thus use 7 bytes.
my $fn = @ARGV[0];
unless ($fn =~ /.*(\d)x(\d)\.txt/) { die "$fn isn't a font filename" };
my ($width, $height) = ($1, $2);
print STDERR "Reading a $width x $height font.\n";
my $handle;
unless (open($handle, '<', $fn)) { die "Can't open $fn"; }
# We start the binary data with our first char, space, which is not in our input
# but needs to be in our output.
print pack('C*', (0) x $height);
while (<$handle>) {
unless (/( |\.){${width}}\n/) { die "Invalid line format '$_'"; }
my @line = split //, $_;
my $num = 0;
for (my $i=$width-1; $i>=0; $i--) {
if (@line[$width-$i-1] eq '.') {
$num += (1 << $i);
}
}
print pack('C', $num);
}

View File

@ -13,6 +13,7 @@ INCCFS=$(mktemp)
for p in "$@"; do
"${CFSPACK}" "${p}" "*.h" >> "${INCCFS}"
"${CFSPACK}" "${p}" "*.asm" >> "${INCCFS}"
"${CFSPACK}" "${p}" "*.bin" >> "${INCCFS}"
done
"${ZASMBIN}" "${INCCFS}"