Cobalt-68: Homebrew 68008 computer

68008-based homemade computer with SD-card, VGA and PS/2 support

Public Chat
Similar projects worth following
This project aims at creating of homemade fully-functinal computer based on Motorola MC68008 CPU. It uses atmega640 chip as main perepherial controller which greatly simplifies mainboard design. Atmega handles UART, SPI (for SD) and PS/2. Otherwise it is pretty classical microcomputer design with RAM, ROM, expansion slots and Video Display Controller expansion card.

Brief description of system:
- CPU: Motorola MC68008 (48 pin DIP package), 8 MHz clock speed.
- RAM: 512 KB static RAM
- PS/2 Keyboard suppport
- Storage: 2xSD slots.
- 4x Expansion bus slots.
- Monochrome 80x25 characters Video Display Controller (VDC)

- ROM-based machine code monitor.
- CP/M-like operation system.
- Basic OS commands (ls, mkdir, etc.)
- Text editor
- Lisp interpreter

So far, so good...

Hello, Hackaday! I want to tell you about my pet project aimed at creation of homebrew computer.  I've been doing this project for three years. In this entry I want to briefly summarize what's been done.

Why I'am doing this?

Mostly for fun, of course. For 20+ year I've been doing software development and I know a lot about it. But the hardware has always remained a mystery for me. To fill in that gap in my knowledge I made some hardware projects (including making my own CPU in FPGA, but that's out of scope). Another reason is retrocomputer nostalgia. Combine that together and you get main idea of this project - create retro-styled computer system with hardware and software.

Why MC68008?

Initially I wanted to use Intel 8080, Z80 or Intel 8086 for my project. But I really do not like it's instruction set and segmentation approach (in case of 8086), so I started looking for alternative. Motorola 68000 series immediately catched my eye for it's clean and lean pdp-ish instruction set. Personally, I think that it is a shame that x86 architecture took over the world. It should be 68000. To reduce complexity I've chosen 8-bit bus version of that CPU - MC68008. I was able to get 8MHz rated 48-pin DIP chips.

Overall design approach

Speaking of architecture my system is pretty much classical one with CPU, ROM and RAM using one system bus. There are four expansion slots which are buffered by 74245 buffers and provide expansion capabilities for system. Glue logic and address decoding are implemented using ATF16V8 and GAL22V10D PLD chips.

One interesting feature of my system is usage of Atgema640 MCU as main peripheral controller. It allows me to save a lot of work by providing single-chip solution for several system functions:

  • UART
  • SPI bridge for SD card access.
  • PS/2 keyboard controller
  • Programmable interrupt controller
  • (planned, but not implemeted): 
    • EEPROM controller
    • Real-time clock

By wiring a lot of peripherals through MCU chip I translate a lot of design issues from hardware to firmware, which greatly reduces time and effort required to integrate them into system. But this approach has one major drawback as MCU chip is quite slow. For example when performing SD card IO main bottle neck is not SPI or memory interface, but internal operations inside microcontroller program (bits and ports manipulation). This is a tradeoff of the design decision - you get simplicity by sacrificing performance. 

Software ecosystem

For my computer I've written my own operating system which provides basic services for applications: filesystem, program loading and running, standard user IO using UART, keyboard and monitor controller. I also designed small set of basic system utilities (like, "ls", "mkdir") and applications (editor, toy lisp interpreter, ported PicoC interpreter). I've used some of 3rd party code to save time and effort, full list is provided at gitlab project page.

For software development I use prebuilt GCC cross-compiler for M68K architecture. In future I plan to port some c compiler and thus provide onboard system development capabilities.

  • Cobalt-68: Optimizing SPI SD I/O operations

    Alexey Kosarchuk01/03/2021 at 14:39 0 comments

    As my software ecosystem begin to grow binary image sizes also became larger and larger. For example, most recent addition to software list - ported PicoC C language interpreter (source) has binary size more than 64 KB. Addition of proper C library also has increased almost every binary image size. Program load times also become longer and longer which made working with system quite uncomfortable. Thus I've decided to investigate this issue and optimize system at least for reading.

    Profiling load process

    My system uses an SD card as mass storage device. SD card is linked via SPI interface to Atmega640 microcontroller which exposes SPI access ports to adress space accessible for CPU. CPU then reads and writes data in PIO mode. Microcontroller doesn't handle SD card protocol, that is done by operating system code.

    To profile loading times I've hooked up logic analyzer to certain signals in my system: SS, SCK, CS# for MCU and CS# for RAM. This way I could deduce how much time system spends on CPU<->RAM, MCU<->SPI and internal MCU operations. My first discovery were:

    • One sector (512b) read time is roughly 60ms.
    • SPI communication takes negligible fraction of all time spent.
    • Most of time is CPU<->RAM operation.

    Conclusion: operatiing system code is bottleneck and should be improved.

    Reworking the code

    When I have analyzed relevant code I found that single SPI access operation goes through several layers of procedure calls and is surrounded by conditionals that may enable debug logging. It seemed logical to organize code this way when I was writing it, but ultimately it resulted in very bad perfomance. To improve things I've collapsed several procedures into one, removed conditionals and have made procedure static inline to save cycles on call/return. 

    When I've tested new version I've noticed 100% speed improvement: single sector read now took only 30 milliseconds. This was already an achievment, but there was stil room for improvement.

    Implementing DMA: high expectations, low yield

    My next step was to eliminate CPU from reading at all. My circuitry was designed with future DMA implementation in mind: I had enought signals wired to MCU to make it possible to master the bus. So, I've implemented DMA mode for SPI in the firmware and modified the operating system. Unfortunately tests showed than sector read time has reduced insignificantly: from 30 to 25 ms. That was quite a disappointment. It appears that I underestimated loss on internal MCU operations during DMA process: address counting, ports manipulation, etc. That code also has been improved, but this only reduced sector read time to 18 ms. Mostly this was achieved by parallelizing SPI transfer and internal logicv operations of firmware.


    Comparing to the initial timings I've achieved dramatic improvements in performance: sector read time reduced from 60 to 18 ms, this is 200% improvement. But this feat of optimization has also discovered the ultimate limitation of using general-purpose MCU as perepherial controller. After all optimization actual transfers over SPI accounted only for 15% of time costs. Almost everything else was wasted because of sequential nature of MCU software-defined operations. No breakthrough optimization of this architecture is possible. It also showed that making DMA controller out of general puprose MCU is generally a bad idea.

    Next step in increasing SD Card performance is to design custom hardware controller for SPI and possible DMA using TTL and/or CPLD chips.

View project log

Enjoy this project?



Peabody1929 wrote 06/15/2021 at 16:23 point

It would be interesting to see a block diagram or a schematic of the design.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates