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