Embedded software

Arduino Uno Led Header

Arduino Scrolling Led Display

I build myself a scrolling led message board and every Christmas and new year I have this in my front window to greet the people in front of my house. Every year I reprogram the Arduino Uno with the wishes I want to display. I has become kind of a tradition here. I used an Arduino Uno (clone) and six MAX7219 based LED Matrix Displays forming a 192 x 8 led area. I chose these number of displays because it would fit my window, but the number of displays you want to use is not limited. When a line is displayed it will scroll on the display from right to left and when the display is fully filled it will scroll on until the whole message is displayed. Then it will wait for a few seconds, clear the display with animation and start a random new message. On this page you can find the hardware and the software for this project. Regards, Hein Pragt

What components do you need?

  • An Arduino Uno board; (Nano will also work)
  • MAX7219 LED Matrix Display 8×32 (2 – 8);
  • 5V DC Power supply at least 3A;
  • Board to build on;
Arduino Uno Led Display1

For my version I used an Arduino Uno clone but an Arduino Nano would also be possible, you would have to find the SPI and SS lines for the Nano yourself. I mounted the led displays on a wooden board with stands and the Arduino Uno at the back. In my first design I included a power supply board (the power supply of the Arduino is by far not sufficient) but in the end it was better to use a switching external power supply of 5V DC to feed the Arduino (Vin) and the Led displays. The led displays will take a lot of current, so more displays means a more powerful power supply.

Arduino Uno Led Display2

The connections are very easy, just two power lines and three SPI lines. The Matrix units come in 8×8 times four on a single board, with holes for the connectors at both sides. What I did was lift off the two outer displays, mount the base board on the wooden board and then connect the connector holes with small wires. This is more reliable and you can fit the display units tight together. Look close at the position of the led matrix boards and put them all in the same position. (Also look carefully when putting the displays back on).

The software

I personally do not like to use Arduino libraries, you have to find the correct one and the correct version or it will not work or give compile errors. So what I did was write the whole driver code myself. The whole Arduino project contains two files, the ledmatrix.ino and a 8×8 font include file. In the sourcecode there is an array of messages, you can fill them as you need, they will be stored in flash so there is (almost) no limit to the size. In the top of the code you can define how many displays you have connected (the number of 8×8 blocks), the code will adjust to this automatically. I give you the full sourcecode you can modify it yourself if you want to. The download link is at the bottom of the page. If you need hardware you can visit my webshop.

Arduino Uno Led Display3

Download

Retro computing webshop

Heinpragt.nl is a daughter site of this website and a webshop focused on retro computer parts, retro electronics components and chips and other articles that have a connection with old retro computers. It is a small webshop that I run myself and I also try to get some more information about retro computers and electronics. Shipments are only made to countries within the European Union.
Retro computing parts webshop

More pages on embedded software

Wifi Light

ESP8226 WIFI led control

ESP8226 Microcontroller The ESP8226 is a very cheap Wi-Fi microcontroller with a complete TCP/IP stack and a 32 bit microcontroller and is made by the Chinese manufacturer Espressif Systems. The chip came to attention in 2014 by a small board (ESP-01) as a cheap Wi-Fi module that could be controlled via a serial interface and through a form of Hayes commands. Soon the chip came to the attention of hackers, mainly due to its low cost, to find other uses. For the low amount of money, the specifications are impressive: a 32-bit RISC CPU (Tensilica Xtensa LX106) with an 80 MHz clock frequency, 64 Kb instruction RAM, 96 KB data RAM, external QSPI flash (512 Kb to 4 Mb), built-in IEEE 802.11 Wi-Fi stack, WEP and WPA/WPA2 authentication, 16 GPIO pins, SPI, I2C, UART and a 10-bit ADC. There are some nice cheap DIY boards for sale with this microcontroller and this page contains information about these boards, documentation, links and specifications, and development tooling. Also a full working sourcecode of a WIFI led controller. Sincerely, Hein Pragt

Wemos D1 mini

Wemos D1A relatively small manufacturer by the name of Wemos brings out nice new developments with the ESP-8266 family on Arduino type shields. One of these fun boards to experiment with yourself is the Wemos D1 mini, a small board equipped with a full Wi-Fi and network stack, a nice number of I/O ports, power supply, a USB connection, serial communication, bootloader, Flash memory and a 32 bit processor with an 80 MHz clock frequency. As in all very nice specifications for a board that costs less than 10 dollar. When you are already used to the standard Arduino IDE and programming environment, you can also use this for the Wemos D1. The correct boards have to be installed in the board manager of the IDE, but then it works almost immediately. There are already many libraries specifically for the ESP-8266 family available for the Wemos D1 mini but I find that many of the standard libraries written for the Arduino also work fine on the Wemos D1 mini. Because I2C and SPI also work standard, many of the boards and shields that are made for the Arduino can also be connected, please note that everything must work on 3v3, but this can also be solved with a level adjustment board or a resistance network. But a standard LCD display or a relay board can easily be connected. Sometimes a few I/O pins have to change definitions and often it works fine. But with 4 Mb of code space and 35 Kb of ram and a 32 bit processor at 80 MHz which is a huge improvement over the 16 MHz 8 bit Arduino processor with 1 to 2 Kb sram. The possibilities of the Wemos D1 mini are therefore very extensive, partly due to the built-in Wi-Fi that you can use ready-to-use.

Link: PDF with instructions for the Wemos D1 on the Arduin IDE.

Wemos OLED display

Wemos D1 Mini Oled DisplayThe first display I used is the WeMos D1 mini OLED shield 64×48 of 0.66 inch with an I2C interface. The shield has many more pins because it can also be controlled differently but of course we like to use I2C because it only uses two I/O lines. At 0.66inch it is quite a small display but is very easy to read as it has a high contrast. It uses the SSD1306 as the interface chip and uses the I2C address 0x3C or 0x3D which can be selected by a solder bridge on the back of the PCB. Very small, so I don’t dare and leave them at the default value. The device was delivered with separate header pins and since you only have 4 connections If you need it, you can also solder the wires directly to the PCB.

Code and example

Wemos D1 Mini Met Oled DisplayDownload: HERE my library for the Wemos D1 OLED display and install it via the IDE in your Arduino environment. Restart the IDE and look at the examples and see it says “oledtest64.ino”. The library works for the combination Wemos D1 and the Wemos OLED display. I also use this library myself and develop it further. With these basic functions you can create extensions in your own code.

I like libraries that only offer basic functions because I usually want to make things in my own way, which are just not in the library or just different which means I am compiling a large amount of code from a library that grows my code and is of no use to me. I wish good luck with this code.

