>>> it will take a bit for me to understand exactly why it works.
The 6800/6809 has two (2) main accumulators (called A and B). These are both 8-bits wide, so can hold an (unsigned) number in the range 0 to 255 (decimal) or $00 to $FF (hexadecimal).
The "LDB $FCF4" instruction loads the 8-bit value of memory address $FCF4 (which we now know is the serial port status register) into accumulator B.
The "BITB #$01" instruction effectively tests the least significant bit of accumulator B. From the data sheet - this isolates and tests the value of the "Receive Data Register Full" bit. A zero (0) bit indicates no character has been received, whereas a one (1) bit indicates that a character has been received.
The "BEQ BACKWARDS" instruction (note: BACKWARDS is my way of indicating what happens rather than where the instruction actually branches to) branches based upon the result of the previous BITB test. A branch is made if the result was zero (0) - indicating that no character had been received. The previous code (reading the status register, testing the appropriate status bit and branching) repeats until the tested bit is a one (1) indicating that a key has been pressed.
The "LDA $FCF5" instruction loads the character that has been received from the serial device data port (that we now know resides at address $FCF5) into accumulator A.
We then (effectively) repeat the same code above (that of checking the serial status port), but this time waiting for the transmitter to be available. This is the 'next bit along' in the status register (hence the BITB #$02 instead of BITB #$01). This bit is identified as the "Transmit Data Register Empty". A zero (0) indicates that the transmitter is busy transmitting a character whereas a one (1) indicates that the transmitter is free.
I will ignore the NOP, as it does nothing...
The "STA $FCF5" instruction stores what is in accumulator A (the character that we previously received) into the serial device's transmitter register for transmission back to the user (i.e. the echo).
JMP obviously jumps to the specified address in memory to repeat the entire process...
The software loop is basically:
Code:
WHILE true {
Wait for a character to be received from the serial port.
Read the received character into accumulator A.
Wait for the serial port transmitter to be free.
Send the previously received character to the serial port.
}
It is unlikely that waiting for the transmitter to be free is required in this case (you can't type too fast can you). However, in a 'real' situation, it is important to wait for the transmitter to be free before attempting to transmit a character. Otherwise you can overrun the serial port resulting in garbage echoed back to you.
I hope this explanation helps? We will get you programming in assembler soon!
This is 'typical' of a 6809 instruction set listing:
https://colorcomputerarchive.com/repo/Documents/Books/Motorola 6809 and Hitachi 6309 Programming Reference (Darren Atkinson).pdf. Others are available.
I also use an online assembler:
https://www.asm80.com/#. Despite the name, it can assemble code for a 6800 and 6809. It contains a simulator also - so you can make your errors in the development environment and save wasting your time re-entering programs again and again into your real machine.
The source code for asm80.com (as entered into a file called ECHO.a09 for a 6809 CPU) is:
Code:
ORG $2000
L1: LDB $FCF4 ; READ THE ACIA STATUS REGISTER.
BITB #$01 ; CHECK THE RX FULL BIT.
BEQ L1 ; WAIT UNTIL A CHARACTER HAS BEEN RECEIVED.
LDA $FCF5 ; READ THE RX CHARACTER.
L2: LDB $FCF4 ; READ THE ACIA STATUS REGISTER.
BITB #$02 ; CHECK THE TX EMPTY BIT.
BEQ L2 ; WAIT UNTIL THE TX IS EMPTY.
NOP ; DO NOTHING!
STA $FCF5 ; WRITE THE TX CHARACTER.
JMP $2000 ; REPEAT FOREVER.
END
Copy and paste the above...
Note that I have replaced my BACKWARDS by two (2) labels (L1 and L2) and told the assembler (via the ORG statement) where I want the code to be assembled to execute at. A $ indicates a hexadecimal number and a # indicates an immediate value.
You can obviously create a label ( say STRT: ) at the beginning of the program and then use this label in the JMP instruction. You can also equate (EQU) a symbols for $FCF4 and $FCF5 to make changing the port addresses easier... All sorts of improvements...
Dave