RF Eclectica Wiki

Try to learn something about everything, and everything about something - Thomas Huxley

User Tools

Site Tools


public:computers:6502:tutorial_progress

6502 Project

Tutorial Progress

A record of my progress through the Ben Eater You Tube tutorial

Day One : Tuesday 16/8/22

  • Kit arrived
  • Installed:
    • CPU
    • EEPROM
    • NAND Gate
    • Address & Data lines between CPU and EEPROM and address decoder for EEPROM
  • Used python “makerom.py” script to burn eprom:
rom = bytearray([0xea] * 32768 )
 
rom[0] = 0xa9
rom[1] = 0x42
 
rom[2] = 0x8d
rom[3] = 0x00
rom[4] = 0x60
 
rom[0x7ffc] = 0x00
rom[0x7ffd] = 0x80
 
with open("rom.bin", "wb") as out_file:
     out_file.write(rom)
 

ROM file hexdump:

00000000  a9 42 8d 00 60 ea ea ea  ea ea ea ea ea ea ea ea  |.B..`...........|
00000010  ea ea ea ea ea ea ea ea  ea ea ea ea ea ea ea ea  |................|
*
00007ff
  • Unable to confirm correct running - still waiting for Arduino Mega to act as a logic analyzer. LEDs on data or Address lines show activity….

Next stage

  • add the 65C22 VIA and use LEDs on output to show correct running
  • make an 8-bit binary counter with LEDs as an exercise

Day Two : Wednesday 17/8/22

Using Siglent Function Generator as the CPU PHI2 clock

  • added 65C22 VIA and 8 leds
  • much debugging of hardware/wiring - breadboard is a NASTY way of doing this…..!
    • ordered some IC sockets & other hardware to allow me to build a version on Vero/perf board and move away from breadboard once I've got the the point in the tutorials where all the hardware is stable.
  • used python script to get the “01010101 → 10101010” LED sequence running.

Self-study

  • modified assembly code to make the LEDs flash in a binary count

8 bit counter

### 8-bit Counter
 
code = bytearray([
    0xa9, 0xff,         # lda #$FF
    0x8d, 0x02, 0x60,   # sta $6002 : put 11111111 into VIA's Port B control register - all port pins are OUTPUT
 
    0xa9, 0xff,         # lda #$ff (start with all LEDs lit)
    0x8d, 0x00, 0x60,   # sta $6000
 
    0x1a,                # inc A
 
    0x4c, 0x07, 0x80,   # jmp $8007
    ])
 
 
rom = code + bytearray([0xea] * (32768 - len(code)))
 
rom[0x7ffc] = 0x00
rom[0x7ffd] = 0x80
 
with open("rom.bin", "wb") as out_file:
     out_file.write(rom);

This assembles as :

00000000  a9 ff 8d 02 60 a9 ff 8d  00 60 1a 4c 07 80 ea ea  |....`....`.L....|
00000010  ea ea ea ea ea ea ea ea  ea ea ea ea ea ea ea ea  |................|
*
00007ff0  ea ea ea ea ea ea ea ea  ea ea ea ea 00 80 ea ea  |................|
00008000

LEDs flash in binary count to 255 and cycle round… endlessly.

16 bit counter

I wanted to see if I could extend the counter to 16-bits, using 2 VIA ports to drive the LEDs

To make life easier I moved to assembly language and the VASM assembler as recommended in the tutorial.

To count beyond a single 8-bit byte needs a way of holding 2 separate bytes of the count, the low byte and high byte, and only increment the high byte when the low byte rolls past 11111111. Tricky with no RAM installed yet.

I used the 2 index registers X and Y. The carry bit is set as a result of arithmetic on the Accumulator register, so X (low byte) has to be copied to the Accumulator for the addition of 1 each time round the loop.

        .org $8000
 
reset:
        lda #$ff
        sta $6002    ; set port B pins to all output
        sta $6003    ; set port A pins to all output
        lda #$00
        tax          ; X holds the low byte. initialize to zero
        tay          ; Y holds the high byte. initialize to zero
 
 
loop:
        txa          ; copy low byte to A
        adc #$01     ; add 1
        tax          ; copy new value to X
        bcs high_b   ; if carry flag set, branch to increment the high byte
 
 
print:
        txa          ; bring the low byte to A
        sta $6000    ; send low byte to Port B LEDs
        tya          ; bring the high byte to A
        sta $6001    ; send high byte to Port A LEDs
        jmp loop
 
high_b:
 
        iny          ; increment high byte in Y
        jmp print
 
        .org $fffc
        .word reset
        .word $0000

Assembled code

00000000  a9 ff 8d 02 60 8d 03 60  a9 00 aa a8 8a 69 01 aa  |....`..`.....i..|
00000010  b0 0b 8a 8d 00 60 98 8d  01 60 4c 0c 80 c8 4c 12  |.....`...`L...L.|
00000020  80 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00007ff0  00 00 00 00 00 00 00 00  00 00 00 00 00 80 00 00  |................|
00008000

Add another 8 LEDs, to Port A, to show the High Byte….

It now counts to 1111111111111111 or $FFFF or 65535 as displayed by the LEDs attached to both VIA ports.

Next stage

is to add the LCD module in place of the flashing LEDs

Day Three : Friday 19/8/22

LCD

  • added the LCD module to the VIA output port(s)
  • put the “hello.s” assembled code into ROM
  • LCD printed Hello, w and no more….

8 Characters… what, why?

Lots of messing about with the assembler code to see if I could get all the Hello, world! message to print to the LCD.

By adding the necessary instruction to change the display position I could use all 16 characters of the display, but I couldn't get it to print all the message in one go…. The same happened with a different LCD module.

Eventually I checked, and re-checked, the address and data lines between CPU, ROM and VIA and must have re-inserted one that was loose. Afterwards the display showed Hello, world! correctly.

I assume the error was that an address line between CPU and ROM wasn't connected, so at one step of the program the ROM went to the wrong address and returned garbage data, and the program stopped, or just randomly stepped through the otherwise empty ROM?

Anyway, whatever the mechanism, ensuring all address & data lines were seated correctly cured the bug.

Next Stage

  • adding RAM
  • rebuilding on “properly wired” stripboard to remove the annoyance of breadboard wires coming adrift.

Day 4 : Saturday 21/8/22

  • added RAM
  • re-wrote “hello_world” to use 4-bit LCD addressing and moved LCD to PORTB of VIA, freeing up all of PORTA for other uses
  • began building veroboard version to

Day 5 : Sunday 22/8/22

  • completed veroboard build and tested with 4-bit/2-line LCD “Hello world”
 
PORTB = $6000
PORTA = $6001
DDRB = $6002
DDRA = $6003
 
 
E  = %01000000
RW = %00100000
RS = %00010000
LED = %10000000
 
  .org $8000
 
reset:
  ldx #$ff
  txs
 
  lda #%11111111 ; Set all pins on port B to output
  sta DDRB
  lda #%00000000 ; Set all pins on port A to input
  sta DDRA
 
  jsr lcd_init
  lda #%00101000 ; Set 4-bit mode; 2-line display; 5x8 font
  jsr lcd_instruction
  lda #%00001110 ; Display on; cursor on; blink off
  jsr lcd_instruction
  lda #%00000110 ; Increment and shift cursor; don't shift display
  jsr lcd_instruction
  lda #%00000001 ; Clear display
  jsr lcd_instruction
 
  ldx #0
 
print1:
  lda message1,x
  beq print2
  jsr print_char
  inx
  jmp print1
 
message1: .asciiz "Shed-o-tron II "
 
message2: .asciiz "* * 22/8/22 * * "
 
 
loop:
  lda #LED
  sta PORTB
  jmp loop
 
print2:
  lda #%10101001
  jsr lcd_instruction
 
  ldx #0
line2:
  lda message2,x
  beq loop
  jsr print_char
  inx
  jmp line2
 
 
 
lcd_wait:
  pha
  lda #%11110000  ; LCD data is input
  sta DDRB
lcdbusy:
  lda #RW
  sta PORTB
  lda #(RW | E)
  sta PORTB
  lda PORTB       ; Read high nibble
  pha             ; and put on stack since it has the busy flag
  lda #RW
  sta PORTB
  lda #(RW | E)
  sta PORTB
  lda PORTB       ; Read low nibble
  pla             ; Get high nibble off stack
  and #%00001000
  bne lcdbusy
 
  lda #RW
  sta PORTB
  lda #%11111111  ; LCD data is output
  sta DDRB
  pla
  rts
 
lcd_init:
  lda #%00000010 ; Set 4-bit mode
  sta PORTB
  ora #E
  sta PORTB
  and #%00001111
  sta PORTB
  rts
 
lcd_instruction:
  jsr lcd_wait
  pha
  lsr
  lsr
  lsr
  lsr            ; Send high 4 bits
  sta PORTB
  ora #E         ; Set E bit to send instruction
  sta PORTB
  eor #E         ; Clear E bit
  sta PORTB
  pla
  and #%00001111 ; Send low 4 bits
  sta PORTB
  ora #E         ; Set E bit to send instruction
  sta PORTB
  eor #E         ; Clear E bit
  sta PORTB
  rts
 
print_char:
  jsr lcd_wait
  pha
  lsr
  lsr
  lsr
  lsr             ; Send high 4 bits
  ora #RS         ; Set RS
  sta PORTB
  ora #E          ; Set E bit to send instruction
  sta PORTB
  eor #E          ; Clear E bit
  sta PORTB
  pla
  and #%00001111  ; Send low 4 bits
  ora #RS         ; Set RS
  sta PORTB
  ora #E          ; Set E bit to send instruction
  sta PORTB
  eor #E          ; Clear E bit
  sta PORTB
  rts
 
 
 
 
 
 
 
 
; Reset/IRQ vectors
  .org $fffc
  .word reset
  .word $0000
 

Next Stage

  • begin expanding software
    • routines to examine memory contents and display (in HEX) the contents of selected memory location(s)
    • add switches to VIA PORTA and begin reading state of switches and update LCD with information
    • a power-on memory test and toggle LED/LCD?

Further Information

public/computers/6502/tutorial_progress.txt · Last modified: 22/08/22 10:47 BST by 127.0.0.1