The code of this libray is compact and contains only a few basic functions:


  public:
    Ssd1306(uint8_t i2caddr,uint8_t width,uint8_t height,uint8_t orientation);
    void begin(void); 
    void oledSetPixel(int16_t x, int16_t y, uint16_t color);
    void oledDrawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
    void oledDrawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
    void oledFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
    void oledDrawCircle(int16_t x0, int16_t y0, int16_t r,uint16_t color);
    void oledDrawChar(int16_t x, int16_t y, unsigned char c, uint16_t color);
    void oledPrintLine(int16_t x, int16_t y, unsigned char *c, uint16_t color);
    void oledInvert(void); 
    void oledNormal(void);
    void oledCopyDisplayBuffer(void);
    void oledClearDisplayBuffer(uint8_t value);

The displays can actually show only a little text, with a font of 5×7 this is the division on the screen and a resolution of 64 x 48 pixels, this gives ten columns and 5 rows, so you can effectively lose 50 characters on the screen.

Oled Text Size 1

Sourcecode Wi-Fi led control

This piece of sample code clearly shows the tremendous power of the Wemos D1 mini. The example uses my OLED library and otherwise only use standard supplied / built-in parts. Through this piece of code you can use your mobile phone via the web browser to find an output pin of the Wemos D1 mini module (read: connected relay) on and off. In this example I control the built-in LED. Since the more complete Wi-Fi stack and network stack are in the module as far as we don’t write our own code for this. First you make on your phone to a mobile hotspot and gives it a name and a password, you enter this name and password at const char* ssid and const char* password after which you can compile the code and upload it in the Wemos module. After turning on of the module, it will try to contact your mobile hotspot and then display its IP address on the screen. You then only need to enter this address in the address bar of the browser on your mobile phone and the Wemos module will now behave like an HTTP server and send you a page with the status of the led. Then you can click on a click on the links or switch the LED on the Wemos module on and off by means of a URL parameter. This is just a small example that can be food for many ideas, but I leave that to your imagination. kind regards, Hein Pragt.

// -----------------------------------------------
// Example code WI-FI led control
// -----------------------------------------------
#include 
#include 
#include 

const char* ssid = "HotspotVanUwTelefoon";
const char* password = "WachtwoordHotspotTelefoon";

int ledPin = BUILTIN_LED;
WiFiServer server(80);

Ssd1306 ssd1306(0x3C,64,48,0);

void setup() 
{
String ip;
char buffer[20];

  Serial.begin(9600);
  delay(10);  

  ssd1306.begin(); 
  // Clear the buffer.
  ssd1306.oledClearDisplayBuffer(0);
  ssd1306.oledCopyDisplayBuffer();

  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);

  // Connect to WiFi network
  ssd1306.oledPrintLine(0,0,"Connecting",1);
  Serial.print("Connecting to ");
  Serial.println(ssid);
  ssd1306.oledPrintLine(0,10,(char *)ssid,1); 
  ssd1306.oledCopyDisplayBuffer();

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  ssd1306.oledClearDisplayBuffer(0);
  Serial.println("WiFi connected");
  ssd1306.oledPrintLine(0,0,"Connected ",1);
  ssd1306.oledCopyDisplayBuffer();

  // Start the server
  server.begin();
  Serial.println("Server started");

  // Print the IP address
  Serial.print("Use this URL : ");
  ssd1306.oledPrintLine(0,10,"MY IP:",1);
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  ip = WiFi.localIP().toString();
  ip.toCharArray(buffer, 20);
  ssd1306.oledPrintLine(0,20,buffer,1);
  Serial.println("/");
  ssd1306.oledCopyDisplayBuffer();
}

