Skip to content

Commit

Permalink
video: add a feature to upgrade the video board firmware via Recovery
Browse files Browse the repository at this point in the history
Fix a bug in the keyboard driver that resulted in corrupted NOR flash.
On boot, if the video board is in recovery mode, then the bootloader will
automatically run the flasher on the UART.
Add a new entry in the menu to flash the video board firmware. The firmware needs
to be sent via UART, just like NOR flash programming.
  • Loading branch information
Zeal8bit committed Apr 20, 2024
1 parent cd82532 commit 761dbed
Show file tree
Hide file tree
Showing 12 changed files with 753 additions and 132 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ ifeq ($(CONFIG_ENABLE_TESTER),1)
FILES += tester.asm
endif

ifneq ($(CONFIG_UART_AS_STDOUT),1)
FILES += video.asm keyboard.asm
ifeq ($(CONFIG_ENABLE_VIDEO_BOARD),1)
FILES += video.asm video_board.asm keyboard.asm stdout.asm
endif

define FIND_ADDRESS =
Expand Down
7 changes: 4 additions & 3 deletions include/config.asm
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
IFNDEF CONFIG_H
DEFINE CONFIG_H

; When set, the UART will be used as the standard output. When not set or set to 0, the video driver will
; be used. The UART driver will still be used to receive files.
DEFC CONFIG_UART_AS_STDOUT = 1
; When set, the video board will be used as the default standard output. In that case,
; the UART will still be used for receiving files and sending some info messages.
; If not set, the UART driver will the standard output.
DEFC CONFIG_ENABLE_VIDEO_BOARD = 1

; When set, the Zeal logo will be shown on screen, this takes more RAM at runtime but won't affect the
; OS or program running after the bootloader as the modified tiles are saved and restored.
Expand Down
29 changes: 20 additions & 9 deletions include/stdout_h.asm
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
DEFINE STDOUT_H

; It is possible to choose either the UART or video board as the standard output
IF CONFIG_UART_AS_STDOUT
IF !CONFIG_ENABLE_VIDEO_BOARD
INCLUDE "uart_h.asm"

DEFC stdout_initialize = uart_initialize
Expand All @@ -35,21 +35,32 @@
DEFM 0x1b, "[0m"
ENDM

ELSE ; !CONFIG_UART_AS_STDOUT
ELSE ; CONFIG_ENABLE_VIDEO_BOARD

; In case we have the video board, it may be possible to switch back to
; to the UART as standard output if the video board fails to boot.
INCLUDE "video_h.asm"
INCLUDE "keyboard_h.asm"
INCLUDE "uart_h.asm"

DEFC stdout_initialize = video_initialize
DEFC STDOUT_DRIVER_UART = 0
DEFC STDOUT_DRIVER_VIDEO = 1

; When the video board is enabled, we can fallback the standard input to UART
; Parameters:
; A - New driver to select, STDOUT_DRIVER_UART OR STDOUT_DRIVER_VIDEO
EXTERN std_set_driver
EXTERN stdout_initialize
EXTERN stdout_write
EXTERN stdout_put_char
EXTERN stdout_newline
DEFC stdout_autoboot = video_autoboot
DEFC stdout_write = video_write
DEFC stdout_put_char = video_put_char
DEFC stdout_newline = video_newline
DEFC stdin_get_char = keyboard_next_char
DEFC stdin_has_char = keyboard_has_char
DEFC stdin_set_synchronous = keyboard_set_synchronous
DEFC stdout_prepare_menu = video_clear_screen

EXTERN stdin_get_char
EXTERN stdin_has_char
EXTERN stdin_set_synchronous

; Use a prefix for the colors
MACRO YELLOW_COLOR _
DEFM 0xFE
Expand Down
4 changes: 3 additions & 1 deletion src/boot.asm
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ bootloader_entry:
ldir

call sys_table_init
call stdout_initialize
; UART will be used to receive files in all cases
call uart_initialize
call pio_initialize
IF CONFIG_ENABLE_VIDEO_BOARD
call stdout_initialize
ENDIF ; CONFIG_ENABLE_VIDEO_BOARD

