Terminal program for MailStation devices
1; vim:syntax=z8a:ts=8
2;
3; msTERM
4; crt0
5;
6; Copyright (c) 2019 joshua stein <jcs@jcs.org>
7;
8; Permission to use, copy, modify, and distribute this software for any
9; purpose with or without fee is hereby granted, provided that the above
10; copyright notice and this permission notice appear in all copies.
11;
12; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18; OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19;
20
21 .module crt0
22
23 .include "mailstation.inc"
24 .globl _main
25
26 .area _HEADER (ABS)
27
28 .org RUN_ADDR
29start:
30 jp boot
31
32 .dw (icons)
33 .dw (caption)
34 .dw (dunno)
35
36dunno:
37 .db #0
38xpos:
39 .dw #0
40ypos:
41 .dw #0
42caption:
43 .dw #0x0001 ; ?
44 .dw (endcap - caption - 6) ; number of chars
45 .dw #0x0006 ; offset to first char
46 .ascii "msTERM" ; the caption string
47endcap:
48
49icons:
50 .dw (icon2 - icon1) ; size of icon1
51 .dw (icon1 - icons) ; offset to icon1
52 .dw (iconend - icon2) ; size of icon2
53 .dw (icon2 - icons) ; offset to icon2
54
55icon1:
56 .dw #0x0022 ; icon width (34, 5 bytes per row)
57 .db #0x22 ; icon height (34)
58
59 .db #0x00, #0x00, #0x00, #0x00, #0x00 ; ..................................
60 .db #0x00, #0x00, #0x00, #0xe0, #0x03 ; .............................#####
61 .db #0x00, #0x00, #0x00, #0x20, #0x02 ; .............................#...#
62 .db #0x00, #0x00, #0x00, #0xa0, #0x02 ; .............................#.#.#
63 .db #0x00, #0x00, #0x00, #0xa0, #0x02 ; .............................#.#.#
64 .db #0x00, #0x00, #0x00, #0xa0, #0x02 ; .............................#.#.#
65 .db #0x00, #0x00, #0x00, #0xe0, #0x03 ; .............................#####
66 .db #0x00, #0x00, #0x00, #0x80, #0x00 ; ...............................#..
67 .db #0x00, #0xff, #0xff, #0x63, #0x00 ; ........##################...##...
68 .db #0x00, #0x01, #0x00, #0x12, #0x00 ; ........#................#..#.....
69 .db #0x00, #0x01, #0x00, #0x12, #0x00 ; ........#................#..#.....
70 .db #0x00, #0x01, #0x00, #0x0a, #0x00 ; ........#................#.#......
71 .db #0xe0, #0x01, #0x00, #0x1e, #0x00 ; .....####................####.....
72 .db #0xf0, #0x01, #0x00, #0x3e, #0x00 ; ....#####................#####....
73 .db #0xf0, #0x01, #0x00, #0x36, #0x00 ; ....#####................##.##....
74 .db #0xf8, #0xff, #0xff, #0x7f, #0x00 ; ...############################...
75 .db #0xa8, #0x92, #0x24, #0x55, #0x00 ; ...#.#.#.#..#..#..#..#..#.#.#.#...
76 .db #0xfc, #0xff, #0xff, #0xff, #0x00 ; ..##############################..
77 .db #0x54, #0x55, #0x55, #0x95, #0x00 ; ..#.#.#.#.#.#.#.#.#.#.#.#.#.#..#..
78 .db #0xfe, #0xff, #0xff, #0xff, #0x01 ; .################################.
79 .db #0xaa, #0xaa, #0xaa, #0x2a, #0x01 ; .#.#.#.#.#.#.#.#.#.#.#.#.#.#.#..#.
80 .db #0xfe, #0xff, #0xff, #0xff, #0x01 ; .################################.
81 .db #0x53, #0x55, #0x55, #0x15, #0x03 ; ##..#.#.#.#.#.#.#.#.#.#.#.#.#...##
82 .db #0xff, #0xff, #0xff, #0xff, #0x03 ; ##################################
83 .db #0x26, #0x00, #0x00, #0xa8, #0x01 ; .##..#.....................#.#.##.
84 .db #0xfc, #0xff, #0xff, #0xff, #0x00 ; ..##############################..
85 .db #0x00, #0x00, #0x00, #0x00, #0x00 ; ..................................
86 .db #0x00, #0x00, #0x00, #0x00, #0x00 ; ..................................
87 .db #0x00, #0x00, #0x00, #0x00, #0x00 ; ..................................
88 .db #0x00, #0x00, #0x00, #0x00, #0x00 ; ..................................
89 .db #0x00, #0x00, #0x00, #0x00, #0x00 ; ..................................
90 .db #0x00, #0x00, #0x00, #0x00, #0x00 ; ..................................
91 .db #0x00, #0x00, #0x00, #0x00, #0x00 ; ..................................
92 .db #0x00, #0x00, #0x00, #0x00, #0x00 ; ..................................
93
94icon2:
95 ; not used
96 .dw #0x0000 ; width
97 .db #0x00 ; height
98iconend:
99
100boot:
101 xor a
102 out (#0x0d), a ; put the cpu in its highest speed
103
104 ; all of our code expects to run in ram so when we're running from
105 ; dataflash, we have to copy our page of flash into ram, then jump to
106 ; it
107
108 ; swap in a page of ram
109 ld a, #DEVICE_RAM
110 out (#SLOT_DEVICE), a
111 out (#SLOT_PAGE), a
112
113 ; copy ourselves into ram
114 ld de, #SLOT_ADDR
115 ld hl, #RUN_ADDR
116 ld bc, #0x4000
117 ldir ; ld (de), (hl), de++, hl++, bc--
118
119 jp SLOT_ADDR + (hijump - start)
120
121hijump:
122 ; PC is now in SLOT_ADDR, put our new RAM page into RUN_DEVICE/PAGE
123 out (#RUN_DEVICE), a
124 out (#RUN_PAGE), a
125
126 ; then jump back there
127 jp RUN_ADDR + (lojump - start)
128
129lojump:
130 call find_shadows
131 call _main ; main c code
132 jp _exit
133
134; set location of port shadow variables depending on firmware version
135find_shadows:
136 ld a, (#0x0037) ; firmware major version
137 cp #0x1
138 jr z, ver_1
139 cp #0x2
140 jr z, ver_2
141 cp #0x3
142 jr z, ver_3
143unrecognized_firmware: ; we can't blink because that requires
144 jp 0x0 ; port and fw function addresses
145ver_1:
146 ld a, (#0x0036) ; firmware minor version
147 cp #0x73
148 jr z, ver_1_73
149 jr unrecognized_firmware
150ver_1_73: ; eMessage 1.73CID
151 ld hl, #p2shadow
152 ld (hl), #0xdb9f
153 ld hl, #p3shadow
154 ld (hl), #0xdba0 ; TODO: verify
155 ret
156ver_2:
157 ld a, (#0x0036) ; firmware minor version
158 cp #0x53
159 jr z, ver_2_53
160 jr ver_2_54 ; else, assume 2.54
161ver_2_53: ; MailStation 2.53
162 ld hl, #p2shadow
163 ld (hl), #0xdba1
164 ld hl, #p3shadow
165 ld (hl), #0xdba2
166 ld hl, #p28shadow
167 ld (hl), #0xdba0
168 ret
169ver_2_54: ; MailStation 2.54
170 ld hl, #p2shadow
171 ld (hl), #0xdba2
172 ld hl, #p3shadow
173 ld (hl), #0xdba3
174 ld hl, #p28shadow
175 ld (hl), #0xdba0
176 ret
177ver_3: ; MailStation 3.03
178 ld hl, #p2shadow
179 ld (hl), #0xdba5
180 ld hl, #p3shadow
181 ld (hl), #0xdba6
182 ret
183
184 .area _DATA
185
186; shadow locations
187p2shadow:
188 .dw #0xdba2
189p3shadow:
190 .dw #0xdba3
191p28shadow:
192 .dw #0xdba0
193delay_func:
194 jp 0x0a5c
195
196_msTERM_version::
197 .db #VERSION
198_debug0::
199 .db #0
200_debug1::
201 .db #0
202_debug2::
203 .db #0
204_debug3::
205 .db #0
206_debug4::
207 .db #0
208
209 .area _CODE
210
211; exit handler, restart
212_exit::
213 call _reboot
214
215_powerdown::
216 di
217 call #0x0a6b ; firmware powerdown function
218 jp _panic ; in case we fail to powerdown somehow
219
220_reboot::
221 jp 0x0000
222
223; new_mail(unsigned char on)
224; toggles 'new mail' light
225_new_mail::
226 di
227 push ix
228 ld ix, #0
229 add ix, sp
230 push hl
231 push af
232 ld a, 4(ix)
233 cp #0
234 ld hl, (p2shadow)
235 jr z, light_off
236light_on:
237 ld a, (hl)
238 set 4, a
239 jr write_p2
240light_off:
241 ld a, (hl)
242 res 4, a
243write_p2:
244 ld (hl), a
245 out (#0x02), a ; write p2shadow to port2
246 pop af
247 pop hl
248 pop ix
249 ei
250 ret
251
252; delay(unsigned int millis)
253; call mailstation function that delays (stack) milliseconds
254_delay::
255 push ix
256 ld ix, #0
257 add ix, sp
258 push af
259 push bc
260 push hl
261 ld l, 4(ix)
262 ld h, 5(ix)
263 push hl
264 call delay_func
265 pop hl
266 pop hl
267 pop bc
268 pop af
269 pop ix
270 ret
271
272; blink(unsigned int millis)
273; turn new mail LED on, wait millis, turn it off, wait millis
274_blink::
275 push ix
276 ld ix, #0
277 add ix, sp
278 push hl
279 ld l, #1
280 push hl
281 call _new_mail ; turn it on
282 pop hl
283 ld l, 4(ix)
284 ld h, 5(ix)
285 push hl
286 call _delay ; wait
287 pop hl
288 ld l, #0
289 push hl
290 call _new_mail ; turn it off
291 pop hl
292 ld l, 4(ix)
293 ld h, 5(ix)
294 push hl
295 call _delay ; wait
296 pop hl
297 pop af
298 pop ix
299 ret
300
301; void panic(void)
302_panic::
303 ld hl, #200
304 push hl
305 call _blink
306 pop hl;
307 jr _panic
308
309; void lcd_sleep(void)
310; turn the LCD off
311_lcd_sleep::
312 di
313 push hl
314 ld hl, (p2shadow)
315 ld a, (hl)
316 and #0b01111111 ; LCD_ON - turn port2 bit 7 off
317 ld (hl), a
318 out (#0x02), a ; write p2shadow to port2
319 pop hl
320 ei
321 ret
322
323
324; void lcd_wake(void)
325; turn the LCD on
326_lcd_wake::
327 di
328 push hl
329 ld hl, (p2shadow)
330 ld a, (hl)
331 or #0b10000000 ; LCD_ON - turn port2 bit 7 on
332 ld (hl), a
333 out (#0x02), a ; write p2shadow to port2
334 pop hl
335 ei
336 ret
337
338; unsigned char read_port(unsigned char port)
339_read_port::
340 push ix
341 ld ix, #0
342 add ix, sp
343 push af
344 push bc
345 ld b, #0
346 ld c, 4(ix)
347 in l, (C)
348 ld h, #0
349 pop bc
350 pop af
351 pop ix
352 ret
353
354
355; 8-bit multiplication
356; de * a = hl
357mult8::
358 ld b, #8
359 ld hl, #0
360mult8_loop:
361 add hl, hl
362 rlca
363 jr nc, mult8_noadd
364 add hl, de
365mult8_noadd:
366 djnz mult8_loop
367mult8_out:
368 ret
369
370; 16-bit multiplication
371; bc * de = hl
372mult16:
373 ld a, b
374 ld b, #16
375 ld hl, #0
376mult16_loop:
377 add hl, hl
378 sla c
379 rla
380 jr nc, mult16_noadd
381 add hl, de
382mult16_noadd:
383 djnz mult16_loop
384 ret
385
386
387; 8-bit division
388; divide e by c, store result in a and remainder in b
389div8:
390 xor a
391 ld b, #8
392div8_loop:
393 rl e
394 rla
395 sub c
396 jr nc, div8_noadd
397 add a, c
398div8_noadd:
399 djnz div8_loop
400 ld b,a
401 ld a,e
402 rla
403 cpl
404 ret
405
406; 16-bit division
407; divide bc by de, store result in bc, remainder in hl
408div16:
409 ld hl, #0
410 ld a, b
411 ld b, #8
412div16_loop1:
413 rla
414 adc hl, hl
415 sbc hl, de
416 jr nc, div16_noadd1
417 add hl, de
418div16_noadd1:
419 djnz div16_loop1
420 rla
421 cpl
422 ld b, a
423 ld a, c
424 ld c, b
425 ld b, #8
426div16_loop2:
427 rla
428 adc hl, hl
429 sbc hl, de
430 jr nc, div16_noadd2
431 add hl, de
432div16_noadd2:
433 djnz div16_loop2
434 rla
435 cpl
436 ld b, c
437 ld c, a
438 ret