void loop() {
  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }

  // Wait until the client sends some data
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  }

  // Read the first line of the request
  String request = client.readStringUntil('\r');
  Serial.println(request);
  client.flush();

  // Match the request

  int value = HIGH;
  if (request.indexOf("/LED=ON") != -1) {
    digitalWrite(ledPin, LOW);
    value = LOW;
  } 
  if (request.indexOf("/LED=OFF") != -1){
    digitalWrite(ledPin, HIGH);
    value = HIGH;
  }



  // Return the response
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println(""); //  do not forget this one
  client.println("");
  client.println("");

  client.print("Led pin is now: ");

  if(value == LOW) {
    client.print("On");  
  } else {
    client.print("Off");
  }
  client.println("

"); client.println("Click here turn the LED on pin 5 ON
"); client.println("Click here turn the LED on pin 5 OFF
"); client.println(""); delay(1); Serial.println("Client disconnected"); Serial.println(""); }

ESP8226 download and links

Here are some external links to pages and documents that will be helpful and helpful when getting started with the ESP8226.

More pages on embedded software

Internet Radio Logo

ESP32 based WIFI internet radio

A nice feature of the Internet is online radio (also web radio, net radio, streaming radio, e-radio, IP radio, Internet radio). These are digital audio services transmitted via the Internet. Broadcasting on the Internet is usually referred to as webcasting since it is not transmitted broadly through wireless means. Internet radio involves streaming media, presenting listeners with a continuous stream of audio that typically cannot be paused or replayed, much like traditional broadcast media. The first Internet radio service was launched in 1993. Nowadays most popular radio stations also have an Internet radio stream and there are a lot of specialized radio stations, for instance I really like outlaw country music, and I have a few nice stations in the USA. Kind regards, Hein Pragt.

Building and ESP32 internet radio

So building an Internet radio is not that hard, we need a HTTP stack and a MP3 decoder. Both are available at a very good price, and we also add a simple display and a button to select a station. I have a 3D printer so I created a nice case as well. Lets start with the part list:

  • A VS1053 MP3 codec board;
  • ESP32 board (I used a WROOM version);
  • OLED 64*128 display module I2C;
  • Push button;
  • 10 K resistor;

Oled Display Module 0.96 128×64 I2C

Ssd1306 I2c Oled DisplayThe display I used is a fairly standard OLED cheap display with white pixels, a resolution of 128 x 64 pixels and a control by means of I2C by the the SSD1306 driver IC. This shield also only needs two data lines and it consumes minimal current so that it can also be used in projects that need to be powered by a battery or battery. The size of this screen is slightly larger than the previous one and measures 26.0 x 15.0 mm. The module runs on 3v3 and can be connected to the outputs of the 3v3 output of the ESP32 and the I2C lines do not need voltage converters. The I2C address of this OLED shield is 0x3C by default. The screen is very clearly readable due to a very high contrast. The SSD1306 is a single-chip CMOS OLED/PLED driver with controller for displays with a maximom resolution of 128 x 64. The IC contains a display controller with display RAM and a built-in oscillator so that it can be used with minimal external components. It has a built-in 256 steps brightness control. It has a 6800/8000 series compatible Parallel Interface and a I2C interface.

VS1053 MP3 codec board

Vs1053The VS1003 audio codec module is a complete MP3/WMA/MIDI audio decoder and ADPCM encoder that features a high quality stereo DAC (Digital to Analog Converter), a 16-bit adjustable ADC (Analog to Digital Converter) and a high quality stereo earphone driver (30 ohms). This module is ideal for adding audio decoding and encoding capabilities to embedded systems. It has a serial data and control interface (SPI) that makes it easy to connect to the ESP32 or any othe board that has an SPI interface. It also has a headphone and audio output interface and a microphone for recording but we cont be using this. It supports MP3 and WAV stream and has a single 5 V power supply that is On-board converted to 3.3 V and 2.5 V for the chips on the board and it uses about 800 mA. When we feed it with 32 bytes chunks of audio data, it will decode and output the audio trough the headphone jack. We can connect this to an amplifier to play it on a stereo set or PC speaker set.

ESP32 connections

Esp Pins Radio

ESP32 internet radio shematics

Esp Radio Schematic

Connecting everything up is not that hard, although the pins on the ESP32 are very hard to read because the text is very small. Also check the pins of the ESP32 board you have, I have noticed some difference in different boards. The name of the pin is the clue you have to follow. The entire device is powered through the micro-usb port of the ESP32. Load the code in the Arduino IDE (you have to make sure it supports the ESO32 first) and you may have to download some additional libraries like the “ESP_VS1053_Library-master” and the “esp8266-oled-ssd1306-master” library. Find the place in the code where you have to put your WIFI network name and password and compile the code.

After uploading the software it will say a welcome phrase and then connect to the WIFI. It will remember the last station you selected and then start streaming the MP3 data to the MP3 codec and you will hear the internet radio station. I really like this little device and I have filled the array in the source code with a few radio stations, you can delete and add your own, as you like and personalize the device. Have fun.

The ESP32 sourcecode

Do not copy and paste, the download link is below the listing!

// ----------------------------------------------------------------
// ESP32 + VS1053  Internet radio
// Hein Pragt 2022
//
// VS1053 - connections 
// XRST = EN (D3)
// MISO = D19
// MOSI = D23
// SCLK = D18
// VCC = 5V / 3.3 V  and  Gnd = Gnd 
// ----------------------------------------------------------------

#include <VS1053.h> 
#include <Preferences.h> 
#include "StartMp3.h"
#include <WiFi.h>
#include <HTTPClient.h>
#include <esp_wifi.h>
#include "SSD1306.h"

char ssid[] = "your wifi ssid";
char pass[] = "your wifi password";

Preferences preferences;
SSD1306     display(0x3c, 21,22);
WiFiClient  client;

unsigned int counter,old_counter;
int change = 13;
bool pinflag = true;
int status = WL_IDLE_STATUS;
uint8_t mp3buffer[128]; 

struct _stationList {
  char sname[64];
  char host[128];
  char path[128];
  int  port;
} stationList[] = {
{ "NPO Radio 1 " ,   "icecast.omroep.nl", "/radio1-bb-mp3", 80 },
{ "NPO Radio 2 " ,   "icecast.omroep.nl", "/radio2-bb-mp3", 80 },
{ "NPO 2 S & J " ,   "icecast.omroep.nl", "/radio6-bb-mp3", 80 },
{ "NPO 3FM     " ,   "icecast.omroep.nl", "/3fm-bb-mp3", 80 },
{ "NPO 3FM Alt " ,   "icecast.omroep.nl", "/3fm-alternative-mp3", 80 },
{ "NPO Radio 5 " ,   "icecast.omroep.nl", "/radio5-bb-mp3", 80 },
{ "538 Radio   " ,   "20073.live.streamtheworld.com", "/RADIO538.mp3", 80 },
{ "QMusic      " ,   "icecast-qmusicnl-cdp.triple-it.nl", "/Qmusic_nl_live.mp3", 80 },
{ "Radio 10    " ,   "25533.live.streamtheworld.com", "/RADIO10.mp3", 80 },
{ "Radio 10 70 " ,   "22343.live.streamtheworld.com", "/TLPSTR18.mp3", 80 },
{ "Radio 10 80 " ,   "25233.live.streamtheworld.com", "/TLPSTR20.mp3", 80 },
{ "Radio 10 90 " ,   "25353.live.streamtheworld.com", "/TLPSTR22.mp3", 80 },
{ "Radio 10 Love" ,  "25293.live.streamtheworld.com", "/TLPSTR04.mp3", 80 },
{ "Veronica    " ,   "22343.live.streamtheworld.com", "/VERONICA.mp3", 80 },
{ "Sky Radio   " ,   "25293.live.streamtheworld.com", "/SKYRADIO.mp3", 80 },
{ "Country Rocks" ,  "stream.dbmedia.se", "/crrMP3", 80 },
{ "Outlaw Country" , "ice10.securenetsystems.net", "/KIEV2", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 },
{ "~" ,   "0", "0", 80 }
};


// Wiring of VS1053 board (SPI connected in a standard way)
#define VS1053_CS    32
#define VS1053_DCS   33
#define VS1053_DREQ  35 

#define VOLUME  100      // volume level 0-100

VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);

// -----------------------------------------
// Setup and init
// -----------------------------------------

void setup ()
{
display.init();
display.invertDisplay();
display.setFont(ArialMT_Plain_16);
display.normalDisplay();
display.setColor(WHITE);
display.drawString(0,0,"  ESP32 Radio");
display.setFont(ArialMT_Plain_10);
  
   pinMode(change,INPUT_PULLUP);
   Serial.begin(115200);
   delay(500);
   SPI.begin();
   player.begin();   // initialize VS1053 player
   player.setVolume(VOLUME);
   
   WiFi.begin(ssid, pass);
   while (WiFi.status() != WL_CONNECTED) {
     delay(500);
     Serial.print(".");
   }
  Serial.println("WiFi connected");  
  Serial.print("IP address:");  
  Serial.println(WiFi.localIP());
  display.setColor(WHITE);
  preferences.begin("my-app", false);
  counter = preferences.getUInt("counter", 0);
  old_counter = counter;
  delay(100);
  player.playChunk(StartUp, sizeof(StartUp)); //VS1053 is wake up & running
  delay(1000);
  station_connect(counter); 
}


// -----------------------------------------
// Main loop
// -----------------------------------------

void loop()
{
  // Play stream
  if (client.available() > 0) {
     uint8_t bytesread = client.read(mp3buffer, 128);
     player.playChunk(mp3buffer, bytesread);
  }
  // Check key
  if (digitalRead(change) == 0 and pinflag == true) {
    pinflag = false;
    counter++;
    if (stationList[counter].sname[0] == '~') { // Empty field
      counter = 0;
    }
  } 
  if (old_counter != counter) {
    player.softReset(); 
    pinflag = true;
    station_connect(counter); 
    old_counter = counter;
  } 
}


// -----------------------------------------
// Connect to radiostation
// -----------------------------------------

