Tervetuola! The purpose of this page is to give a specification on the Commodore LCD machine. If you don't know what it is, visit this link first.
Important: it seems there are more Commodore LCD versions! This document and my emulator is about the version I have ROM images of. Any help would be nice to get the ROM images of the "other version" though. Also in general: any help about any information on this site (including the documentation, and the emulator) is welcome!
I write this documentation from partly the experiences got from my own Commodore LCD emulator and my try to disassembly the KERNAL of this machine, but still; it would be impossible without some great guys who helped me in various ways! Big thanks to them! Without them there would be no usuable emulator and not a detailed specification like this. Also as they are (as far as I know) the actual designers of the Commodore LCD, I must thank for their original work as well, it's a shame that this machine was never released, it would haven been a great hit in its time, I am quite sure. However never underestimate the power of time: it's not so easy to get information, find documentations or even just remembering things happened many years ago, especially if they're technical details ... That's even an important factor me to try to collect information and write an emulator before everything fades out totally, this machines deserves to be saved at least in this form.
As usual, information on this site should be considered as "may be" and shouldn't be trusted blindly! Also, I often update this page (last section on this page tries to summarize the changes) in case of corrections, new findings or information. If you have any idea what I can write about, or you have more information, possible corrections, please tell me. Contact for me can be found on this page.
Sorry for my not-so-perfect English / typos in advance.
It's important to mention: there is a seems-to-be nice PDF describes the Commodore LCD. However as it turned out for me, that PDF is not about the "final" (well ...) Commodore LCD. As far as I can imagine, it was a very early proof-of-concept design, and the actual design went into a different direction at the end. To demonstrate the differences, here are some:
Anyway, if you're interested, here is the link.
The rest of the document is not based on this document, but on the actual situation seems to be true for the real machine what we have ROM images for. This document was even a bit confusing for me, when I started to write my emulator I find the "display port" where ASCII/PETSCII values are written to be displayed (as I know now, Commodore LCD uses memory mapped video RAM), and when I found a location which seems to be often meanigful to form understandable text, I thought it was. However it was only an MMU register, the "dummy write" style (ie, it's not important what you write there just the fact of writing itself).
It's very important to note, that specifications should never been treated as fully correct. See the previous section for an example (I thought it's the actual specification at the beginning of the project). But even seems-to-be more correct information resources can have problems. For example the documentation I managed to get was about the VIA pin usage by the RTC chip. It took me hours to try to emulate this, but it didn't worked. After watching the KERNAL disassembly list for a long time, I had the idea that WR and RD are exchanged in the table. And bingo, it was the problem, the specification had this "minor" fault. Also the RTC chip, besides the type, it seems some registers are not at the "right" position. In these cases, I always modified my emulator to work with the known-to-be-real ROM images. However, it's still possible that for example the KERNAL is incorrect and had bugs, since the Commodore LCD was not released yet, thus we may have to consider the possibility it's not production ready code, and have faults of its own.
My specification (this page) is an odd mix: it contains information which is more or less only guessed by me, but it also contains actual "facts" written by seems-to-be-official specification. As I've stated, even those seem to contain bugs (or it's the KERNAL's?) so I tried to present the correct information here.
In nutshell: I try my best, but I can't guarantee that this specification is fully correct. But the opposite, I am very sure it's not ...
You should also read the page of my emulator, there are some known bugs mentioned there.
Name of the computer is "Commodore LCD". Since just saying "LCD" can be confusing (is it about the whole machine or just the LCD display/controller of it?), I will name it as "CLCD" for being short. However, it seems, some documents mention it as "LCDC" instead of probably for "LCD Commodore" or "LCD Computer"?
As Commodore LCD was never released and it's told only two (or four?) "fully assembled" units exist, thus it's not so realistic as with other machines: if you want to write an emulator and you have question, try it out on the real "iron"! As I am not so rich to try to buy one of the existing Commodore LCD machines (but I am open to get one as a gift - ok, back to the serious parts ...), my only choices:
To be clear: I've tried all the methods above in paralell to achieve some progress. This is also an answer for the qestion: why my documents are quite inconsistent: it's possible that some sections or pages contain outdated information got from another source, my guesswork or from understanding the ROM disassembly, while I write about newer information at the other place. I'll try to fix these kind of errors though.
Again: thanks to all the people who helped me in collecting information!
You can try an emulated CLCD out with my emulator.
The CPU seems to be 65C102 though some sources mention 65C02. I guess, it does not matter too much, as 65C02 and 65C102 are software compatible. My emulator doesn't (or didn't, it depends when you read this ...) emulate bit oriented new opcodes compared to NMOS 6502, only TSB/TRB and new immediate addressing mode of BIT. So no SMB/RMB/BBR/BBS. It would stop the emulation with fatal error in case of an unemulated opcode, but it didn't happened with the original ROM images. For me it's always confusing what is 65C02 and 65SC02 opcodes and various extensions (like "GTE") so I wouldn't judge here.
The CPU clock is also interesting. 1MHz and 2MHz can be seen as well. I assume 1MHz is the right, as the ROM dissasembly suggested that (because of the software TOD updating and the used value to generate IRQ with the help of VIA's timer).
The physical memory address space of CLCD is 256K width (as I thought too from the usage of $FF00 from disassembly) and it's constructed like this:
Phys. addr | Content |
---|---|
28000 - 3FFFF |
96K internal ROM (KERNAL and applications) |
24000 - 27FFF |
16K applications ROM socket |
20000 - 23FFF |
16K spare for disk/wafer tape/exp I/O |
10000 - 1FFFF |
64K expansion ROM or RAM |
08000 - 0FFFF |
32K internal expansion RAM |
00000 - 07FFF |
32K internal RAM ("video/shared ram") |
Video ram means in the table: the LCD controller can only access this RAM (regardless of the MMU state, see later). It seems this RAM area is shared between the LCD controller and the CPU on the clock, half of the clock cycle signals the CPU to use the bus, on the other half the CPU, as we would expect.
I find a bit lost now, as the saved ROM images are 128K in size and not 96K though ... Maybe the "applications ROM socket" is filled on those together or such.
IMPORTANT: I really don't know what is the exact order of the ROM images (you can find them on this page): it's clear that kernal is the last. But I have no idea about the others. I picked a "random" order and it seems working, maybe it's not even important what's the order, as the ROM scan routine scans ROMs at boot-up and register things what it found (see later).
From the view point of the CPU, the memory layout (CPU's address space is 64K, of course) is the following (I've already understood that partly via disassembling the KERNAL code, but not fully, eg the window of $4000 was quite clear for me):
CPU addr | size | Memory mapping in various MMU modes | summary | |||
---|---|---|---|---|---|---|
RAM | APPL | KERN | TEST | |||
FA00-FFFF | 1.5K | always reads 3FA00-3FFFF (top of KERNAL) or writes LCD ctrl/MMU |
always fixed | |||
F800-F9FF | 0.5K | always reads and writes I/O (VIAs, ACIA, EXP) | ||||
C000-F7FF | 14K | 0C000-0F7FF |
Appl window #4 | 3C000-3F7FF |
Offset 4 / Offset 5 | fixed/mapped according the MMU mode |
8000-BFFF | 16K | 08000-0BFFF |
Appl window #3 | 38000-3BFFF |
Offset 3 | |
4000-7FFF | 16K | 04000-07FFF |
Appl window #2 | Kernal window | Offset 2 | |
1000-3FFF | 12K | 01000-03FFF |
Appl window #1 | 01000-03FFF |
Offset 1 | |
0000-0FFF | 4K | always 00000-00FFF |
always fixed |
More about the MMU (and the meaning of 'window') can be read later in this document.
As you could see from the table above, the top of the memory (F800-FFFF) from the CPU's view point is always "fixed", and it's KERNAL "top" code and I/O. This "top" area can be thought to be divided into two parts:
F800-F9FF is a read/write I/O area (even if you can "see" the ROM content there in the disassembly list, the CPU read/write I/O here, not the ROM. I don't know though if it's possible to read "the real ROM" by mapping the top 16K of the ROM into another window, like to $4000 in KERN mode). I guess, not fully decoded, so while there is 128 addresses for each VIAs, a VIA has only 16 registers, so there is some "memory echo" within that area. Of course it's true for ACIA as well, but it has only 4 registers.
FA00-FFFF functions as ROM in case of read access, the top of the KERNAL code, including the 65xx CPU RESET, NMI and IRQ vectors as well. However on write, special meaning is assumed as write only registers. AFAIK within a 128 byte long area, the same purpose is true for all bytes (maybe not the LCD controller though, but the others!), the address is not decoded further (but it seems this fact is not exploited by the KERNAL at least). MMU select/save/recall stuffs seems to be "dummywrite", ie you can write _any_ byte value, only the fact of write access counts, not the value itself ("don't care"). However the five MMU offsets registers are different: in these cases, the written value has important role to form the offset for the given window.
The table (column "u.s" is useful size, ie the guessed useful number of registers within the 128 bytes, ie VIAs have 16 registers for each, thus VIA#1's registers can be accessed from F800, F810, F820, etc too, as far as I can understand - for MMU registers there are even 128 possibilities to address a single register):
space | u.s | write access | read access |
---|---|---|---|
FF80-FFFF |
4? | LCD controller (write only) | Top of KERNAL @ 3FA00-3FFFF |
FF00-FF7F |
1 | MMU KERN window offset (write only) | |
FE80-FEFF |
MMU APPL window#4 offset (write only) | ||
FE00-FE7F |
MMU APPL window#3 offset (write only) | ||
FD80-FDFF |
MMU APPL window#2 offset (write only) | ||
FD00-FD7F |
MMU APPL window#1 offset (write only) | ||
FC80-FCFF |
MMU select TEST mode (dummywrite only) | ||
FC00-FC7F |
MMU save current mode (dummywrite only) | ||
FB80-FBFF |
MMU recall saved mode (dummywrite only) | ||
FB00-FB7F |
MMU select RAM mode (dummywrite only) | ||
FA80-FAFF |
MMU select APPL mode (dummywrite only) | ||
FA00-FA7F |
MMU select KERN mode (dummywrite only) | ||
F980-F9FF |
4 | I/O #4 area: ACIA (read/write) | |
F900-F97F |
- | I/O #3 area: EXP I/O (read/write) | |
F880-F8FF |
16 | I/O #2 area: VIA#2 (read/write) | |
F800-F87F |
I/O #1 area: VIA#1 (read/write) |
I guess, the "EXP I/O" areas is something like with the Commodore 64, reserved space for I/O expansions (cartridges, etc).
The MMU works like the tables above shows. Windows are memory areas where the exact mapped memory is up to the programmer. Five offset registers are given (four for appl window #1-4 and one for kernal window). Their purposes to define an offset (in Kbyte granulity, to say differently: offset is shifted left by 10) the CPU address is added to (in "test" mode only the offset registers value are generated, unusable for normal operation, see later).
The purpose of the "top" fixed area is to provide an always-fixed region of executing hardware vectors (IRQ, RESET, NMI) and kernal entry points (the ROM code can map the lower addressed part before jumping there), and the same for I/O.
The purpose of the "bottom" fixed area is to provide a stable space for the important 65xx CPU constructions: the fixed position zero page, and the stack. Also, since it's 4K (and not only 0.5K for only ZP+stack) there is enough room for various other storage space for the operating system needs to be always there (both data and code), and even the default text video memory is there (from $800). This also means that you can provide different stack and/or zero page for the CPU, as the bottom part is always fixed to be the same memory (RAM) area.
The MMU also provided the ability to save the current mode and recall (restore) the last saved mode. This is an important feature, eg you can have IRQ while you use MMU in application mode, the top kernal code will save current mode, and sets up kernal mode before jumping to lower parts of the kernal (and after returning from IRQ, it restores the saved MMU mode). Of course it's just one example, there are more (eg calling kernal entry routines from outside of kernal).
The "test" mode is interesting, but not useful for normal operation: it simply causes the window offset registers are outputed for all addresses for the given CPU address window (for C000-F7FF there is a split at E000 to emit appl window #4 or kernal window). As you can see it cannot be even used normally (CPU wouldn't be execute normal opcodes etc) only for hardware check it can be useful. For writing an emulator, this mode can be ignored safely (in the CPU memory table, offsets 1-4 means the content of appl window registers, while offset 5 is the kernal window).
The MMU hasn't got RESET input, thus software must set it up after RESET. Since the 65xx RESET hardware vector is at the top memory, which is always the same (in all MMU modes) it's not a problem, the RESET vector and the initial code will always run correctly.
The MMU chip seems to be named as "5707 LCD MMU CHIP (gate array)".
The LCD panel of CLCD has resolution of 480*128 and said to be excellent quality to its age. The LCD controller IC can drive it in character mode (with 6*8 or 8*8 character matrix, the first is used only on CLCD though, so it gives you 80*16 characters), or hi-res graphical mode (1bpp 480*128).
As a foreword / live test, you can try my emulator in the test mode (click on the link to learn more).
Registers of the LCD controller:
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
---|---|---|---|---|---|---|---|---|
$FF80 |
- | XS6 ... XS0 | ||||||
$FF81 |
YS7 ... YS0 | |||||||
$FF82 |
- | GRAPH | ALT | |||||
$FF83 |
- | TEST | S40 | CS80 | CHRW | - |
The generic description:
The LCD controller is capable of addressing the first 32K of RAM of CLCD (regardless of the MMU/window states, it always address the RAM directly, the first 32K of the physical address map) in the PHI1 phase of the system clock (CPU access it in PHI2). The first 32K of RAM is also named as "video" or "shared" memory because of this. The exact memory location where video RAM starts is selected by the XS and YS registers (see later). The standard location of (text) video RAM on CLCD is $800, which is a nice choice as the MMU provides 4K fixed RAM (in all modes) at the beginning of the CPU address space, so video RAM is always available for the softwares in this way. Of course, it's still possible to use video RAM at higher addresses (in the first 32K) but then you wouldn't be able to access it directly in some MMU modes. In text mode, only the lower 7 bits of the video RAM is used to determine the character, the MSB controls the inverse mode.
The ROM disassembly suggests that there is a KERNAL routine to set these registers up, and $FF83 & $FF84 registers are always set with the same value, allowing only the lower two bits to be set up by the caller, forcing bit 3 to be set. As these two registers have used/unused bits seems to be "inverted" to each other, the algorithm is understandable. Also, you can notice, that the panel type if "fixed" in this way (see above), also the CHRW (I have no idea what would happen on a real CLCD if you modify the panel type bits, but I guess CHRW can be modified without dangers, if you write register directly not with the kernal routine - without too much sense as charset is in ROM, thus is it not even emulated by my emulator) to be 6 pixel wide characters. The two lower bits is allowed to be programmed, which seems to mean the graphical/text mode, and the character set selection (in BASIC you can select as with the Commodore 64 from keyboard).
It seems LCD controller does not allow for custom character set, and dedicated ROM is assigned as the character generator ROM. However in general about the character set: I'm more or less guessing only.
The layout of the video RAM is somewhat complicated (especially with different CS80/S40 settings) if you try to find out/understand the situation, currently I don't try to explain it, but I provide the information I use with my emulator which seems to be work in text and graphical mode (I've tested that with entering into LCD BASIC and typing a simple program which draws an ellipse in graphical mode):
It seems, the 128 bytes and 64 bytes length of display lines are for a simplier hardware/software, to keep byte counters at a power of number two.
Important problems with my emulator and understanding the hardware/software as well:
The exact name of the LCD controller seems to be "5706 LCD controller chip (gate array)", however eg "Secret weapons of Commodore" page mentiones 8653 (not to be confused with 8563!). That page is also interesting because it shows on a picture of the PCB an IC labeled as some kind of chargen ROM. As I've mentioned above, I have serious problem with finding the other character set, and I only found something in the KERNAL ROM image. Maybe the character set for real is stored in separated ROM I have no ROM image file of?
CLCD is battery powered, even if "switched off" (from the user point of view, at last with not flat batteries) the content of the RAM is preserved. CLCD tries hard to check the "state" of the machine as valid to distinguish valid "shutdown" and "fresh power-on" events. The primary "storage" of the CLCD is RAM disk like entity (see later) unless if you connect a real disk drive (CLCD has IEC bus connector). As far as I can understand even the initial ROM scanning (see later again) forms ROM checksums to be ensure the machine state is intact.
CLCD is able to detect if battery is low, more about this at the section of VIAs.
CLCD contains a 65C51 ACIA chip at $F980. The built-in TERMINAL application can use it, and also some sources mention that CLCD has true serial port, and even an (auto answer?) modem. I haven't tried to expand my knowledge on this area yet.
CLCD contains two 65C22 VIAs. I will name them as VIA1 (the one from $F800) and VIA2 (from $F880). Note: information on VIAs, and the keyboard are quite weak and only based on my guess-work, which can be fair lower accurate than things got as information for CBM engineers, like some MMU "secret". It's even possible something only seems to be true because it works this way for some reason in my emulator and not on the real machine (but since the emulator tries to emulate the hardware and the software is the original ROM images, some truth should be there, still) ...
Pin | VIA #1 @ $F800 | VIA #2 @ $F880 |
---|---|---|
PA0 | [O] Keyboard row 0 | [O] Centronics/RTC D0 |
PA1 | [O] Keyboard row 1 | [O] Centronics/RTC D1 |
PA2 | [O] Keyboard row 2 | [O] Centronics/RTC D2 |
PA3 | [O] Keyboard row 3 | [O] Centronics/RTC D3 |
PA4 | [O] Keyboard row 4 | [O] Centronics/RTC RD |
PA5 | [O] Keyboard row 5 | [O] Centronics/RTC WR |
PA6 | [O] Keyboard row 6 | [O] Centronics/RTC AW |
PA7 | [O] Keyboard row 7 | [O] Centronics/RTC BZ |
CA1 (edge in) | [I] No battery IRQ | /RingDetect |
CA2 | [I] Alarm In | Centronics STB out |
PB0 | [O] Key shift/load | [O] Low DTMF out |
PB1 | [O] RTC enable | [O] /ModemEnable |
PB2 | [O] /PowerOn | - |
PB3 | [O] IEC ATN out | [O] Modem audio enable |
PB4 | [O] IEC CLK out | [I] /CTS RS232 |
PB5 | [O] IEC DATA out | - |
PB6 | [I] IEC CLK in | [I] Centronics Busy in |
PB7 | [I] IEC DATA in | [O] High DTMF out |
CB1 | [O] Key shift clock | Beeper |
CB2 | [O] Key shift data | Barcode reader |
Timer usage | ||
Timer1 | System IRQ | High DTMF |
Timer2 | Micro-wafer | Beeper |
[O] and [I] means the default configured direction of I/O in DDR registers (I haven't spent too much energy yet to deal with VIA#2 in general ...). For low-active signals there is "/" sign before the name.
/PowerOn signal on port B of VIA#1 seems to be important as this is one of the first things kernal does after reset before the whole VIA initialization stuff: sets DDR as output for that single pin with output value of zero. Maybe that would control the power on a real CLCD: you have some kind of push button to "turn on" which gives power for the system for the time you press the button. So one of the first thing the machine need to do is to initialize this output which will instruct an electronical switch to turn on, before you release the button. In this way the machine can even turn itself off by setting /PowerOn to high-inactive (this is a low active signal).
Important to note about the Shift register of VIA#1, which is used as a 16 bit wide input port, most likely to optimize the usage of "real" VIA ports. Though keyboard rows are selected for scan through VIA#1 port A (bit is clear = row is elected), the actual read of the state of the selected row(s) are done through the shift register of VIA#1! Also note, that actually it's a 16 bit value to read, the first byte is the state of the keyboard matrix for the selected row(s), the next 8 bits though are mixed purpose:
Bit.pos | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Meaning | ?? | 1 = batter low | ?? | C= key | CTRL key | SHIFT key | CAPS key | STOP key |
Bits marked with "??" are quite interesting ones. Setting any of them to '1' seems to freeze my emulator (after clearing the screen and/or scroll it rapidly), they should be "power sense" and "no battery" signals as far as I can understand, but anyway, setting any or all of them seems to result a non-working situation. As "battery is low" also not so nice to have (and it won't occur too much for a software based emulator) I think it's fair enough to say to leave three highest bits as zero in an emulator always, and only feed the lower 5 bits for the VIA emulation.
CLCD contains an RTC chip, it's OKI MSM58321, which has got a 4 bit wide shared data/address bus, which makes it easy to integrate with the use of minimal number of VIA pins. See section "The VIAs" for more information, name of the signals:
WR, RD and AW are high level (not edge) sensitive inputs of the RTC. Bus of D0-D3 is open drain in case of output (during read) according the specification. This may be the key that VIA can read RTC registers, regardless of its DDR (VIA#2 port A is configured as output constantly, but still, it's also used meanwhile to read data!). Please note that in case of port B it wouldn't work (VIA port B has different behaviour in this case compared to port A).
Please refer the data sheet of OKI MSM58321. Years are shown as 0 being 1984, thus there will be Commodore LCD Y2K-style problems in 2084 :)
One interesting problem: according to the data sheet, the registers used for month and day of the month should be swapped ... I don't know if it's a KERNAL bug, or another chip (revision?) was used with different register layout ... In my emulator I used the order to have meaningful date display in SHELL. BZ (BUSY) is not even emulated by my emulator, and I guess it's not even needed (as the KERNAL seems to read then compare all registers if was no time update during the read).
My emulator currently does not support writing the RTC registers (so it won't work in SHELL to set the clock), however the time/date should be correct as it gets values from clock of your computer via JavaScript date/time functions.
Some sources state, there is no sound at all. However the VIA pin usage suggests "beeper". Anyway, don't think about a complex stuff like a SID, even if there is sound, it's intended only for beeping or so. Anyway, as we know from ZX Spectrum, 1 bit should be enough for everyone :)
As Timer2 of VIA2 is seems to be used as the beeper output, sound at a programmed frequency can be produced without using the CPU itself.
My emulator currently does not support sound though.
CLCD's keyboard is quite similar to the one of the Commodore Plus/4, however there are few differences, more keys (eight function keys) and some matrix differences. Also the most notable thing is that "special" keys (especially modifier keys) are not part of the matrix but handled separately. This description and also the generic way to read the state of the matrix can be found in section "The VIAs" above.
This really ugly table tries to demonstrate the keyboard matrix (based on my work with checking the visible (or functional) result of each sel/sr combination in my emulator):
Read value (SR-in) | |||||||||
---|---|---|---|---|---|---|---|---|---|
L i n e s e l |
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
0 | DEL | 3 | 5 | 7 | 9 | DOWN | LEFT | 1 | |
1 | RET | W | R | Y | I | P | * | HOME | |
2 | TAB | A | D | G | J | L | ; | F2 | |
3 | F7 | 4 | 6 | 8 | 0 | UP | RIGHT | 2 | |
4 | F1 | Z | C | B | M | . | ESC | SPACE | |
5 | F3 | S | F | H | K | : | = | F8 | |
6 | F5 | E | T | U | O | - | + | Q | |
7 | @ | F4 | X | V | N | , | / | F6 |
The order of bits (0...7 numbers) can be though as being odd, etc, but it was the first version I checked the key events with my emulator (yet in X-Y system not with bit masks), and I am lazy to re-order the table now :) "Linesel" is the value should be written to VIA#1 port A (here, bit value of 0 means selected), and the "read value" can be read (here, bit value of 1 means the pressed state) for selected line(s) then through the SR of VIA#1 if the usual matrix read request transition is done on VIA#1 port B bit 0 (see the VIAs section above for more description on this topic).
More-or-less correct VIA SR implementation is needed for an emulator, as VIA's SR has the feature to start the actual shift-in (or shift-out, but not in our case) on read/write SR register and then you can read the result later. As the shift-in operation reads another data after the "VIA#1 port B bit 0" transition, it's esential to emulate this well to be able to use the keyboard.
Also, some special keys are not found within the generic matrix, but read separately, see the VIAs section (again).
Some KERNAL code/data related to the keyboard:
As you can see in section "The VIAs", total of five pins from VIA#1 port B is used for the IEC bus. The position and direction of bits seems to be similar as with port A of CIA#2 in Commodore 64.
If you donwload the zip file containing the ROM images, you'll find kernal
with the file name of kizapr-u102.bin
.
You can see my disassembly try here, but please note: many parts are wrongly interpreted as code instead of data or vice versa. I mainly corrected this and commented some parts and even inserted meaningful labels which were interesting for me during my detective work, and it was hard to remember for, by heart :)
KERNAL (as on CBM machines in general) is very important as its code is executed on power-up/reset, also the hardware vectors (which includes IRQ and NMI too, not just RESET) are there. Note, that in all MMU modes, the top of the kernal is always there! It's an important fact for two reasons:
The KERNAL's first task is to set up the MMU mode to be kernal mode as the state can't be known for sure. It's needed to access the lower parts of the kernal too, not just the "top area".
The kernal's top area also contain the usual Commodore standard kernal entry points. Please note that compared with eg Commodore 64 the major difference that on Commodore LCD you quite often see "two step" call. I mean: calling a given kernal entry first hits a code which sets up the MMU to access the lower part of the kernal and only then it will jump there. Here, the Commodore LCD's MMU is really nice as it provides a "save current MMU mode" and a "recall last saved MMU mode" functions. It's important as the routines may be called from various MMU modes. The IRQ/NMI vector works also like this: you can't tell what is the exact MMU mode when you get an IRQ.
Major feature of the CLCD is the ability to remember the "state" of the machine including the content of the RAM disk ("virtual 1541"). This is possible as RAM is always powered from battery even if the machine is "switched off". From the KERNAL disassembly I have confusing ideas on this area. It seems CLCD does not care too much if the content of the memory is "invalid" (ie a "cold" boot when all the memory is empty, which is always the case with my JavaScript based emulator of course). It merely displays some warning, and simply skips the proper initialization of the machine which cause serious problems later (eg you see PI signs instead of numbers in BASIC, virtual 1541 does not work, and other anomalies. Maybe the intent from the developers was the following: let people to continue even if state is not intact in the hope that some data can be still there and can be rescued, but give a warning about the situation. And indeed, in this case some warnings are displayed and user even needs to press a key to continue to be sure they can see it before SHELL clears the screen. I am not really sure what user can do if they want a proper initialization anyway after an event like this, maybe that keyboard combination (C= SHIFT STOP at the same time).
Currently I have the ugly solution in my emulator to patch the KERNAL image to always force the full initialization. It would be interesting to know how it is done on a real CLCD: it's possible there too, eg battery is totally flat (memory content is not valid), after the first power on, or after a misbehaving software which corrupts the memory ... As far as I can tell, there are some sings in the KERNAL to use an interesting key combination (C=, SHIFT, STOP pressed at the same time?) during the power up, which forces the initialization though.
Foreword: for a "live" demo to demonstrate the process (and the graphical mode of the LCD controller) with my own ROM installed, check this page out.
The information on software (in contrast of hardware, where I got help from some people, like with the MMU) is enterly based on my own knowledge only got by reading and trying to understand the disassembly of the kernal. As usual I can be wrong here, any corrections, additions are welcomed as feedback.
Commodore LCD kernal scans the available ROMs on start up. The kernal uses the machine with MMU state of "kernal mode" (no wonder the name ...). During the scan, the kernal window from $4000 is used to "page in" the possible memory locations where system ROMs can exist. So you can even remove ROMs (other than the kernal, of course) and the machine will work, however only with kernal you'll dropped into monitor mode (the experience got with my emulator).
The ROM scanning itself means altering the kernal offset register of the MMU to be able to see memory areas from $20000 in 16K steps (8 choices). It tries the find the string "Commodore LCD" (without the quote marks of course) at offset of 8. Even the kernal has this identifier, so it will find "itself" and the identifier string of the kernal itself is used to compare the values in the kernal window. On each found ROM images simple (16 bit) checksum is calculated, byte at offset 4 tells how many Kbytes should be used to form the checksum. I don't know the purpose of the other bytes in the very first 8 bytes beside the byte at offset 4.
The ROM images and their first 8 bytes:
bytes | image name | phys.addr | comment |
---|---|---|---|
00 00 FF FF 10 DD DD DD | kizapr-u102.bin | $38000 | KERNAL is also here |
00 00 FF FF 10 DD DD DD | sizapr-u103.bin | ?? | BASIC 3.6 (as an application) is here |
00 00 FF FF 20 04 12 85 | sept-M-13apr-u104.bin | ?? | empty after offset $6480 |
00 00 FF FF 20 04 12 85 | SS-CALC-13apr-u105.bin | ?? | empty after offset $6480 |
Just to note: in case of 04-12-85 byte sequence it can be even date in packed BCD
format (if month-day-year is assumed with year of '85 and one day earlier than
the file names suggests), almost the same as in the file names (I don't know how these file names
were choosen by people (Bil, I guess) who saved the ROM images), but then what's
up with DD DD DD
? As I've already mentioned, I don't know the exact order ("phys.addr") of
the ROM images. One thing is sure: the KERNAL is at the top of the system address space,
so it must be $38000. In my emulator currently I load ROMs in the order as you can see
in the table, KERNAL from $38000, and every ROM images at an address 32K lower than the previous. However
I still use the question marks as this is probably not the "real" order (but it seems to work, and maybe
the exact order is not even important? - detected and used then by the ROM scanning routine in the given order).
I can't tell why two ROM images have not used space and exactly from offset $6480 for both ...
The 16K steps rule may signal the idea that you can have smaller but multiple ROMs, though the default ROM images seems to have only the identifier string and "application directory" only at the beginning of every images, and those images are 32K in size.
After the identifier string a "directory" follows which describes the applications in this ROM. I guess this is used later by the menu system (named "SHELL") to show applications. As far as I can understand the structure of this "directory" is the following:
example.bas
, BASIC app will
open with trying example.bas to be loaded ...
Applications in various ROM images:
Header bytes | Name | ROM image name |
---|---|---|
LN ?? ?? ?? START | ||
11 10 20 00 38 80 | MONITOR.MON | kizapr-u102.bin |
11 01 20 00 4C 80 | COMMAND.CMD | |
0F 20 10 00 AF 54 | SHELL.SHL | sizapr-u103.bin |
0F 04 10 00 49 40 | BASIC.BAS | |
12 02 20 04 4B 80 | WORDPROC.WPR | sept-M-13apr-u104.bin |
12 02 20 00 00 C0 | TERMINAL.COM | |
11 01 20 00 80 E2 | MEMOPAD.MEM | |
0E 01 20 02 37 80 | CALC.DMB | SS-CALC-13apr-u105.bin |
13 02 20 06 A3 8F | CALCSHEET.SPR |
Of course KERNAL ROM has the important role that besides of the "applications" it also contains the KERNAL itself (so it contains only two relatively small applications in addition compared to the others).
It seems the content of the X register is important when an application is started by jumping on its entry point. I don't know the exact values yet, but it seems zero means the "boot time" so when the ROM scan utility finds ROMs and applications, then every application is called with X=0. Later, other X register values are used, so you can have an "init" routine called only on "boot time" only by inspecting the value of X.
Also note, that there are entry point addresses ("START" in the table) like around $4000 in "BASIC ROM", while even $E280 and such in others. As far as I can imagine this is because there can be different MMU modes/used windows to execute a given application eg, apps in KERNAL (monitor for example) seems to be logical to run in kernal MMU mode anyway.
Interestingly, the monitor itself is not snown by the SHELL. However you can access it at least four different ways (according to my experience with my emulator):
MONITOR.MON is in the KERNAL image, so it's always available even if you remove all of the ROMs (or images, in the emulator) but the kernal. That's why you will be dropped into monitor mode if no other ROMs are found: there is no other command to be executed, eg the usual menu system (SHELL, see later) is in another ROM (image).
The MONITOR seems to be similar to Commodore 128's monitor (at least I can tell, I am not really familiar with the C128 ...), maybe the C128's one based on the CLCD's code, at least this is said for BASIC (see later) so I assume this can be true in this situation as well.
One thing to note: in BASIC, if you activate the MONITOR, the scroll of the screen ignores the last line (function keys' bar) but if you activate from the SHELL, it's not. That's understandable, as apps launched from the SHELL are expected to set up its own screen (ie, clear the screen, display what it wants) but MONITOR is not this kind of app. Maybe it was not even designed to be able to start "manually" from SHELL, but still you can do that.
Besides of monitor (MONITOR.MON) it's the other application which is in the kernal ROM.
I guess, its function is executing commands (whooo, what a surprise), and in the SHELL what you type into the SHELL "command line" is also executed with this (maybe also the filename extension and application bind is handled here). The disassembly of this part is interesting.
CLCD has the interesting concept so it can be usable even without a "real" disk drive. Of course in theory you can connect an 1541 or similar (CLCD has serial IEC bus) but then the portable nature wouldn't be too nice anymore - unless with the planned 1561 which is also battery powered. Anyway ...
The trick is to use the RAM as "disk drive" and the KERNAL even emulates some kind of functionality (like directory listing) of a real disk drive. As the CLCD always powers the RAM from battery, it will preserve the content (unless the battery is flat). This is the kernal part creates the directory listing.
The virtual 1541 can be accessed as the device 1, ie LOAD "$",1
loads
the directory (but you should use the DIRECTORY
command as it won't overwrite
the BASIC program in the memory).
Even "memopad" application works this way: what you type there is saved, and loaded
back if you start memopad again (it seems the file name would be: MEMO.MEM
).
This way you have some kind of "multitask feeling", it feels
like it is a background application having your data all the time.
SHELL is the "menu system" you'll see after your CLCD boots up. It resides in the ROM image named as "sizapr-u103.bin" which also contains the BASIC (v3.6) interpreter. SHELL provides:
Besides the "what you can see", the functionality of the SHELL:
I wrote about the file name extension - application binding. Now you can try the theory,
type something like this into the SHELL: example.bas
Tasks provided by functions keys can be also accessed with typing the
name, ie F6 for RS-232 settings, but you can also type rs-232
(and press RETURN at the end, of course).
In various applications you can see inverse "labels" at the bottom of the screen. It shows the function of the F1...F8 function keys. Usually F8 is the exit in many situations, though not in SHELL (as you can't exit from the SHELL as it is the first application running).
In the SHELL, the function keys are system settings or for invoking often used functions. The list:
In case of the SHELL and F6, F7, you have multiple choices to set up, so another function key bar is displayed. You can use the functions keys to navigate between settings, but you can also use the cursor left/right to do this (or the Fx keys). F8 exists. In one setting you can use the cursor up/down keys, and no need to use RETURN or whatever to select a setting, simply leave the inversed item where you want and navigate away, or exit.
In other applications the function key bar is different of course. Usually the F8 means there to exit to the SHELL. Interestingly there is a POPUP mode (at least in BASIC) which is some kind of "multi tasking" like feeling: if you choose MEMOPAD there, you can use the MEMOPAD without exiting from BASIC first.
Again: I can't tell too much about the file functions as it seems I have problem with storing any file on the RAM disk, so I can't test it too much. Maybe this is also the reason as the nice "popup" feature does not show the last typed text in memopad, as it would load the text back from the RAM disk (?).
On CLCD BASIC interpreter is a 'regular' application as others, not the default mode as with usual CBM micros.
According to the screen, it's "COMMODORE LCD BASIC V3.6". Interesting feature compared to other CBM BASICs is
the existence of the function key bar display at the last line. You can use command "EXIT
" to get back into the SHELL.
Since RESET vector points to $FA07 in LCD kernal, you can "reset" the machine with the following BASIC command:
SYS 64007
. You can try to "shut down" the machine with:
POKE 63488,255
which would make the /POWERON signal high (inactive). Currently my emulator only
alerts the user about power-off but accepting the alert window will cause to continue the emulation. A real
Commodore LCD would lost its power at this point, I guess (without a "clean shut down" though, to preserve
the state). If you click on the RESET button at this point, odd things will/can happen, I am not exactly sure why. Of course
reloading the emulator page works, so it must be something about the RAM content, and state information.
Because of the habit (I guess) the upper case charset is used by default in BASIC in contrast of other applications (including the SHELL itself) of the CLCD.
It seems the BASIC memory starts at $1001 (right
after the text video RAM default location). LCD BASIC can use the graphical mode (of course no colours), I was
able to use GRAPHIC
and CIRCLE
in a short BASIC program to draw an ellipse on the screen. It seems, in graphical
mode the BASIC memory start is shifted to address $3001 (since gfx screen needs $2000 bytes of RAM, the $2000 increment
in start address seems to be logical).
Short test program to test graphical mode:
10 GRAPHIC1,1 20 CIRCLE,240,64,230,60 30 GET A$ 40 IF A$="" THEN 30 50 GRAPHIC0
It's said that LCD BASIC can run BASIC 7 programs if it does not contain platform specific SYS/PEEK/POKE and
features about colours, etc (as those cannot be implemented on the CLCD, it has monochrome LCD display).
I can't comment that further too much. BASIC is in a separated ROM (or only ROM image
file?) contains only the SHELL itself other than BASIC. Commodore-128's (V7) BASIC is said to be the further
developed LCD BASIC, so it can answer questions like why "unimplemented command error" for some C128 BASIC keywords
like "OFF
", maybe it was for the CLCD originally to switch off the machine, turn display/the machine/something OFF (I've tried the
"OFF
" in LCD BASIC, nothing happened - but at least no error unlike on the C128 - but it can be the limitation of
my emulator).
About disk handling: wikipedia says about the drive status: Commodore BASIC versions 4.0 and later provide a pseudo-variable referred to as DS$.
However even with LCD BASIC (3.6) seems to support this feature, try it: PRINT DS$
. As I've stated before, virtual 1541 is emulated
as device 1 (would be tape on C64), DLOAD
, DIRECTORY
and similar commands access that as well by default (but if
you change the default storage in the SHELL with F7 -> F4 then those commands would use the device you selects there).
You can save BASIC programs with any name, but it's worth to use .BAS "extension" as then SHELL can be used to start it directly with the .BAS ~ BASIC "filename extension binding".
Memopad is a simple utility to give some short text as a reminder. It has two interesging features:
MEMO.MEM
. As it always tried to load the file first,
you may have the feeling it's always running in the "background" though, so it's quite ideal
to use as a reminder utility, indeed. It's interesting to note that you can force mempad to
use another file, with the "filename extension binding": type a filename with the extension
of .MEM at the SHELL. But I guess this is not the intended use of this application :)Calculator application is a (surprise!) calculator. Like the MEMOPAD it's possible to start it from another application before exiting that first. Calculator has many input and format modes. It does not use files too much, so while it's possible to launch it with the filename extension binding method, the given file won't be accessed at all.
I am not a great fan or user of word processors and/or spreadsheet applications too much in general (not only on CLCD) so I can't say too much. However one interesting thing that CLCD allows you to use both of these at the same time on splitted screen! That's also one reason I mention these in one section. An early newspaper article mention that CLCD's spreadsheet application is much faster than Visio (?) or Lotus-1-2-3 on IBM PC, and even has more features.
Only major changes (or the ones can be important) are shown here.