
Cisc-8
nailed-barnacle/Cisc-8-ttl-processor
A cut-down version of the 8080 processor using HCTTL and including a discrete ALU and instruction decoder

Resources for an 8 bit computer based on the 6502 micro processor
6502-pactvm v01 is an open-source printed circuit board by napicella, from the napicella/8-bit-computer repository on GitHub. It is a 2-layer board of 99 × 96.5 mm with 15 parts on 88 nets, routed with 829 tracks and 10 vias.
It is built around the UM245R, 74HC00D and 74HC4075D, with the AT28C256-15PU and MXO45T-2C-1M000000 among its other parts. Its parts include 8 ICs, 4 resistors, 1 connector, 1 switch and 1 crystal. It belongs with the retro computing and games boards of this library.
Resources for an 8 bit computer based on the 6502 microprocessor.
Check the datasheets folder for the list of components.
| Address (16 bits) | Address (hex) | Device | Length |
|---|---|---|---|
0000 0000 0000 0000 | 0x0000 | RAM | |
0111 1111 1111 1111 | 0x7FFF | RAM | 0x8000 |
1000 0000 0000 0000 | 0x8000 | VIA | |
1000 1111 1111 1111 | 0x8FFF | VIA | 0xFFF |
1001 0000 0000 0000 | 0x9000 | UM245 | |
1001 1111 1111 1111 | 0x9FFF | UM245 | 0xFFF |
| 1010 0000 0000 0000 | Unused | ||
| 1011 1111 1111 1111 | Unused | ||
1110 0000 0000 0000 | 0xE000 | ROM | |
1111 0000 0000 0000 | 0xFFFF | ROM | 0x2000 = 0xFFFF-0xE000+1 |
The bits highlighted in the address are part of the address decoding which enable the chip. For example, if the most significant bit of the address is low, the RAM is enabled, if the three most significant bits are (100) the VIA is enabled. Address decoding is described later.
The 65c02 needs a stack for the jsr and rst instructions (assembly subroutines).
The stack boundaries are set in the chip and expected to be between 0x0100 and 0x01FF.
The stack grows from 0x01FF (top) to 0x0100 (bottom), for a total of 265 bytes.
| Address (16 bits) | Address (hex) | Device | Length |
|---|---|---|---|
| 0000 0000 0000 0000 | 0x0000 | RAM | |
| 0000 0001 0000 0000 | 0x0100 | RAM Stack | |
| 0000 0001 1111 1111 | 0x01FF | RAM Stack | 0xFF |
| 0111 1111 1111 1111 | 0x7FFF | RAM | 0x8000 |
The whole address space between 0x8000 and 0x9FFF is mapped to the VIA to simplify the address decoding, but the VIA only needs the first 16 bytes in that address space.
| Address (hex) | Description |
|---|---|
0x8000 | I/O Register B |
0x8001 | I/O Register A |
0x8002 | Data Direction Register B |
0x8003 | Data Direction Register A |
0x8004 | T1 Low Order Latches/Counter |
0x8005 | T1 High Order Counter |
0x8006 | T1 Low Order Latches |
0x8007 | T1 High Order Latches |
0x8008 | T2 Low Order Latches/Counter |
0x8009 | T2 High Order Counter |
0x800a | Shift Register |
0x800b | Auxiliary Control Register |
0x800c | Peripheral Control Register |
0x800d | Interrupt Flag Register |
0x800e | Interrupt Enable Register |
0x800f | I/O Register A sans Handshake |
0x8010 - 0x8fff | Mirrors of the sixteen VIA registers |
The whole address space between 0x9000 and 0x9FFF is mapped to the UM245 to simplify the address decoding, but the UM245 only needs the 3 bytes in that address space.
| Address (hex) | Description |
|---|---|
0x9000 | Unused |
0x9001 | Write |
0x9002 | Read |
0x9003 | Unused |
0x9004 | Status |
0x9005 - 0x900f | Unused |
0x9010 - 0x9fff | Mirrors |
The UM245 contains an internal bidirectional FIFO buffer, decoupling the communication.
The Status address allows to check if the device is ready to accept data (MCU can write) and
if the device has data to be read (MCU can read). If the device is busy for a write, the Status contains a 1 in the 1st bit (LSB). If the device does not have data to be read, the Status contains a 1 in the 2nd bit (LSB).
Example assembly routine to read one byte of data:
UART_WRITE = $9001
UART_READ = $9002
UART_STATUS = $9004
UART_WRITE_BUSY_MASK = %00000001
UART_READ_NO_DATA_MASK = %00000010
read_uart_byte:
read_uart_byte_loop:
lda #UART_READ_NO_DATA_MASK
and UART_STATUS
bne read_uart_byte_loop ; can't read, no data
; set return value
; low word : (A low byte, X high byte)
lda UART_READ
ldx #$00
rtsDownload minipro 0.5. Follow the installation instructions.
After installing, check it works by attaching the programmer to the laptop, then run the minipro --version. You should see minipro recognizing the device:
> minipro --version
Supported programmers: TL866A/CS, TL866II+,T48 (experimental)
Found TL866II+ 04.2.132 (0x284)
Device code: 02092661
Serial code: 5BJVT6MR20ZZJBB0JPAE
minipro version 0.6 A free and open TL866 series programmer
Commit date: 2024-02-11 20:34:27 -0800
Git commit: 77c26fd2e5d8674d65382a3eff4628013483c4d2
Git branch: master
TL866A/CS: 14184 devices, 44 custom
TL866II+: 16281 devices, 45 custom
Logic: 283 devices, 4 customNote: For Ubuntu 20, version 0.6 (latest as of writing fails during upload):
minipro -p AT28C64B -w kernel.bin
Found TL866II+ 04.2.132 (0x284)
Device code: 02092661
Serial code: 5BJVT6MR20ZZJBB0JPAE
Erasing... 0.02Sec OK
Writing Code... 1.67Sec OK
Reading Code... 0.11Sec OK
Verification failed at address 0x0000: File=0x00, Device=0xFF
make: *** [Makefile:20: install] Error 1git clone https://github.com/cc65/cc65.git
cd cc65
makeMove the generated binaries somewhere under $PATH.
The 8 bit computer running a simple program which turns on eight leds, first the ones in a even position and then the ones in a odd position, looping forever.
You do not need cc65 for the hello world.
Run:
python blink-leds.pywhich generates the image for the ROM in the file program.bin.
Then connect the eeprom to the programmer and run:
minipro -p AT28C64B -w program.binYou need cc65.
cl65 -C load.cfg --cpu 65C02 --no-target-lib blink.swhich builds the blink binary.
Note
This binary should be exactly the same as the one generated by the python program
python blink-leds.py
cl65 -C load.cfg --cpu 65C02 --no-target-lib blink.scompare with:
diff <(xxd ./blink) <(xxd ./program.bin)which should return nothing (meaning the binary are the same).
minipro -p AT28C64B -w blinkcalling assembly routines from C (calling sequence and fast calls) https://www.cc65.org/doc/customizing-7.html
How do hardware timer/time sleep works https://www.youtube.com/watch?v=g_koa00MBLg&ab_channel=BenEater
Reserving memory location in assembly
.zeropage
_led_data: .res 1, $00
.segment "CODE"
; you can use _led_data in the code, eg.
lda #$FF
sta _led_dataLinks
You can't.
From: https://www.reddit.com/r/beneater/comments/mm3m9s/how_to_have_ca65_output_as_raw_binary/
Simple assemblers convert assembler source code file(s) directly into a final binary output file in one step.
More complex development systems convert each source code file into an intermediary object code file, then a linker/locater pulls together and converts all object files into one target binary file. All linkers require some type of configuration file that tells it where your RAM and ROM (aka Flash) memory is located, unless it has some known assumptions about the final target. Though more complicated, this approach is a lot more flexible, because this concept supports any combination of assemblers and compilers that creates the same object code.
Currently this development system only supports assembler and C, but theoretically new compilers could be created for other high-level computer languages too. As long as future compilers create compatible object files then LD65 should be able to support them too.
From a generic point of view of these concepts, there are plenty of books about this subject matter, and likely lots of stuff written about it on the internet. I'll leave it up to you to further investigate and educate yourself. Good luck.
C Source Code Files(s) ---> CC65 [compiler] ---> Object Code File(s)
Assembler Source Code File(s) ---> CA65 [assembler] ---> Object Code File(s)
Object Code File(s) and optional Libraries ---> LD65 [linker] and Config File ---> Binary or Hex File
Binary or Hex File ---> Chip Programmer Tool ---> ROM/Flash/EEPROM chipNote that ca65 do not handle the org directive as other assemblers for 6502.
From: https://wiki.cc65.org/doku.php?id=cc65:the_.org_directive
Most other assemblers for the 6502 handle .ORG different than ca65. The reason is, that these tools usually do not use a linker. Professional development systems separate the job of the assembler and the linker to gain more flexibility and to implement features not possible with just one tool.
If you don't have a separate linker, the assembler is responsible for code translation and code placement. With such an assembler, you use the .ORG directive to place your code at a specific address.
For example:
.org $0000
NOP
.org $FFFF
NOPWhen compiled:
ca65 --cpu 65sc02 -o sample.o sample.s
ld65 -t none -o sample sample.oProduces a 2 bytes ROM image, instead of 64K:
> ls -lha ./sample
-rw-r--r-- 1 user domain^users 2 Apr 20 23:19 ./samplevasm on the other hand for the same program produces 64K:
> /tmp/vasm/vasm6502_oldstyle -Fbin -dotdir -o binary.out sample.s
...
> -rw-r--r-- 1 napicell domain^users 64K Apr 20 23:25 ./binary.out
> hexdump -C binary.out
00000000 ea 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
0000fff0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ea |................|
00010000da65 --cpu 65C02 -g --comments 4 blink_subroutines | lessBefore we start. 6502 reads from 0x1ffc (low byte) and 0x1ffd (high byte) the address where to read the first instruction. We need to write at that address where that is. In this project, the first instruction is
at location 0 in the ROM, which is 0xE000 (1110000000000000) as seen by the CPU (see memory mapping)
blink-leds.py creates the binary by specifing the 6502 instructions in binary. No assembler.
The program does not RAM. It blinks without a wait, so run it with a slow clock. The python script creates
a binary that exactly fits the rom and sets the address 0x1ffc and 0x1ffd to 0xE000blink.s it's the assembly version of the previous program.ram_test.s is the first program that needs a ram to be installed. It verfies the ram works by storing something in ram and reading it backblink_subroutines.s runs the blink program with subroutines. This requires a ram since the RTS function (return sub routine) needs to know where to return to. This info is stored in the stack by the JSR (jump sub routine). The assemply also use PHX and PLX (push/pull x register to stack) to showcase how a subroutine can avoid interfere with registers being set outside of the subroutine.| Qty | Value | Footprint | References |
|---|---|---|---|
| 4 | 1k | Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_Horizontal | R1, R2, R3, R4 |
| 2 | 74HC00 | Package_DIP:DIP-14_W7.62mm_Socket_LongPads | U2, U4 |
| 1 | 74HC4075 | Package_DIP:DIP-14_W7.62mm_Socket_LongPads | U3 |
| 1 | AS6C62256 | Package_DIP:DIP-28_W15.24mm_Socket_LongPads | U5 |
| 1 | AT28C256-15PU | Socket:DIP_Socket-28_W11.9_W12.7_W15.24_W17.78_W18.5_3M_228-1277-00-0602J | IC1 |
| 1 | Conn_01x06_Pin | Connector_PinHeader_2.54mm:PinHeader_1x06_P2.54mm_Vertical | J1 |
| 1 | MXO45T-2C-1M0000 | MXO45T_OSCILLATOR:MXO45T2C1M0000 | Y1 |
| 1 | SW_SPST | Button_Switch_THT:SW_PUSH_6mm | SW2 |
| 1 | UM245R | UM245_LIB:UM245R-DIP-24_W15.24mm_Socket_LongPads | U7 |
| 1 | W65C02SxP | Package_DIP:DIP-40_W15.24mm_Socket | U1 |
| 1 | W65C22SxP | Package_DIP:DIP-40_W15.24mm_Socket | U6 |
It measures 99 × 96.5 mm and has 2 copper layers, 1.6 mm thick.
15 parts, built around the UM245R, 74HC00D, 74HC4075D and AT28C256-15PU. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
From the napicella/8-bit-computer repository on GitHub, at the commit this page was made from: the board is kicad-projects/6502-pactvm-v01/6502-pactvm-v01.kicad_pcb and its schematic kicad-projects/6502-pactvm-v01/6502-pactvm-v01.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository states no licence, so its author keeps all rights: ask napicella before reusing the design.

nailed-barnacle/Cisc-8-ttl-processor
A cut-down version of the 8080 processor using HCTTL and including a discrete ALU and instruction decoder


DoctorWkt/CSCvon8
A crazy small 8-bit CPU built with only seventeen 7400-series chips.