void station_connect (int station_no) 
{
  if (client.connect(stationList[station_no].host,stationList[station_no].port) ) {
    Serial.println("Connected now");
  }
  client.setNoDelay(true);
  Serial.print(String("GET ") + stationList[station_no].path + " HTTP/1.1\r\n" + "Host: " + stationList[station_no].host + "\r\n" + "Connection: close\r\n\r\n");     
  client.print(String("GET ") + stationList[station_no].path + " HTTP/1.1\r\n" + "Host: " + stationList[station_no].host + "\r\n" + "Connection: close\r\n\r\n");     
  display.clear();
  display.setFont(ArialMT_Plain_16);
  display.drawString(0,0,"ESP32  Radio");
  display.drawString(0,21,"Station: " + String(station_no));
  String line4 = String(stationList[station_no].sname); 
  display.drawString(0,42,line4.substring(0,60));
  display.display();
  preferences.putUInt("counter",station_no); 
  Serial.printf("Set counter to new_value: %u\n", station_no);
}

Downloads

Download: Full sourcecode Zip file.

To compile the code you will need some libraries, i have used the next libraries:

  • ESP_VS1053_Library-master
  • esp8266-oled-ssd1306-master

This is my build

I also have a 3D printer and I design using Freecad so I made my own case for this internet radio.

Internetradio

Links

More pages on embedded software

Fz9gfz0jfx0inh3

Arduino RFID Door Lock

On this page I will document and explain how to build a relatively cheap electric door lock based on an Arduino Nano and a RFID shield. I have a small garden with a bicycle shed that has a door to the common area behind our house. I have a lock on this door, but a lot of people have a key, my children, my neighbor and buying a new spare key takes long and is expensive. And then people lose their key, so I thought of a simple solution where I could make many keys and could authorize, but also unauthorize keys. I though of a solution using simple 125 Khz RFID keys and a cheap reader and an Arduino Nano processor. I ordered an electric lock online because it was hard to get here in a shop and rather expensive. I gave everyone who needs access to my garden (fi. to feed the animals) a small RFID key, and created a 3D printed reader next to the door and its working fine. On thsi page I will show you how I build it, because it’s all standard components, you could design your own version, if for instance you add a clock chip you could even give certain RFID keys only access at specific times. You can download all the files from this website, if hope this project will inspire you to create your own version. Regards, Hein Pragt

Step 1: So What Components Do You Need?

  • An Arduino Nano board;
  • EM4100 RDM-6300 RFID card reader 125 khz (or compatible);
  • Some 125 Khz RFID badges;
  • Led with 330 Ohm resistor;
  • 2N7002 Mosfet;
  • 10 K resistor;
  • 1N4004 diode;
  • 5 Volt relay;
  • 7808 voltage regulator;
  • 12V power supply at least 2A;
  • Terminal connector for power;
  • Terminal connector for lock wires;
  • An electric lock (Fail-Secure);
  • PCB board to mount the parts;
  • Female header pins to mount the Arduino and RFID reader.

I usually mount the Arduino Nano and other boards with a female pin header so they can be easily replaced when broken or if they are failing. The lock needs 12V power and I wanted a single power supply, so in order to save the Arduino from becoming very hot, I put a 7808 power regulator chip between the 12V power line and the Vin of the Arduino, I use a 5 Volt relay to switch the power to the electric lock because this device will draw a lot of current. I have used a cheap 12v switching power supply, but you can use any power supply that’s 12 V and can deliver at least 2 or 3 Amp current. For the RFID badges I use the read-only ones, they have a fixed number inside and are cheaper than the R/W badges,

Step 2: The Whole Diagram

F9witfejfx0ihf5
Ffy929xjfx0iq0v
Fubnw89jfx0iqjq

This is the diagram of the lock system.I build it on a PCB board using several colors of wire, the diagram is not that complex. I use a 7808 power converter to lower the 12 voltage for the Arduino to 8 volt, I don’t use the capacitors on both sides as the input power is stable and the Arduino does not use too much power. But you could put two 1 uf capacitors on bothe sides of the 7808. I use the +5v output from the Arduino to power the rest of the circuit. I use a mosfet (the old common 2n7002) to drive a relay to switch the 12 v power to the lock. As the lock can draw a lot of current its save to use a relay. I took a little plastic case to hold the electronics and I 3D printed a little case on the outside to hold the antenna and the indicator led.

Fu1vyxmjfx0iksc
The Antenna and the Indicator Led.


Mount the Hardware on and Next to the Door. Mount the Hardware on and Next to the Door. Mount the Hardware on and Next to the Door.

Fkob2n6jfx0im52
Fz9gfz0jfx0inh3

I also designed a holder for the lock to mount it next to the door. I also used a standard door lock on the door with a latch that will move inside when the door closes. I designed a knob to mount on the lock to be able to open the lock from the inside without a RFID badge. (The third file of the knob, the axis, should be printed with 100% infill to make it strong enough) I also created a 4mm spacer for the lock, so you can mount it right in front of the latch. The lock and latch should fit loosely otherwise the unlock won’t work. I used a 12 volt 3 A switching power supply for the 12 volt and I mounted it in the top of the bicycle shed in a dry space. I have used a 3 meter wire to connect the 12 volt to the lock system.

Step 5: The Software.

I wrote a very small Arduino program to read the RFID badges and display them on the serial interface so you can read the value inside the badge. Then you can add the hexadecimal number to the array at the top of the file (don’t forget to increment the number of cards below the array). When a valid card is detected the pin 12 of the Arduino controlling the relay pin will be activated for 5 seconds. You can adjust this time to your own needs. I use the software serial to read the badge so the other serial port is free for other use. There are a lot of pins left on the Arduino, you could add a I2C clock module and enable certain badges only at certain times. There is programming space left so add what you want. The basic version is working code and currently mounted in my own backyard.

Download

More pages on embedded software

Intel 8052ah Basic2

Intel 8052AH Basic computer

A while ago I bought an old box with integrated circuits that had been stored for many years and contained a lot of tubes with very old IS’s. As I like to build old processor boards and try to repair old computers and boards, these chips were very welcome. In one tube there were two original P8052-Basic chips and that brought back good memories of the time mid 80ties of last century when I was working as head R&D embedded programmer and hardware designer for a small company and was using the 8031 processor a lot. I even extended a tiny Basic version at that time, but the real P8031-Basic was incredible and complete, but expensive and hard to get at that time. I put these chips in my computer chips and cpu collection and one I kept aside to make a board to get it working again. I had a latch and a memory chip in my workshop, a PCB was also there, I only needed to order a few 11.0592 crystals as these are not so common anymore. After two evenings of wiring it was finally ready and at my first attempt to run it I got a line number error all the time. I seemed that the external sram was not working and it was a small wiring error. After I had fixed that it worked like a charm, I connected it to my VT100 terminal with the TTL serial input and after pressing the spacebar I got the prompt and I could write a small Basic program. On this page I will show you the schematic I made, some build instructions and some documentation and (source)code. Regards, Hein Pragt.

I also have a Facebook Group on Retro Computing and Electronics, feel free to join!Intel 8052-Basic chip

Why do we need at least 3 chips

