I find it vexing that I have not yet figured out the RAM banking scheme. Some things:
- at reset, the peripheral configuration registers and internal RAM are mapped at 0000h. They can be moved elsewhere, but are not. The RAM at 40-ff is partitioned into 40-bf is 128 bytes of data, and c0-ff is 64 bytes of stack.
- I can see writes at 0x0100+. Right after that internal memory. It would be a bit of a challenge in external support circuitry to map the external RAM right smack against the internal RAM. Much more sensible would be to map the external RAM to somewhere, say, 4000h, and let from 16 KiB to 48 KiB be a 32 KiB 'page' of RAM in the 128 KiB chip. The decoding logic is easier. (I do not know that the design realizes 32 KiB RAM mappings -- it could be much smaller -- but I am just guessing with this minimal design that less hardware is better, and that is probably the largest power-of-two subdivision of 128 KiB for this 16-bit address space.) But the reads and writes are there nonetheless.
- Could it be that the designers simply chose to 'waste' the first 256 bytes of each page? Because the internal config registers and RAM will be selected in preference to external when ambiguity arises. 256 * 4 = 1024. Maybe they didn't care about wasting 1 KiB of 128 KiB in the interest of making the hardware design cheaper.
- At the same time, the INIT register provides for re-mapping the config regs and also the internal ram elsewhere on a 4 KiB boundary, so those could have simply been moved and then all the RAM would be available. There are 166 padding bytes, so there's code space for a simple setting of that register. On the other hand, moving those registers will make all reference to such 16-bit instead of 8-bit (a privilege of being mapped to the first 256 bytes with special instructions for such accesses). So maybe it was deemed not worth it (or even not possible with the ROM size constraints).
Still, I also see writes to 8000h. If the '32 KiB pages mapped to 0000h' hypothesis holds, then what is going on at 8000h? Mysteries to be solved...
One thing I did find was this code:
EC60 sub_EC60:
EC60 85 01 bita #1
EC62 26 05 bne flick3high_EC69
EC64 15 00 08 bclr PORTA_0 8 ; PA3 low
EC67 20 03 bra cont_EC6C
EC69 flick3high_EC69:
EC69 14 00 08 bset PORTA_0 8 ; PA3 high
EC6C cont_EC6C:
EC6C 85 02 bita #2
EC6E 26 05 bne flick5high_EC75
EC70 15 00 20 bclr PORTA_0 $20 ; ' ' ; PA5 low
EC73 20 03 bra leave_EC78
EC75 flick5high_EC75:
EC75 14 00 20 bset PORTA_0 $20 ; ' ' ; PA5 high
EC78 leave_EC78:
EC78 39 rts
This essentially maps bits 1,0 in the A reg into bits 5,3 in the GPIO port A. OK. Well, you have to know a little bit about port A from the manual. Port A has 3 output-only pins, 3 input only pins, and two bidirectional pins. Moreover, two of the pins are not bonded out on this 40-pin DIP device. Bit 5 is output only, Bit 3 is bi-di, but configured for output. Bits 6 and 4 are not bonded.
There are several references to this code, but one of note is at F723:
F723 sub_F723:
F723 18 CE 01 00 ldy #$100
F727 8D 0F bsr sub_F738 ; XXX store 'ram valid sig' @ Y
F729 86 03 ldaa #3
F72B BD EC 60 jsr sub_EC60 ; XXX set PA5,3 from A b1,0
F72E 18 CE 7F DF ldy #$7FDF
F732 8D 04 bsr sub_F738 ; XXX store 'ram valid sig' @ Y
F734 BD EC 79 jsr sub_EC79 ; XXX clear PAb5,3
F737 39 rts
This seems to want to store a textual 'signature' at the beginning and end, assuming that mapped memory cannot access the first 256 bytes (hence the #$100 start). This textual signature ("This is the RAM valid signatur2") is 31 bytes. (32 with nul, but nul is not copied). I don't know why the end starts at 7FDF instead of 7FE0.
But curious to me is that there is the interceding call to sub_EC60 before writing the 'final' signature. Also that there is no effort from an analogous method to set P5,3 into a known state before writing the signature at $100.
This routine is called once during system bootup, and perhaps can make assumptions about the PAb5,3 state as being '00'.
I found another routine:
EC79 sub_EC79:
EC79 15 00 08 bclr PORTA_0 8 ; clear PAb3
EC7C 15 00 20 bclr PORTA_0 $20 ; ' ' ; clear PAb5
EC7F 39 rts
Which explicitly sets those pins to '00'. This routine is called quite a bit -- more (17) in fact than the other that selects other pages (12), so I think the system likes to keep the mapping 'parked' at page 0, venturing out to other pages only as-needed.
It's interesting that there is a dedicated 'select page 0' method, when the 'select page A' method would work just fine with 0 in A, but I suspect this is for some flash space economy. There is only 166 free bytes. To replace 17 calls to ones that first clear A and call the general purpose paging routine would rack up more bytes than just calling this routine. (Also, registers are unaffected, so there's some other overhead that might be incurred in using the general purpose routine.)
This ROM is a bit tight for space, and there's some dead code I have found and other opportunities here and there to save some space, but I'm sure no-one is interested in a code review 28 years hence from product launch! It worked well enough at the time...
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.