; Ready to send and receive data over UART, show welcome message
ld hl, start_message
Expand Down
112 changes: 72 additions & 40 deletions src/keyboard.asm
Original file line number Diff line number Diff line change
Expand Up @@ -9,68 +9,99 @@

SECTION BOOTLOADER

; Receive a character from the keyboard (synchronous, blocking)
; Parameters:
; None
; Receive a character from the keyboard, non-blocking version
; Returns:
; A - ASCII byte received
; A - 0 if no valid character was received, character value else
; Alters:
; A, B, DE
PUBLIC keyboard_next_char
keyboard_next_char:
xor a
ld (received), a

PUBLIC keyboard_get_char
keyboard_get_char:
ld de, received

_keyboard_get_char_loop:
ld a, (de)
; A, B, HL, DE
PUBLIC keyboard_get_char_nonblocking
keyboard_get_char_nonblocking:
ld hl, received
ld b, 0
; Atomic test and set
di
ld a, (hl)
ld (hl), b
ei
or a
jr z, _keyboard_get_char_loop
; Check if it's release key
ret z
; Make HL point to the 'flag' variable
inc hl
; Set a flag if release key
cp KB_RELEASE_SCAN
jr z, _release_scan
; Character is not a "release command"
; Check if the character is a printable char
push hl
jr z, _release_scan_received
; Check if we received a release scan previously
ld b, (hl)
; Check if flag is 0
inc b
dec b
jr nz, _flag_not_zero
; Flag is not 0, we just received a real character, parse it
; Check if it is a printable character
cp KB_PRINTABLE_CNT - 1
jp nc, _special_code ; jp nc <=> A >= KB_PRINTABLE_CNT - 1
; Save the scan size in B
ld hl, base_scan
ld b, base_scan_end - base_scan
jr get_from_scan
jr _get_from_scan
_special_code:
; Special character is still in A
cp KB_EXTENDED_SCAN
jr z, _pop_ret
add -KB_SPECIAL_START
sub KB_EXTENDED_SCAN
; Ignore extended scan characters for now, return 0
ret z
; We just subtracted KB_EXTENDED_SCAN, add it back
add KB_EXTENDED_SCAN-KB_SPECIAL_START
ld hl, special_scan
ld b, special_scan_end - special_scan
get_from_scan:
_get_from_scan:
; Check if there would be an overflow
cp b
; If there no carry, A is equal or bigger than the length
jr nc, _overflow_pop_continue
; If there no carry, A is equal or bigger than the length, consider this
; an invalid character, return 0
jr nc, _overflow_ret_zero
; Get the value of A from the scan table pointed by HL
add l
ld l, a
adc h
sub l
ld h, a
ld a, (hl)
_pop_ret:
pop hl
ret
_overflow_pop_continue:
pop hl
jr _keyboard_get_char_loop
_overflow_ret_zero:
xor a
ret
_flag_not_zero:
; Clear the flag and ignore the current character, return 0
xor a
; Fall-through
_release_scan_received:
; Set the flag to a non-zero value
ld (hl), a
; Return not-valid character
xor a
ret


_release_scan:
; Ignore the next character
call keyboard_next_char
; Return the next character
jp keyboard_next_char
; Receive a character from the keyboard (synchronous, blocking)
; Parameters:
; None
; Returns:
; A - ASCII byte received
; Alters:
; A, B, DE
PUBLIC keyboard_next_char
keyboard_next_char:
; Clear the previously received keys
xor a
ld (received), a
push hl
_keyboard_next_char_loop:
call keyboard_get_char_nonblocking
or a
; If character is invalid, continue the loop
jr z, _keyboard_next_char_loop
pop hl
ret

base_scan:
DEFB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\t', '`', 0
Expand Down Expand Up @@ -120,4 +151,5 @@ keyboard_int_handler:


SECTION BSS
received: DEFS 1
received: DEFS 1
flag: DEFS 1
Loading

0 comments on commit 761dbed

Please sign in to comment.