To answer the question why we need al least 3 chips I have to explain the 8031 bus a little. To make room for as many I/O pins as possible Intel decided to multiplex the low part of the addresses and the 8 bit databus on one port. This would mean only 8 pins of the chip instead of 16 pins. Of course you would need an external latch for decoding the 8i address bits and the chip needed a pin to signal the output of the address part. Port 1 is actually a 8 bit data out and a 8 bit data in and a 8 bit address out port. The 74573 chip is often used as an 8 bit latch, this will store the 8 bits and save them (kind of like a 8 bit memory chip) to provide the lower 8 bits of the external memory address when reading or writing to external memory. Then we need a external memory chip, we can use anything between 8 and 128 x 8 sram chips, I chose the 32kb x 8 chip (62256) as I had these laying around. I use A15 as a chip select signal, the chip select pin is active low, so the A15 pin selects to lower 32Kb part. When using other chips you have to figure out yourself how to select the chip and put the unused address lines to ground. This is the minimum configuration and all we need to add are a small reset circuit and the crystal oscillator circuit and were done. Below is my schematic I made of my design.

8052 Hp

Building the board

When building this I use a PCB board that is double sided and not too small so I have room to wire the circuit. I put all the chips in sockets, to be able to reuse them again and protect the chips when soldering. I first put the sockets on the board and leave enough space between them for the wires, then I solder the sockets. Then I solder four pin connectors in one corner, two for the power +5v and Gnd, and two for the Tx and Rx lines. Then I solder the crystal near the processor pins, leaving room for the capacitors and I solder them to the correct pins of the processor socket. Then I do the same with the reset capacitor and resistor.

20220521 221504

The next thing is wiring and soldering all the power lines, I use red wire for the +5V and black wire for the Ground. I use solid kernel wire that is available in a lot of colors. I avoid going over the soldering points and like using a PCB layout go around the chips as much as possible. After this I wire the control and chips elect R/W lines using gray / white and orange wire. Then I take yellow wire and connect all the address lines, I try to keep the wires as much together as possible. Now it becomes a little tricky as the AD lines need both a address and a data latch wire. I use blue for the data latch and green for the databus lines. First I solder the blue wire to the socket pin and then carefully on top of that the second green wire. Make sure you do not use to much solder otherwise you can short two pins. I you shorted two pins, take the solder od with a solder pump and try again.

20220521 220244

Now all the lines are attached it is time to check for short circuits, take a Ohm meter and put the pins on two socket pins near each other and do that for all pins. If there is no short circuit we can place the chips. Check the powerlines for short circuit before putting 5 volt on the board. I use a USB power supply and I cut a standard USB cable ands solder female sockets on the power lines, safe an cheap. Now connect the board to a terminal or to a PC using a TTL RS232 to USB cable and type space. When all is right you should see a basic welcome message and prompt. The basic manual download link is at the bottom of this page, have fun!

20220521 220213

Using a AT89c52 or STC89c52 chip

The P8052-Basic chip is very rare and not available anymore, but there us a good alternative. Intel made the Basic code freeware a while ago and put the sourecode and hex files on their FTP site. I cannot find it anymore, but luckily I download everything that is interesting and so I have put the original zip file on my website to download. It contains the sourcecode and the binary hex file of the 8Kb Basic interpreter. When you use a 8052 with Flash eeprom like the 89c52 you can burn the hex code inside the microcontroller and you will have the same chip as the P8052-Basic chip. So you can build this small computer with modern parts.

8052 Basic PCB

I have a PCB for a very complere 8052 Basic computer in my webshop. This is a PCB of a Basic computer based on intel p8052-ah basic for the RCBus. (RC2014), an improved basic version for the 8052 was published in ELEKTOR 2001 (MCS BASIC-52 V1.3) This board can hold many different 8052 variants and supports a lot of different crystal oscillator configurations from 11.075 Mhz (Original) up to 22 and even 33 Mhz. The designer flashed the code into an ds89c450 running at 22.184 mhz, and that is 12x faster than an normal 8052. I build mine with a AT89C52 processor, but ANY 8052 version with at least 8Kb internal Flash will work. https://www.heinpragt.nl/?product=8052ah-basic-pcb-rc2014

My 8031 background

In 1986 I started to work as an embedded programmer and hardware designer for a small company in the Netherlands that build modems and computer equipment. At first it was only my favorite processor the Z80 but in the low cost modems we needed a cheaper microcontroller so one day I got a 8031 hardware emulator from Intel with all the development tools. As Intel provided PL/M and Assembler with their development kit I started to program in PL/M and assembler for the 8031 processor. I really fell in love with this processor and struggled to get all the code into a single eprom and only use the internal ram. In the second modem I got a 8032 so that gave me 128 bytes of extra ram and in the next redesign we implemented an Atmel version so we needed no external eprom anymore, bringing the chipcount down. In one of the last devices I build with the 8032 I had implemented the tiny Basic as well to make the device a programmable communication controller. After that we started to make modems with V42/v42bis and MNP compression and the 8032 was not powerful enough, so we stated to use an Intel 80188 processor. But I loved the MSC-52 processors from Intel, but the next companies I worked for used the Z80 and MC6809 chips, so I have used and programmed a lot of different processor chips.

8052 and 8052-Basic related documents

More pages on embedded software

Scmp

INS8060 or scmp processor

This page is dedicated to my fist microprocessor, the INS8060, also called the SC/MP processor. At the time I was 13 years old and did not have much money, I could afford to buy an electronics magazine called Elektuur every month, and they published a simple computer board based on the SC/MP processor. I was very interested in computer technology at that time and I read all I could about the SC/MP processor. As I did not have the money to buy a board I would draw the internal of the processor on a big piece of paper, with the RAM / ROM / keyboard and display as registers and I would have a lot of small zero and one papers to simulate the flow of the bits and bytes in the (paper) circuit. Looking back this was ridiculous, but this is the way I learned computer design and binary logic. By the time I learned the Z80 system I had good knowledge of processors and binary logic. I also saw a board called the MK14 that was based on the SC/MP as well, I considered buying one at the time, but I decides to go for a real computer. Still the SC/MP is my first processor and nowadays you cannot get the processor anymore (at least not at a reasonable price), but there are emulators in software and hardware that are still available. I have to say that I recemtly bought a SC/MP processor in China for 20 Euros. On this page I will share all documentations, links, schematics and code that I have or have found. Regards, Hein Pragt.

I also have a Facebook Group on Retro Computing and Electronics, feel free to join!

About the INS8060 or SC/MP Processor

National Semiconductor introduced the INS8060 or SC/MP In April 1976 and it was intended for small and cheap industrial controllers. The acronym SC/MP stands for Small Cost-effective Micro Processor and it needed few external components and was simple to program. In 1977 Elektor Magazine devoted a few issues to the SC/MP and the Elektor design came in two versions, a simple basic one and a version with a hexadecimal keyboard, 7-segment displays and a monitor program in ROM, cassette interface and the option to connect a VDU. The INS8060 or SC/MP has a rather simple architecture and can address a total of 65536 bytes memory. Because only 12 of these address lines are connected to pins the addressing space is 4 kb bute the high four bits of the address were multiplexed on the data bus during the NADS-signal. The 64k memory is divided in 16 x 4096-bytes pages. Only a limited number of memory reference instructions can cross a page boundary.

