Although Atom BASIC is an impressive achievement in terms of what can be crammed into just 8K of ROM, programmers may soon find it a chore to write programs with just 26 variables named A to Z. As memory prices fell, it became practical to provide more. The BBC micro had 16K for the OS ROM and another 16K for a far more advanced interpreter with the ability to define functions and procedures.
The BASIC makes well-defined calls to the OS, so porting the language only involves providing the OS functions. The Atom-to-BBC-BASIC upgrade board used the same BASIC ROM as the real BBC, but with a new 4K MOS ROM. Their binary code can be loaded into the RAM 'underneath' the Atom ROMs, then the Atom ROMs switched off before jumping to the new reset vector.
The hardware modifications require swapping the 16K at 4000 hex with the 16K at 8000 hex. This allows the BBC BASIC ROM to be seen at 8000 up, where it was in the BBC micro. The 6522 that was optional on the Atom must be fitted, and able to interrupt the CPU so that the new BBC OS can implement the ESC, TIME, and SOUND features.
The OS ROM expects the standard display modes of the 6847. To take advantage of the new display modes, which are more compatible with BBC display modes, the OS ROM would have to be modified. If located in RAM, there is plenty of scope for experimentation before committing it to Flash ROM.
The BBC micro had several hardware devices that are not present on the Atom or this project. Notably the UPD7002 Analogue to Digital converter, the 76477 sound generator, the speech chip, the Econent interface. Therefore the OS ROM does not implement the OS software to use them. The OS ROM is only 4K instead of 16K, so other features may simply have been unable to fit in there.
The FPGA design includes a control bit to change CPU's view of the memory map to match the Atom to BBC BASIC upgrade board. Note that the video circuit and RAM paging stay the same, to avoid design complications.
Getting the firmware into the project is a little tricky. The existing LPT to Atom program simply sends Atom BASIC command lines. The upgrade ROM code is 16K plus 4K of binary. It is impractical to convert this to a text file of poke commands by hand, but a small PC utility can do this. There are other possible ways, such as re-vectoring the Atom's tape input routines to collect binary from the LPT slave port, or transfer files as intel hex files, but are harder to do.
The utility for binary to RAM-poke commands has been written and the output has been used to poke the firmware into paged RAM. As a bonus, it can also be used to load utilities and DOS.
The BBC-mode memory map hardware definitely re-maps the CPU's view of the system, and a small assembly program has verified this.
The system seems to have some problems, in that it can crash when switching modes. Suspecting the mode selection took some time to settle I added a nop code or two to delay the CPU before accessing the switched RAM. This improved things a little but not completely.
LFFBA: lda VEC_98
VDUCHR: plp
pla
sec
OSEVEN: sbc #$01
sta VAR_FD
pla
sbc #$00
sta VAR_FD+1
NVRDCH: jmp (BRKV)
NVWRCH: jmp (IRQ2V)
OSFIND: jmp (FINDV)
OSGBPB: jmp (GBPBV)
OSBPUT: jmp (BPUTV)
OSBGET: jmp (BGETV)
OSARGS: jmp (ARGSV)
OSFILE: jmp (FILEV)
OSRDCH: jmp (RDCHV)
OSASCI: cmp #$0D
bne OSWRCH
OSNEWL: lda #LF
jsr OSWRCH
lda #CR
OSWRCH: jmp (WRCHV)
OSWORD: jmp (WORDV)
OSBYTE: jmp (BYTEV)
OSCLI: jmp (CLIV)
hw_nmi_vec: .word HANDLER_NMI
hw_res_vec: .word HANDLER_RESET
hw_irq_vec: .word HANDLER_IRQ
HANDLER_RESET:
ldx #$19
LFF1A: lda TBL_DEFAULT_VECTORS,x
sta IRQ1V,x
dex
bpl LFF1A
txs
txa
inx
stx $EA
stx ROW_MULT_TAB_PTR+1
stx $E7
lda #$0A
sta VAR_FD+1
lda #$8A
sta IO_SYS_PIA_CONTROL
lda #$07
sta IO_SYS_PIA_PORT_C
PRINT_BBC_BASIC:
jsr PRINT_IMMEDIATE
.byte $06,$0C,$0F
.text "BBC BASIC"
.byte $0A,$0A,$0D
lda #$0E
sta IO_SYS_VIA_T1_C_L
lda #$27
sta IO_SYS_VIA_T1_C_L+1
lda #$40
sta IO_SYS_VIA_AUX_CONTROL
lda #$C0
sta IO_SYS_VIA_IE
lda #$00
ldx #$04
LFF64: sta W_GFX_WIN_LEFT,x
dex
bpl LFF64
sta GFX_CUR_V_LAST
sta GFX_CUR_V_LAST+1
sta BUFFER_0100_LESS_1
lda #$0E
sta VAR_FD
lda #$80
sta VAR_FD+1
lda $C000
cmp #$AA
bne LFF85
jsr LC001
cli
LFF85: jmp ENTRY_PAGED_ROM
PRINT_IMMEDIATE:
pla; sta STRING_POINTER
pla; sta STRING_POINTER+1
PRINT_IMMEDIATE_LOOP:
ldy #$00 ; y is zero throughout
inc STRING_POINTER
bne PRINT_IMMEDIATE_SKIP
inc STRING_POINTER+1
PRINT_IMMEDIATE_SKIP:
lda (STRING_POINTER),y
bmi PRINT_IMMEDIATE_EXIT
jsr OSWRCH
jmp PRINT_IMMEDIATE_LOOP
PRINT_IMMEDIATE_EXIT:
jmp (STRING_POINTER)
OSWRCH: jmp (WRCHV)
DO_WRCH:php
cld
stx VE4_BYTE_TEMP_X
sty VE5_BYTE_TEMP_Y
KEY_WAIT_FOR_RELEASE:
bit IO_SYS_PIA_PORT_C ; is repeat key pressed?
bvc KEY_RELEASED ; bit 6 of port C
jsr KBD_SCAN ; yes, scan again to debounce
bcc KEY_WAIT_FOR_RELEASE
KEY_RELEASED:
jsr WAIT_100_MS
KBD_SCAN_LOOP:
jsr KBD_SCAN
bcs KBD_SCAN_LOOP
jsr KBD_SCAN
bcs KBD_SCAN_LOOP
LFE8A: tya
ldx #$17 ; final in 24-byte table
jsr CHK_FOR_CTRL
LFE90: lda TABLE_FEBC,x
sta VE2_WORD_PTR
lda #$FD ; MSbyte of all printing routines
sta VE2_WORD_PTR+1
tya
jmp (VE2_WORD_PTR) ; jumps to printing routine
CHK_FOR_CTRL_AGAIN:
dex
CHK_FOR_CTRL:
cmp TABLE_FEA4,x
bcc CHK_FOR_CTRL_AGAIN
rts
TABLE_FEA4:
.byte $00,$08,$09,$0A,$0B,$0C,$0D,$0E
.byte $0F,$1E,$7F,$00,$01,$05,$06,$08
.byte $0E,$0F,$10,$11,$1C,$20,$21,$3B
TABLE_FEBC:
.byte <LFD1D, ; INVERT_CHAR
<LFD35, ; KEY_BS
<LFD11, ; INC_CUR_POSN
<LFD3B, ; KEY_LF
<LFD60, ; KEY_VT
<LFD42, ; KEY_FF
<LFD19, ; PRINTING_FD19
<LFD66 ; KEY_S0
.byte <LFD6B, ; KEY_S1
<LFD56, ; KEY_RS
<LFD29, ; DO_DELETION
<LFDB8, ; KEY_CNV_TST
<LFDAB, ; KEY_21_24
<LFD73, ; KEY_SHIFT_LOCK
<LFD7B, ; KEY_CURSOR_CTRL
<LFDBB ; KEY_TEST_CTRL
.byte <LFD87, ; KEY_COPY <LFD99, ; KEY_DEL <LFDB8, ; KEY_CNV_TST <LFDB1, ; KEY_20 <LFDAF, ; KEY_3C_3F <LFDA1, ; KEY_20 <LFD9F, ; KEY_21_3A <LFD9B ; KEY_5B_5F