While I’ve been buying goodies from https://gotek.nl, I missed a place to buy hard to find obscure items.
And then I found https://heinpragt.nl (Last year)
Awesome! Retro parts old and new, some are very hard to find!
While I’ve been buying goodies from https://gotek.nl, I missed a place to buy hard to find obscure items.
And then I found https://heinpragt.nl (Last year)
Awesome! Retro parts old and new, some are very hard to find!
Test picture of a multiprocessor computer setup.
Using buttons on the right, I want the possibility to change between systems and keyboard settings.
Also, multiple software/OS slots for SDCards will be on the right.
The lid containing the keyboard has a handle!
After laser cutting a nice front, it could become a nice road warrior hacking station.
I’m going to replace the wireless keyboard, probably with a touch display and a programmable layout for keyboards.
Something like below
Some layouts:
I’ll probably buy this one from waveshare
Info about Faux86
In previous post I was talking about an esp32 with display for demo’s.
But my friend Erik mentioned a cheap LCD matrix from Ali.
What about creating something cool with that!
My Maze project would look amazing on this!
I can draw walls now!
Or I could make a cool audio visualiser, like the posted WLED version
Ehh .. not posted (well I can’t post everything)
What about a game of life display?
Using a web interface for inputting the start situation of the cells
Conway’s Game of Life is a cellular automaton. It consists of a grid of cells, each of which can be alive or dead. The state of each cell evolves based on simple rules: any live cell with fewer than two live neighbours dies (underpopulation), any live cell with two or three live neighbours survives, and any live cell with more than three live neighbours dies (overpopulation). Additionally, any dead cell with exactly three live neighbours becomes alive (reproduction). This simple set of rules can lead to complex patterns and behaviours.
But back to the demo …
What about a 6502 with 64×64 pixel display!
What would be needed?
Using some libraries and a framework setup, maybe there is a way to make a cool and cheap demo machine
Do you have any suggestions ideas?
Comment or email me!
Using a LilyGo TTGO ESP32 VGA32, I’m connecting my breadboard 6502 to a serial vga terminal with its own keyboard.
Due to a lot of moving around, new places, new homes I dumped a lot of terminal hardware.
Also are those old terminals too big and use too much power.
I’m going to use this DIY screen.
https://www.henriaanstoot.nl/2021/03/24/broken-or-slow-laptop-screen-still-works/
Using the Libraries from Fabrizio Di Vittorio, named FabGL, you can transform this device into a dumb terminal, game device, VIC-20, a 8086 pc and more.
There are even some projects to turn this into a C64.
But the main thing I want to do: A simple terminal.
(I probably revisit the other options again at a later stage)
My Wozmon bios has bare minimum support for serial communication, so i have to do some bitbanging.
(6502 is using a 6551 ACIA)
Sound from the ESP32 VGA board.
A while ago I started a soldering a 6502 bare SBC.
I got it running now.
It has an EPROM with Wozmon and Basic for now.
I have to redo the address decoder, but I like the simple serial interface by Geoffrey. (I hate the PIC18F15Q41, made by Microchip, but still the best minimal option .. for now)
Probably the last time i’ve used a pic was in 1998
My BBC Acorn model B is working again. The original monitor is still dead.
Time to play with some machine code and ROMs.
My machine has a NFS rom installed. (NetFS)
Econet was Acorn Computers’s low-cost local area network system, intended for use by schools and small businesses. It was widely used in those areas, and was supported by a large number of different computer and server systems produced both by Acorn and by other companies.
I found a ROM online called Gremlin. It is a 16K rom file. But at the moment I only got some 28C64 (8k) or 28C256 (32k) eeproms.
32k it is. But de beeb having address line A14 floating high, I need to flash the upper 16k of the 32k ROM.
So I made the 16K rom into a 32K using cat
cp Gremlin\ v1.21\ \(1983\)\(Computer\ Concepts\).rom 16k.rom cat Gremlin\ v1.21\ \(1983\)\(Computer\ Concepts\).rom >> 16k.rom minipro -w 16k.rom -p AT28C256
I got the rom from this page:
https://acorn.huininga.nl/pub/unsorted/roms/Gremlin%20v1.21%20(1983)(Computer%20Concepts).rom
Below booting straight into the monitor program.
Manual:
Ben posted a youtube about Wozmon running on his 6502.
In 1976, Steve Wozniac wrote what’s commonly known simply as Wozmon.
Wozmon is a machine-code monitor program written by Wozniak for the Apple 1. In Only 256 bytes ! Being pure 6502 code easily adaptable.
A monitor program allows you to view/edit and run machine code using simple commands.
I’ve got a different setup as Ben’s computer.
But changing the necessary, and it will run on my 6502.
I’m not using rs232 voltage levels (-7 till -25 and +7 till +25 volts).
I’m using a usb serial uart standard 5v leveling stick …
For address decoder see other post
Compiling the Wosmon gave me an error, DEC is not a valid opcode for a bare 6502 .. but we have a 65c02.
Solution: Add -c02 extra opcodes
error 1 in line 187 of "wozmon.s": illegal operand types > DEC ; Decrement A. # fix .. add -c02 vasm6502_oldstyle -c02 -Fbin -dotdir wozmon.s
Below Apple I Manual with the sourcecode for Wozmon
Using searle’s design, i can draw pixels using composite video out.
Converting b/w png to hex include files, for usage in vasm I did the following.
#Python script to convert black levels to pixels from PIL import Image i = Image.open("fash.png") pixels = i.load() # this is not a list, nor is it list()'able width, height = i.size all_pixels = [] for x in range(width): for y in range(height): cpixel = pixels[x, y] if cpixel[1] == 255: s = '\t.db 0x05,' + hex(int(x)) + ',' + hex(int(y)) print (s)
Running and output example
python3 image.py > out head out .db 0x05,0x1,0x16 .db 0x05,0x1,0x18 .db 0x05,0x1,0x19 .db 0x05,0x2,0x7 .db 0x05,0x2,0x8 .db 0x05,0x2,0xc .db 0x05,0x2,0xd .db 0x05,0x2,0x17 .db 0x05,0x3,0x5
Control codes and vasm include
01 (01) - Cursor home (Standard ASCII) 04 (04) - Cursor solid 05 (05) - Set graphics pixel (next two bytes = x,y) 0C (12) - Clear screen (Standard ASCII) 0D (13) - Carriage return (Standard ASCII) 0E (14) - Set column 0 to 79 (2nd byte is the column number) or 0 to 39 for a 40 char line 0F (16) - Set row 0 to 24 (2nd byte is the row number) 1B (27) - ESC - reserved for ANSI sequences vasm include part: message: .db 0x01,0x0c ; home and clear .db 0x1b,0x2d ; disable ansi translation include "out" ; include hex "png" .db 0x00 ; end with 0 (part of message print routine)
I’ve got a ROM in my 6502 which can load programs at $0200.
When running own programs i want to use IRQ’s, but my rom is also using IRQ routines.
So i was wondering if i could ‘hijack’ this IRQ for own program purposes.
So i’ve altered the rom to use a vector in userspace.
All seems fine and dandy … buzzer is sounding, but no blinky leds.
When flashing the rom with only my program, everything works ..
So whats going on? .. anyone?
00000000 78 a9 6e 85 f1 a9 02 85 f2 58 a9 ff 8d 03 50 8d |x.n......X....P.| ; sei , lda #$6e, store $f1, lda #$02, store $f2 - so address $026e 00000010 02 50 a9 00 8d 01 50 8d 00 50 85 04 20 45 02 a9 |.P....P..P.. E..| 00000020 77 8d 04 50 a9 07 8d 05 50 20 2f 02 4c 29 02 38 |w..P....P /.L).8| 00000030 a5 00 e5 04 c9 19 90 0c a9 40 4d 00 50 8d 00 50 |.........@M.P..P| 00000040 a5 00 85 04 60 a9 00 85 00 85 01 85 02 85 03 a9 |....`...........| 00000050 c0 8d 0b 50 a9 a0 8d 0e 50 a9 0e 8d 08 50 a9 27 |...P....P....P.'| 00000060 8d 09 50 a9 00 8d 04 50 8d 05 50 58 60 40 48 a9 |..P....P..PX`@H.| ; at $6e opcode 48 (pha) 00000070 0e 8d 08 50 a9 27 8d 09 50 e6 00 d0 0a e6 01 d0 |...P.'..P.......| 00000080 06 e6 02 d0 02 e6 03 68 4c f3 00 |.......hL..|
ROM parts
MYIRQ = $F0 ; Own IRQ vector <=================== my additions/alterations ; Below definitions for VIA 1 my loadable program uses VIA 2 PORTB = $6000 ; VIA port B PORTA = $6001 ; VIA port A DDRB = $6002 ; Data Direction Register B DDRA = $6003 ; Data Direction Register A -------------8<------- snip PROGRAM_LOCATION = $0200 ; memory location for user programs .org $8000 main: ; boot routine, first thing loaded ldx #$ff ; initialize the stackpointer with 0xff txs ; ISR redirect code <=================== my additions/alterations sei lda #$4C sta MYIRQ sta MYIRQ + 3 lda #<ISR sta MYIRQ + 1 sta MYIRQ + 4 lda #>ISR sta MYIRQ + 2 sta MYIRQ + 5 cli ; End ISR redirect <=================== till here ; below this the standard rom routines -------------8<------- snip .org $FFC9 ; as close as possible to the ROM's end ISR: <====================== Whole ISR not my code CURRENT_RAM_ADDRESS = Z0 ; a RAM address handle for indirect writing pha tya pha lda ISR_FIRST_RUN ; check whether we are called for the first time bne .write_data ; if not, just continue writing lda #1 ; otherwise set the first time marker sta ISR_FIRST_RUN ; and return from the interrupt jmp .doneisr .write_data: lda #$01 ; progressing state of loading operation sta LOADING_STATE ; so program_ram routine knows, data's still flowing lda PORTB ; load serial data byte ldy #0 sta (CURRENT_RAM_ADDRESS),Y ; store byte at current RAM location ; increase the 16bit RAM location inc CURRENT_RAM_ADDRESS_L bne .doneisr inc CURRENT_RAM_ADDRESS_H .doneisr pla ; restore Y tay pla ; restore A rti .org $fffc .word main ; Main ROM program .word MYIRQ ; Redirect to OWN irq vector <=================== my additions/alterations
RAM Program
; Second VIA stuff PORTB = $5000 PORTA = $5001 DDRB = $5002 DDRA = $5003 ;------------------8<------------- ; Vector pointer on zero page MYIRQ = $F0 ticks = $00 ; 4 Bytes toggle_time = $04 ; 1 Byte .org $0200 start: ; IRQ REDIRECT sei ; irq masked lda #<irq ; get low byte IRQ routine address sta MYIRQ + 1 ; store at $F1 lda #>irq ; get high part of address sta MYIRQ + 2 ; store at $F2 cli ; irq enabled ; IRQ END REDIRECT ; init of program part lda #%11111111 sta DDRA sta DDRB lda #$00 sta PORTA sta PORTB sta toggle_time jsr init_timer lda #$77 sta T1CL lda #$07 sta T1CH loop: ; loop jsr update_led ; update led routine jmp loop update_led: sec lda ticks sbc toggle_time cmp #25 bcc exit_update_led ; Toggle led lda #%01000000 eor PORTB sta PORTB lda ticks sta toggle_time exit_update_led: rts ;-----------------------------8<------------- snip irq: pha lda #$0e sta T2CL lda #$27 sta T2CH inc ticks bne end_irq inc ticks + 1 bne end_irq inc ticks + 2 bne end_irq inc ticks + 3 end_irq: pla jmp MYIRQ + 3 ; jmp to vector which points to ROM routine ; should be $FFC9
Work in progress code
PORT2B = $5000 ; VIA PORTB PORT2A = $5001 ; VIA PORTA DDR2B = $5002 ; Data direction register DDR2A = $5003 ; Data direction register PORTB = $6000 ; display PORTA = $6001 ; control display + matrix keyboard DDRB = $6002 ; data direction register DDRA = $6003 ; data direction register SID = $7000 ; sid base address E = %10000000 ; enable bit RW = %01000000 ; RW bit RS = %00100000 ; Register Select bit HOME = %00000010 ; VIA PORTB HOME command DADDR = %00010000 ; VIA DADDRESS LINENO = $0200 ; temp address linenumber (move to other location) NEXTLINE = 40 ; 2x16 Chars but internally 40 .org $8000 reset: ldx #$ff txs ; reset stack ; ################################################### ; # DISPLAY CONTROL # ; ################################################### ; VIA Setup lda #%11111111 ; Set all pins on port B to output sta DDRB lda #%11100000 ; Set top 3 pins on port A to output sta DDRA ; DISPLAY Setup lda #%00111000 ; Set 8-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 ; ################################################### ; # PRINT MESSAGE LINE NO 0 # ; ################################################### lda #0 ; set line number sta LINENO ; store for subroutine jsr gotoline ; move cursor ldx #0 ; message index pointer print: lda message0,x ; start of message beq nextprint ; stop when null in message (asciiz <- Zero padded) jsr print_char ; print char inx ; incr index jmp print ; resume print ; ################################################### ; # PRINT MESSAGE LINE NO 1 # ; ################################################### nextprint: lda #1 ; set line number sta LINENO ; store jsr gotoline ldx #0 ; index pointer print2: lda message1,x ; absolute address message + x in A beq sidsound ; if x is 0, end of message jsr print_char ; jump subroutine inx ; increment x jmp print2 ; loop print2 ; ################################################### ; # SID SOUND # ; ################################################### sidsound: lda #0 sta SID+$5 ; attack/decay duration lda #250 sta SID+$6 ; sustain level/release duration lda #$95 ; frequency voice 1 low byte sta SID+$0 lda #$44 ; frequency voice 1 high byte sta SID+$1 lda #%00100001 ; sawtooth + gate sta SID+$4 ; control register voice 1 lda #$0f ; filter mode and volume (bits 3-0 main volume) sta SID+$18 ; filter mode and volume ; ################################################### ; # 2ND VIA # ; ################################################### lda #%11111111 ; set port A output sta DDR2A lda #%11111111 ; all ones! sta PORT2A ; ################################################### lda #%11111111 ; set port A output sta DDR2A lda #%11111111 ; all ones! sta PORT2A ; ################################################### ; # MAIN PROGRAM LOOP # ; ################################################### loop: jmp loop ; 1234567812345678 message0: .asciiz "VIA 1,2 SID TEST" message1: .asciiz " FASH 2022 " ; ################################################### ; # ONLY SUBROUTINES # ; ################################################### ; ################################################### ; # Subroutine gotoline # ; # Moves character placement position on display # ; # Needs : $LINENO ADDRESS # ; # Exit values : - # ; # Destroys registers: - # ; ################################################### gotoline: pha ; store a txa pha ; store x ldx LINENO lda #HOME ; cursor down jsr lcd_instruction lda #$80 nextline: ldx LINENO cpx #00 beq endnextlines loopline: adc #40 jsr lcd_instruction dex stx LINENO jmp nextline endnextlines: pla ; pop a tax ; a to x pla ; pop a rts ; ################################################### ; # LCD SUBROUTINES # ; ################################################### lcd_wait: pha lda #%00000000 ; Port B is input sta DDRB lcdbusy: lda #RW sta PORTA lda #(RW | E) sta PORTA lda PORTB and #%10000000 bne lcdbusy lda #RW sta PORTA lda #%11111111 ; Port B is output sta DDRB pla rts lcd_instruction: jsr lcd_wait sta PORTB lda #0 ; Clear RS/RW/E bits sta PORTA lda #E ; Set E bit to send instruction sta PORTA lda #0 ; Clear RS/RW/E bits sta PORTA rts print_char: jsr lcd_wait sta PORTB lda #RS ; Set RS; Clear RW/E bits sta PORTA lda #(RS | E) ; Set E bit to send instruction sta PORTA lda #RS ; Clear E bits sta PORTA rts nmi: rti irq: rti .org $fffa .word nmi .word reset .word irq ; .word $0000