The first INS8060 or SC/MP chip was developed in P-MOS technology and needed a positive power supply of 5 Volts and a negative of 7 Volts. Later National Semiconductor introduced the SC/MP-II that was made in N-MOS technology and only needed a single 5 Volt power. Three of the signals on the SC/MP-II were logically reversed (i.e. BREQ became NBREQ) so the SC/MP-II is not 100% pin-compatible with the first SC/MP-I. The INS8060 or SC/MP was not a powerful microprocessor but at the time it was cheap and simple to use. The SC/MP only an instruction set of 46 basic instructions and was rather easy to program at binary level. Beside the Elektor design there was also a one board computer implementation called the MK14, developed by Science of Cambridge Ltd, which was a company of Sir Clive Sinclair. These are still sold on Ebay sometimes but there are also great emulators in software and hardware. (PIC microcontroller).

INS8060 or SC/MP Pinout

Scmp Pins

The table below describes the various SC/MP signals and pinouts.
(A preceding “N” in the signal mnemonic signifies a negative active signal.)

NRSTReset InputSet high for normal operation. When set low, aborts in-process operations. When returned high, internal control circuit zeroes all programmer-accessible registers; then, first instruction is fetched from memory location &H0001
CONTContinue InputWhen set high, enables normal execution of program stored in external memory. When set low, SC/MP operation is suspended (after completion of current instruction) without loss of internal status
NBREQ *Bus Request In/OutputAssociated with SC/MP Internal allocation logic for system bus. Can be used as bus request output or bus busy input. Requires external load resistor to Vcc
NENIN *Enable InputAssociated with SC/MP Internal location logic for system bus. When set low, SC/MP Is granted access to system busses. When set high, places system busses in high-impedance (TRI-STATE) mode.
NENOUT *Enable OutputAssociated with SC/MP Internal allocation logic for system bus. Set low when NENIN is low and SC/MP Is not using system busses (NBREQ-high. Set high at all other times.)
NADSAddress Strobe OutputActive-low strobe. While low, indicates that valid address and status output are present on system busses.
NRDSRead Strobe OutputActive-low strobe. On trailing edge, data are input to SC/MP from 8-bit bi-directional data bus. High-impedance (TRI-STATE) output when input/output cycle is not in progress.
NWDSWrite Strobe OutputActive-low strobe. While low, indicates that valid output data are present on 8-bit bi-directional data bus. High-impedance (TRI-STATE) output when input/output cycle is not in progress.
NHOLDInput/Output Cycle Extend InputWhen set low prior to trailing edge of NRDS or NWDS strobe, stretches strobe to extend input/output cycle; that is, strobe is held low until NHOLD signal is returned high. (for slow memory)
SENSE ASense/Interrupt Request InputServes as interrupt request input when SC/MP Internal IE (Interrupt Enable) flag is set. When IE flag is reset, serves as user-designated sense condition input. Sense condition testing is effected by copying status register to accumulator.
SENSE BSense InputUser-designated sense-condition input. Sense-condition testing is effected by copying status register to accumulator.
SINSerial Input to E registerUnder software control, data on this line are right-shifted into E register by execution of SIO instruction.
SOUTSerial Output from E registerUnder software control, data are right-shifted onto this line from E register by execution of SIO instruction. Each data bit remains latched until execution of next SIO instruction.
FLAGS 0,1,2Flags OutputsUser-designated general-purpose flag outputs of status register. Under program control, flags can be set and reset by copying accumulator to statusregister.
AD00-AD11Address bits 00 through 11Twelve (TRI-STATE) address output lines. SC/MP outputs 12 least significant address bits on this bus when NADS strobe is low. Address bits are then held valid until trailing edge of read (NRDS) or write (NWDS) strobes. After trailing edge of NRDS or NWDS strobe, bus is set to high (TRI-STATE) mode until next NADS strobe.
DatabusOutput at NADS TimeDuring NADS time the four most significant bits of the addressbus are active at the outputs. Also some other special signals are available at the remaining database pinouts.
DB0Address Bit 12Fourth most significant bit of 16-bit address
DB1Address Bit 13Third most significant bit of 16-bit address
DB2Address Bit 14Second most significant bit of 16-bit address
DB3Address Bit 15Most significant bit of 16-bit address
DB4R-FlagWhen high, data input cycle is starting; when low, data output cycle is starting
DB5I-FlagWhen high, first byte of instruction is being fetched
DB6D-FlagWhen high, indicates delay cycle is started; that is, second byte of DLY instructions being fetched
DB7H-FlagWhen high, indicates that HALT instruction has been executed. (In some system configurations, the H-Flag output is latched and, in conjunction with the CONTinue input, provides a programmed halt).
DatabusStandard Output 
DB0-DB7Databus input/outputDuring the assertion of NWDS or NRDS data is written to or read from external devices. Except for NADS-time, at all other times the databus is floated in (TRI-STATE) modus.
VccPlus 5 voltsPower lead
GND *Ground (0 Volts)Power ground lead SC/MP-II (P-MOS)
VggMinus 7 VoltsPower negative lead SC/MP-I (N-MOS)
XIN/ XOUTClock Crystal inputsA quarts crystal between these leads will determine the clock-frequency of the SC/MP CPU. The SC/MP-II has an internal divide stage so its clock-frequency divided by two.

INS8060 or SC/MP Instruction format

Scmp Opcode

The SC/MP executes either 1 or 2 byte instructions, the first byte is called the OPCODE the optional second byte is the OPERAND. When the most significant bit of the OPCODE is set to 1 it will be a 2 byte instruction, the programcounter (P0) is automatically incremented to fetch the OPERAND byte. Most 2 byte instructions are memory reference instruction that will access memory external to the CPU. With the exception of the ILD and the DLD instruction the SC/MP will initiate a single byte read or write memory access, the ILD and the DLD instruction will do a read-modify-write instruction.

Scmp Registers

The internal register set of the INS8060 or SC/MP is VERY simple, it has only a few internal registers.

Accu

This is a standard accumulator register that contains the result of the most operations and usually holds one of the source operands.

Extension

The extensionregister has a multi purpose usage, it can be used to hold secondary operands to the extension instructions, it can be also be used to temporarily save the accu and it can be used as an 8-bit index register to facilitate relative indirect addressing. Whenever the 2nd byte operand of a memory reference instruction (called the displacement) holds a value of &H80 the content of the extension register is taken as the displacement instead of the 2nd byte operand. Also the extension register is used for the build in serial I/O capability of the SC/MP. The MSB of the extension register is connected to the SIN input and the LSB is connected to the SOUT output line.

Status

The status register contains a number of standard flags like the carry flag and the overflow flag and the interupt enable flag. However, the carry and overflow flags are not directly tested by branch-instructions. They must be copied to the accu first (CAS-instruction) and their state must be ascertained with bitwise logical instructions. Branch testing is only done on the state of the accu-register. Flag F0, F1 & F2 are connected to the flag pins for output. Sense SA & SB that are connected to the sense input pins.

The Pointer Registers P0-P3

The Pointer registers P1-P3 are used as datapointer, stackpointer and subroutine / interupt service pointers. Pointer register P0 is used as the Programcounter, the main difference with a normal programcounter is the fact that the SC/MP PC is incremented prior to fetching a new instruction, so the program always continues the next instruction at PC+1. Another feature of all pointer registers is that whenever a pointer-register is incremented by a auto indexed addressing mode instruction or an effective address is calculated that crosses a page boundary, the effective address folds back to the beginning of the page. Only when loading an absolute address into the pointer register the page boundary can be crossed! National Semiconductor recommends the following pointer register roles as a rule of thumb: P0 = Program Counter, P1 = Data of I/O Pointer, P2 = Stackpointer, P3 = Subroutine/interrupt Pointer. The XPPC instruction can exchange the content of the PC with any of the other pointer-registers so any Px can service a subroutine but only P3 can service a service routine for an interupt, because the XPPC3 instruction is generated automatically whenever an interupt is received.

INS8060 or SC/MP addressing Modi

All memory reference instructions make use of addressing modes to calculate the effective address of the memory reference. This could be to access the content of a memory location but also to determine the target adress of a branch or jump instruction. The SC/MP features the following addressingmodes:

PC Relative/Pointer-register Indexed Addressing

The 2nd byte of an instruction is taken as a displacement in 2s complement fashion and added to the current content of the designated pointer register to calculate the effective address. When the PC (P0) is used as the designated pointer register we call this PC relative mode. A 2s complement 8 bit value can contain any value from 127 dec to +127 dec. In the case of a PC relative Jump (branch) one should take into consideration the the programcounter will be incremented by 1, prior to the next opcode fetch.

Indirect Addressing

In SC/MP documentation indirect addressing is regarded as a special case of PC-relative and indexed addressing, in the event that the second byte of an memory reference instruction contains &H80 as a displacement value it is not taken as a negative displacement of 128 dec, but the content of the extension register is used as the 2s complement displacement to calculate the effective address.

Immediate Addressing

The second value of the instruction in a memory reference instruction is immediately used as source data for the instruction, no further address calculation is required.

Auto Indexed Addressing

This addressing mode is a bit like Indexed addressing but this time the pointer register itself is modified by the displacement in a pre decrement and post increment way. In the case of a negative displacement the pointer register is replaced with the effective address and then the memory access is executed. In the case of a positive displacement the memory access is executed with the current value of the designated pointer register, prior to replacing Px with the new modified calculated EA value. In this way we can used P1, P2 or P3 as a LIFO stackpointer.

Mnemonic@-modesOpcode1Opcode2TypeFlagsDescription
CO
ADD@DISP(X)1111.0maapppp.ppppMRXXBinary ADD mem. w. Carry
ADEe0111.0000 EXXBinary ADD extension w. Carry
ADIi1111.0100dddd.ddddIXXBinary ADD immediate w. Carry
AND@DISP(X)1101.0maapppp.ppppMR  Logical AND accu w. mem.
ANEe0101.0000 E  Logical AND accu w. extension
ANIi1101.0100dddd.ddddI  Logical AND accu immediate
CAD@DISP(X)1111.1maapppp.ppppMRXXADD memory complement w. Carry
CAEe0111.1000 EXXADD extension complement w. Carry
CAIi1111.1100dddd.ddddIXXADD immediate complement w. carry
CASst0000.0111 ST!!Move Accu to Status
CCLcy0000.0010 MF Clear Carry-flag
CSAst0000.0110 ST  Move Status to Accu
DAD@DISP(X)1110.1maapppp.ppppMRX Decimal ADD memory w. Carry
DAEe0110.1000 EX Decimal ADD extension w. Carry
DAIi1110.1100dddd.ddddIX Decimal ADD immediate w. Carry
DINT 0000.0100 M  Disable Interrupt
DLDDISP(X)1011.10aapppp.ppppMR  Decrement & Load memory
DLYi1000.1111dddd.ddddM  Delay
HALT 0000.0000 M  Halt instruction
IEN 0000.0101 M  Enable Interrupt
ILDDISP(X)1010.10aapppp.ppppMR  Increment & Load memory
JMPDISP(X)1001.00aapppp.ppppJ  Jump Absolute
JNZDISP(X)1001.11aapppp.ppppJ  Jump Non Zero
JPDISP(X)1001.01aapppp.ppppJ  Jump Positive
JZDISP(X)1001.10aapppp.ppppJ  Jump Zero
LD@DISP(X)1100.0maapppp.ppppMR  Load accu from memory
LDEe0100.0000 E  Load accu from extension
LDIi1100.0000dddd.ddddI  Load accu immediate
NOP 0000.1000 M  No operation
OR@DISP(X)1101.1maapppp.ppppMR  Logical OR accu w. memory
OREe0101.1000 E  Logical OR accu w. extension
ORIi1101.1100dddd.ddddI  Logical OR accu immediate
RR 0001.1110 SR  Rotate right accu
RRL 0001.1111 SRX Logical Rotate right w. Carry
SCL 0000.0011 MT Set Carry Flag
SIO 0001.1001 E  Serial I/O extension
SR 0001.1100 SR  Shift right
SRL 0001.1101 SRX Logical Shift right
ST@DISP(X)1100.1maapppp.ppppMR  Store accu to memory
XAE 0000.0001 E  Exchange accu w. extension
XOR@DISP(X)1110.0maapppp.ppppMR  Logical XOR accu w. memory
XREe0110.0000 E  Logical XOR accu w. extension
XRIi1110.0100dddd.ddddI  Logical XOR accu immediate
XPAH x 0011.01aa X  Exchange pointer high with accu
XPAL x 0011.00aa X  Exchange pointer low with accu
XPPC x 0011.11aa X  Exchange pointer with PC

The MK14

Mk14

An well known INS8060 or SC/MP board was the MK14 single board conputer, it was not an Acorn product but a first step in the creation of Acorn Computers. Chris Curry worked
with Clive Sinclair on the development of the MK14 as a Science of Cambridge / Sinclair product. The MK14 was made by Science of Cambridge (later becoming Sinclair Computers and
finally Sinclair Research), it was based on the National Semiconductors SC/MP (INS8060) processor and was sold as as a kit.

National Semiconductor produced quite a lot of other documentation for the SC/MP processor which will be of interest to MK14 owners:

Schematics

There were a number of versions of the MK14, the early version schematic is most likely the first version, the later version schematic refers to a version 5 that includes the updated address decoding required for the VDU.

Firmware

There are two versions of the MK14 monitor program, the first was on the first release of the MK14 and is just National Semiconductors SCMPKB. Then there was an upgrade that included the tape interface routines.

The MK14 PIC implementation

I found a very nice MK14 clone on this page an I intend to build this one. The PIC14 program will run in a PIC16F876, Ports A, B and C providing an interface to the display and keyboard. This is a very neat design and a nice piece of programming, it is a hardware clone of the MK14 using a PIC microcontroller.

Pic14

You can find this project on: Karen’s Microprocessor Projects

INS8060 or SC/MP related documents

INS8060 or SC/MP links, tips and webpages

More pages on embedded software

Z80 Mega05

Z80 on Arduimo Mega

Zilog Z80 Arduino Mega I found an interesting project on the Internet of a Z80 processor on a breadboard that was connected with wires to an Arduino Mega board. It had some code with it, it was far from complete but it triggered me. I adopted the idea and improved it, rewrote the Arduino code and improved the hardware design. The Z80 processor in this project is running at 200 Khz, clocked from the Arduino and the Arduino emulates 8 kb of ROM and 6 kb of RAM and serial input and output. With this simple and cheap configuration you have a complete working Z80 based computer. With some adjustments I even got a complete Basic interpreter running on this hardware with the serial I/O of the Arduino as interface. But it is also nice to write your own assembler code and see it not only running in an emulator, but also on a real Z80 processor. Just put your generated HEX code in the memory.h file and recompile the Arduino sketch and upload it to the Mega board. On reset the Z80 will execute the code in the ROM section of the MEGA. Have fun! Regards, Hein Pragt.

I also have a Facebook Group on Retro Computing and Electronics, feel free to join!

Building a Z80 Arduino Mega computer

What do you need for this project? Well at first an Arduino Mega board, then a development shield, a 40 pin socket for the Z80 processor, some breadboard wires and two rows of header pins. At least, that’s how I build it and the parts are all re-usable. You can also put the Z80 on a breadboard beside the Arduino Mega and use longer wires. Longer wires will effectively have some influence on the reliability and the speed. I soldered the socker on the development shield and also soldered the two rows of header pins alongside the socket. For a more permanent solution you could also solder all the connections from the Z80 socket to the header pins of the Arduino. There are many possibilities, its up to you how to make this project. The wiring diagram is below.

I noticed that the below configuration will only work with a NMOS version of the Z80 processor, I used a AB1 version!

Z80 Mega04

The pins on the Arduino are chosen to pair the data and address lines to fixed 8 bit ports of the Arduino Mega so its easy to process them. The data lines are connected to pins 42-49 and this is the port L register of the Arduino Mega. The lower 8 address lines are connected to pin 22-29 and this is the port A register of the Arduino Mega. The upper address lines are connected to pins 32-37 and this is the port C register of the Arduino Mega. The INT, RESET and WAIT pins are outputs of the Arduino Mega and inputs on the Z80. The M1, IQREQ and MREQ are input pins on the Arduino and output pins on the Z80. These are control signals and the pins on the Arduino Mega are not dedicated. The CLK line is, this is connected from pin 10 of the Arduino Mega to the Z80 and pin 10 is the output pin of one of the internal timers of the Arduino Mega, to generate the clock signal for the Z80. You can program the speed by programming the divider in the Arduino. The most important lines are the RD and WR lines of the Z80, we connect them to the Arduino pins 18 and 19 so they can be used to generate interrupts on the Arduino Mega for the read cycle and the write cycle of the Z80 processor. On the Z80 some unused pins must be connected to +5V and the ground pin must be connected. That’s all.

Z80 Mem Cycles

The RD and the WR are used to trigger interrupts on the Arduino Mega, so all the read and write actions will be processed in the background. The triggers od the interrupts are on the falling edge of the signals, that is de start of the RD and WR signal. On read we will first read the address from the address lines and if its below 2000h we will read the flash memory array (8K) of our Arduino (our Rom) and it its above 2000h we will read the memory array (6K) of the Arduino (out Ram) and put this data on the data bus to be read by the Z80. On WR we also read the address pins and also read the data pins, then we will store it in the memory array inside our Arduino memory. You cannot write to Rom so we do not need to handle that. It seems quit simple.

But we also need to process IO requests, so at the start of the interrupt routines we first check the MREQ pin. If this is active it is a memory request and we do the above. Then we test the IOREQ pin, if this is active it is an IO request. We now read the lower part of the address register (the Z80 only uses the low bytes) to determine the port. If it is an IO read, we read the data and if its port 1 we will send the data to the serial port of the Arduino. If it’s a IO read we check the lower address line for the port number and then its important to activate the WAIT l ine. Because we are going to do some serial IO things on the Arduino Mega, this will take more time on the Arduino Mega than the length of the read cycle of the Z80. The Z80 has a feature for slow IO devices that’s called the WAIT pin. When this pin is active the Z80 waits the IO operation until the device has the data ready and deactivates the WAIT pin. We now have enough time to poll the Serial buffer of the Arduino Mega and return the data (character received or the buffer status) on the data pins for the Z80 to read.

Z80 Mega06

In basic we now have a complete emulation of Rom, Ram and IO device to the Z80 processor. At the start of the Arduino sketch, I first declare the pins of the Z80 to map them to Arduino registers. I also have some macros to read the state of pins or set the state of pins. This makes it easier to use in the code. Then I set the correct lines to input and output, its important to use the internal pullups on the address lines. Then initialize the serial port of the Arduino to a high speed and activate the RESET pin of the Z80 processor. This will start running and executing the instructions that I reads from our Arduino Flash memory array and read / write data to the ram memory array inside our Arduino Mega. We can start the serial terminal of the Arduino to see the serial output and send characters to the Arduino Mega and thereby to the Z80. You can also use any other terminal program. I included a version of the (little modified code) of the basic interpreter I got form the website of Grant Searle, a great electronics designer.

You can use my Z80 IDE to develop programs for this device, just set the rom area to 0000-2000 and the ram to max 3800 and then you can write, test and debug your Z80 assembly code. Do not forget toe initialize the SP register somehere in the Ram area. When its working, just export it to a HEX C style array (files menu) and cut and paste that code to the memory.h file of the Arduino sketch. Recompile the sketch and send it to the Arduino Mega, on reset the Z80 program will run on a REAL Z80 processor. I think that is cool.

You can expand the Arduino sketch, currently there is no code in the loop(), you can add your own code here, f.i. to read sensors or and SD card, but you can also use the ports of the Arduino as digital or analog input / outputs (just add an IO port section) to interface the Z80 processor. It’s up to your own creativity. Be aware that in this setup I tested that the maximum reliable clock speed of the Z80 is about 200 kilohertz, so that’s rather slow. You cannot speed this up too much, the Arduino will not respond in time on the Z80 requests and the wires will also cause a loss in signal quality. But is is a nice experiment if you want to play around with the old Z80 processor, I had a lot of fun building and developing this. Have fun!

The code and schematics

Z80 related documents and webpages

More pages on embedded software