5804

Part 2 of the O-M-S-U MCS-52 BASIC project is here! After more than 14,000 views on the first installment, we now continue with the next key module of the system: the display board. Retro architecture, modern modularity — and fully open hardware. Let’s dive deeper into the O-M-S-U universe!

The first part of the O-M-S-U MCS-52 BASIC project received an incredible amount of attention — more than 14,000 views. I would like to express my sincere thanks to everyone who took the time to read, comment, and support this retro-inspired modular computer system.

For those who haven’t seen the introduction yet, you can find the first part of the project here: O-M-S-U MCS-BASIC-52 V1.1 to V1.3 and more…

In this second installment, I would like to take you one step further into the system architecture and continue the journey through the O-M-S-U universe. After presenting the CPU and the overall concept in Part 1, this article now focuses on one of the most important functional modules of the system: the Display Board.

It not only provides visual output, but also plays a central role in debugging, user interaction, and system monitoring — all within the constraints (and charm) of classic MCS-BASIC-52 hardware.

As before, the project remains entirely open-hardware and open-documentation.
My goal is to share as much knowledge as possible and to revive a piece of 1980s engineering in a modern, maker-friendly form — transparent, reproducible, and enjoyable to explore.

I hope you enjoy this second part as much as the first, and I look forward to your comments, ideas, and feedback. Let’s continue building the O-M-S-U system together!

Introduction

The O-M-S-U Display Card forms the central interface between the user and the MCS-52 BASIC system. It enables the display of information via an alphanumeric LCD and allows user input through four pushbuttons. In addition, the board features two serial interface ports (RS-232), an I²C expansion interface, eight status LEDs, and a buzzer for audible feedback.

Like all O-M-S-U modules, the Display Card is fully pluggable, easy to service, and built exclusively with through-hole components (no SMD parts).
This makes it a universal User-Interface (UI) Module for the O-M-S-U CPU board — robust, accessible, and true to the project’s retro spirit.
image-20251118171541.png
image-20251118150316.png
image-20251118150338.png

 
Functional Description 

The LCD display (HD44780-compatible, 4×20 characters) is driven by the 82C55A I/O controller on the CPU module.
 This device is fully decoded in the address range 0C020H–0C023H and provides three 8-bit ports, which supply all required signals for the display, status LEDs and user inputs.

Display Interface
 
  • Data lines DB0–DB7 (Port A0–A7 of the 82C55) handle text output and command.
  • Control lines RS, E and WR (Port C0–C2) are used to operate the LCD controller.
  • Backlight control is connected to Port C3 of the 82C55.

The LCD backlight can be polarity-matched using jumpers JMP1/JMP2, since manufacturers occasionally reverse the backlight pins. Display contrast is adjusted via trimmer R1.

User Interface: Keys and LEDs

The board provides four pushbuttons (S1–S4), wired to the upper four bits of Port C (C4–C7). These can be freely programmed as navigation or function keys.

For visual feedback, eight LEDs are installed and driven through a ULN2803 transistor array connected to Port B0–B7.
Each LED has its own dedicated resistor, making them ideal for power, status, and function indications.

Serial Interfaces

Serial communication is implemented via a MAX232 transceiver, converting the TTL levels of the AT89S52 to standard RS-232 levels.
Connector X1 (9-pin Sub-D) allows direct connection to a PC or terminal. Optionally, a 5V supply can be routed through this interface using jumpers SJ1, enabling small external modules to be powered directly from the board.

A second Sub-D connector, X2, exposes the line-printer output (TXT) only, making it suitable for simple serial display devices or print output.
Here as well, a solder jumper  SJ2  can enable a 5-V auxiliary supply.

I²C Interface

To support modern peripherals, the module includes an I²C expansion interface.
This allows the direct connection of real-time clocks, EEPROMs, sensors or other I²C-based building blocks.
Power for these modules can be supplied via jumper JP2, avoiding the need for an additional power supply.

An optional jumper (S3) routes the I²C interrupt signal to the INT1 pin of the AT89S52, enabling interrupt-driven I²C applications.

Buzzer Output

A small but useful feature is the buzzer, connected directly to the PWM output of the AT89S52. This allows MCS-52 BASIC to generate tones, alerts and acoustic feedback — for example on keypress, error conditions or as a timing signal in interactive applications.

Jumpers and Settings

SJ1, SJ2
Route the 5-V supply voltage to the Sub-D connectors of the serial interfaces (PIN 1), allowing small external modules to be powered if required.

S3
Routes the I²C interrupt to the INT1 input of the AT89S52 to signal external I²C events.
optional; not required for normal I²C bus operation.

JP2
Switches the 5-V supply voltage to the external I²C connector (W1), enabling add-on modules to be powered directly.
JP2 must be set if the I²C bus is not powered externally. If the I²C bus is powered by an external 5V source, JP2 must be removed to avoid back-feeding or damage. 

JMP1 / JMP2
Set the correct polarity of the LCD backlight (depends on the display manufacturer).
image-20251118173323.png


Display Backlight Polarity

The solder-jumper configuration shown here for JMP1 and JMP2 is intended for the 20×4 text display from AZ-Delivery (https://www.az-delivery.de).
Of course, displays from other manufacturers of the same LCD family can also be used.
In my tests and research, this particular display offered the best price/performance ratio.
image-20251118174337.png
Since the exact polarity configuration of the backlight is not 100% obvious from the schematic alone (at least not without measuring equipment), the accompanying photo shows the correct jumper positions directly on the O-M-S-U display board.

elektor


elektor
Important:
JMP1 and JMP2 configure the backlight polarity of the LCD module. The settings shown here are valid for the AZ-Delivery 20×4 display. If you use another display type, consult the datasheet and verify the supply pin orientation before powering the board. Although reversed polarity is uncommon, numerous variants exist on the market — so double-checking is highly recommended. 


The I²C Bus

As described in the functional overview, the display module also provides a connector for the I²C bus. For the I²C interface to operate correctly under MCS-52 BASIC, it is essential that the external FLASH contains the BASIC extension created by Detlef Wulf and Hans-Jürgen Böhling. This extension has been modified by the author so that Port 3 pins 4 and 5 are used as SCL and SDA.

With this extension installed, MCS-52 BASIC provides the commands:

  • I2CSTART

  • I2CPUT

  • I2CGET

  • I2CSTOP

Additionally, the status of the I²C bus can be queried using DBY(18H).
A small example using the well-known PCF8574 I/O expander is provided later in this document.
The pin assignment of connector W1 can be found in the illustrations further below.
image-20251118175559.png
image-20251118175609.png
I²C BUS - Pin assignment of connector W1
elektor

elektor
Important:
JP2 must be set if the I²C bus is not powered externally.
If the I²C bus is powered from an external 5V source, JP2 must be removed to avoid backfeeding and potential damage.

Example program I²C

10 REM ####################################################
20 REM #              I2C Communication Test
30 REM #          (C) H.-J. Boehling 08.29.99
35 REM #         modified by J.Lange 27.07.2023 
40 REM ####################################################
50 ADDR=40H
60 FOR I=0 TO 255
70 PRINT I,
80 REM ============== I2C Write ===============
90 I2CSTART
100 IF DBY(18H)=0 I2CPUT (ADDR) ELSE 260
110 IF DBY(18H)=0 I2CPUT (I) ELSE 260
120 I2CSTOP
130 REM ============= I2C Read ================
140 I2CSTART
150 IF DBY(18H)=0 I2CPUT (ADDR.OR.1) ELSE 260
160 IF DBY(18H)=0 I2CGET B ELSE 260
170 PRINT B
180 I2CSTOP
185 REM
190 NEXT I
195 REM GOTO 10 for measurements (remove REM and comment)
200 REM ============== Wait for key ============
210 K=GET : IF K>0 THEN 210
220 PRINT "Continue?"
230 K=GET : IF K=0 THEN 230
240 GOTO 60
250 REM ============== I2C Error ===============
260 STATUS=DBY(18H)
270 FOR J=1 TO 3 :  I2CSTOP  :  NEXT
280 IF STATUS.AND.2=2 THEN  PRINT "Time out error!"
290 IF STATUS.AND.4=4 THEN  PRINT "Busy error!"
300 IF STATUS.AND.8=8 THEN  PRINT "No acknowledge error!"
310 GOTO 90

image-20251118181103.png


The Serial Interfaces

The AT89S52 microcontroller includes an integrated serial interface that can be operated in full-duplex mode. This RS-232 interface outputs TTL-level signals, which are converted to proper RS-232 levels by a MAX232 located on the display board.

The two 9-pin Sub-D connectors on the O-M-S-U display board are wired in such a way that a null-modem cable is not required.
elektor

They can be connected directly to a terminal device (typically a PC) using a 1:1 cable.
Since most modern PCs no longer include a native RS-232 port and require USB adapters, a USB-to-RS232 converter can be connected directly to either interface (X1 or X2) without additional adapters. The pin assignments for both 9-pin Sub-D connectors can be clearly seen in the corresponding diagrams. The +5V supply is, of course, only available if the associated solder jumpers have been set.
elektor

The second 9-pin Sub-D connector (X2) is, as shown in the diagram, not fully populated, and the RXD line of the RS-232 interface is not present at all.
The TXD line of X2 is routed through the MAX232 to the LINE-PRINTER OUT output of the microcontroller and is implemented purely in software on the AT89S52.
elektor


This interface must first be initialized using the BAUD command in MCS-52 BASIC before it can be used. As the name suggests, this interface originates from a time when BASIC program listings were sent to a simple line printer.

Even today, however, this port can be quite useful — for example for debugging or to drive serial displays. There are virtually no limits to what you can do with it. In a later article, these possibilities will be discussed in more detail.



Technical Data – O-M-S-U Display Board

Property:
Value / Description:

Display:
LCD 4×20 characters, HD44780-compatible
Input Elements:
4 pushbuttons (S1–S4)
Status Indicators:
8 LEDs with ULN2803 driver
Acoustic Output:
Buzzer, directly connected to the PWM output of the AT89S52
Communication Interfaces:
RS-232 (via MAX232), I²C bus
Supply Voltage:
+5 V DC
Internal Power Distribution:
Decoupling via electrolytic capacitors (22 µF) and 100 nF capacitors
Data Bus Width:
8-bit
Address Range (82C55A):
0C020H – 0C023H
Address Increment:
1 byte
LCD Backlight Polarity:
Selectable via jumpers JMP1-0R / JMP2-0R
Expandable Interfaces:
I²C with interrupt option and power supply
RS-232 Auxiliary Power:
Switchable via SJ1/SJ2
Component Type:
THT only, no SMD components
Special Features:
Direct connection to CPU board, service-friendly, fully pluggable
Developer:
J. Lange (O-M-S-U / Old Man Stands Up)
Revision:
1.2 – 2025

Pin assignment SV7
elektor

Pin assignment SV8
elektor

Example programs Display and buttons

REM #############################################################
REM #             DISPLAY BOARD EXAMPLE PROGRAM               
REM #                 O-M-S-U MCS-52 BASIC   
REM #                     J.Lange 2024
REM # Contents:                                                 
REM # - String storage, number→string (4000…4490)     
REM # - Key scan 82C55 (5000…5120)                   
REM # - Display routines:
REM # - INIT, position, line, cursor, CLR (9500…9993)
REM # - Backlight enable, disable (9500…9993)
REM # - Example A: Start screen + FREE/MTOP output (10000…)   
REM # - Example B: LED demo & key control (10000…10740)     
REM # - Example C: 4-point menu with keys (20000…)         
REM #############################################################
REM =============================================================
REM #  STRING STORAGE DIMENSIONING
REM =============================================================
REM # 5 strings with 20 characters each (lines 1..4 + helper $(0))
REM # $(0) is used as a helper string (e.g. for number→string).
REM =============================================================

1 STRING 106, 20
2 GOTO 10000
REM =============================================================
REM =              NUMBER → STRING (DECIMAL) (4000…4490)           
REM =============================================================
REM Converts TP1 into ASCII characters in $(0).
REM ST = integer length, SP = length incl. "." + 3 decimals
REM =============================================================

4000 SP=0 : $(0)=""
4010 IF INT(TP1) > 999999 THEN ST=7 : GOTO 4100
4020 IF INT(TP1) >  99999 THEN ST=6 : GOTO 4120
4030 IF INT(TP1) >   9999 THEN ST=5 : GOTO 4140
4040 IF INT(TP1) >    999 THEN ST=4 : GOTO 4160
4050 IF INT(TP1) >     99 THEN ST=3 : GOTO 4180
4060 IF INT(TP1) >      9 THEN ST=2 : GOTO 4210
4070 IF INT(TP1) >=     1 THEN ST=1 : GOTO 4230
4080 IF TP1>0 THEN ST=0 : GOTO 4250
4100 TP2=INT(TP1/1000000) : GOSUB 4300
4110 TP1=TP1-TP2*1000000
4120 TP2=INT(TP1/100000) : GOSUB 4300
4130 TP1=TP1-TP2*100000
4140 TP2=INT(TP1/10000) : GOSUB 4300
4150 TP1=TP1-TP2*10000
4160 TP2=INT(TP1/1000) : GOSUB 4300
4170 TP1=TP1-TP2*1000
4180 TP2=INT(TP1/100) : GOSUB 4300
4190 TP1=TP1-TP2*100
4210 TP2=INT(TP1/10) : GOSUB 4300
4220 TP1=TP1-TP2*10
4230 TP2=INT(TP1) : GOSUB 4300
4240 TP1=TP1-TP2
4250 SP=SP+1 : ASC($(0),SP)=ASC(.)
4260 TP2=INT(TP1*10) : GOSUB 4300
4270 TP1=TP1*10-TP2 : TP2=INT(TP1*10) : GOSUB 4300
4280 TP1=TP1*10-TP2 : TP2=INT(TP1*10) : GOSUB 4300
4290 RETURN
4300 SP=SP+1
4310 ON TP2 GOSUB 4400,4410,4420,4430,4440,4450,4460,4470,4480,4490
4320 RETURN
4400 ASC($(0),SP)=ASC(0) : RETURN
4410 ASC($(0),SP)=ASC(1) : RETURN
4420 ASC($(0),SP)=ASC(2) : RETURN
4430 ASC($(0),SP)=ASC(3) : RETURN
4440 ASC($(0),SP)=ASC(4) : RETURN
4450 ASC($(0),SP)=ASC(5) : RETURN
4460 ASC($(0),SP)=ASC(6) : RETURN
4470 ASC($(0),SP)=ASC(7) : RETURN
4480 ASC($(0),SP)=ASC(8) : RETURN
4490 ASC($(0),SP)=ASC(9) : RETURN

REM =============================================================
REM =               KEY SCAN ON 82C55 (5000…5120) 
REM =============================================================
REM Keys are on PC4..PC7. Return value TP1:
REM 0=no key, 1..4 = keys 1..4. Includes debouncing.
REM =============================================================

5000 TP1 = XBY(0C022H)     : REM Read Port C
5012 XBY(0C022H) = TP1.OR.0F0    : REM Set PC4..PC7 high
5020 TP1 = XBY(0C022H)     : REM Read Port C again

5030 IF (TP1.AND.128) THEN TP1=4 : GOTO 5100 : REM Bit7 key 4
5040 IF (TP1.AND. 64) THEN TP1=3 : GOTO 5100 : REM Bit6 key 3
5050 IF (TP1.AND. 32) THEN TP1=2 : GOTO 5100 : REM Bit5 key 2
5060 IF (TP1.AND. 16) THEN TP1=1 : GOTO 5100 : REM Bit4 key 1
5070 TP1 = 0         : REM No key
5080 RETURN
REM Debounce + wait for key release
5100 DO
5105   FOR TEMP = 1 TO 50 : NEXT TEMP
5110   TEMP = XBY(0C022H).AND.0F0H
5115 WHILE TEMP > 0
5120 RETURN
REM =============================================================
REM =              DISPLAY ROUTINES (9500…9993)               
REM =============================================================
REM Control lines (via Port C):
REM  - PC0 = RS, PC1 = R/W, PC2 = E
REM Data on Port A (0C020H).
REM =============================================================
REM ---------- INIT ----------
9500 REM SUB_Display INIT
9501 XBY(0C023H)=136:REM Control word: Mode 0 (PA/PB out, PC partial)
9502 XBY(0C020H)=0       : REM Port A = 0 (data bus)
9503 XBY(0C021H)=0       : REM Port B = 0 (e.g. LEDs off)
9504 XBY(0C022H)=0       : REM Port C = 0
9505 XBY(0C023H)=4       : REM PC2=E=0
9506 XBY(0C023H)=2       : REM PC1=R/W=0 (write)
9507 XBY(0C023H)=0       : REM PC0=RS=0 (command)
9508 XBY(0C020H)=56:GOSUB 9990:REM Function Set: 8-bit, 4 lines
9509 XBY(0C020H)=14 : GOSUB 9990  : REM Display ON, cursor OFF
9510 XBY(0C020H)=6  : GOSUB 9990   : REM Entry mode set
9511 XBY(0C020H)=1  : GOSUB 9990   : REM Clear display
9512 XBY(0C020H)=128: GOSUB 9990 : REM Set DDRAM address
9513 XBY(0C020H)=1  : GOSUB 9990   : REM Clear display
9514 XBY(0C020H)=2  : GOSUB 9990   : REM Home
9515 XBY(0C023H)=7   : REM Backlight ON (HW dependent)
9516 ZEI=1                    : REM Start line
9517 RETURN

REM ---------- CURSOR POS (ZEI/ZPO) ----------

REM 4×20: ZSW1=0x00, ZSW2=0x40, ZSW3=0x14, ZSW4=0x54
9700 REM SUB_DISP.POS-LINE-COLUMN
9710 IF ZEI<1.OR.ZEI>4 THEN RETURN
9715 IF ZPO<1.OR.ZPO>20 THEN RETURN
9720 IF ZEI=1 THEN ZSW=0
9725 IF ZEI=2 THEN ZSW=64
9730 IF ZEI=3 THEN ZSW=20
9735 IF ZEI=4 THEN ZSW=84
9740 DSA=ZSW+ZPO-1 : DSA=DSA.OR.128 : REM Set DDRAM address command
9745 XBY(0C023H)=2                    : REM R/W=0
9750 XBY(0C023H)=0                    : REM RS=0 (command)
9755 XBY(0C020H)=DSA : GOSUB 9990     : REM Set address
9760 RETURN

REM ---------- PRINT LINE (20 chars from $(ZEI)) ----------

9800 REM SUB_DISP.PRINT-LINE
9801 XBY(0C023H)=2                    : REM R/W=0
9802 XBY(0C023H)=0                    : REM RS=0 (command)
9803 IF ZEI<1.OR.ZEI>4 THEN RETURN
9804 ON ZEI GOTO 1,9810,9820,9830,9840
9810 XBY(0C020H)=128 : GOSUB 9990     : REM Line 1 start
9812 GOTO 9850
9820 XBY(0C020H)=192 : GOSUB 9990     : REM Line 2 start
9822 GOTO 9850
9830 XBY(0C020H)=148 : GOSUB 9990     : REM Line 3 start
9832 GOTO 9850
9840 XBY(0C020H)=212 : GOSUB 9990     : REM Line 4 start
9842 GOTO 9850
9850 REM PRINT TEXT (20 characters)
9851 XBY(0C023H)=1                    : REM RS=1 (data)
9853 FOR TEX=1 TO 20
9854   XBY(0C020H)=ASC($(ZEI),TEX) : GOSUB 9990
9855 NEXT TEX
9856 RETURN

REM ---------- CURSOR OFF ----------

9930 REM SUB_DISP_CURS_OFF
9931 XBY(0C023H)=2                    : REM R/W=0
9932 XBY(0C023H)=0                    : REM RS=0
9933 XBY(0C020H)=12 : GOSUB 9990 : REM Display ON, cursor OFF
9934 RETURN

REM ---------- CURSOR ON ----------
9940 REM SUB_DISP_CURS_ON
9941 XBY(0C023H)=2                    : REM R/W=0
9942 XBY(0C023H)=0                    : REM RS=0
9943 XBY(0C020H)=14 : GOSUB 9990      : REM Display ON, cursor ON
9944 RETURN

REM ---------- HOME ----------
9950 REM SUB_DISP_HOME
9952 XBY(0C023H)=2                    : REM R/W=0
9953 XBY(0C023H)=0                    : REM RS=0
9954 XBY(0C020H)=2  : GOSUB 9990      : REM Home
9955 RETURN

REM ---------- CLEAR ----------
9960 REM SUB_DISP_CLR
9961 XBY(0C023H)=2                    : REM R/W=0
9962 XBY(0C023H)=0                    : REM RS=0
9963 XBY(0C020H)=1  : GOSUB 9990      : REM Clear
9964 RETURN

REM ---- BACKLIGHT OFF/ON (HW dependent on PC bits) --------

9980 REM SUB_Disp_Bel_off
9981 XBY(0C023H)=6
9982 RETURN
9985 REM SUB_Disp_Bel_on
9986 XBY(0C023H)=7
9987 RETURN

REM ---------- ENABLE PULSE ----------
9990 REM SUB-DISPLAY-E
9991 XBY(0C023H)=5 : REM E=1, RS/RW according to previous state
9992 XBY(0C023H)=4                    : REM E=0
9993 RETURN

REM ============================================================
REM =        EXAMPLE A: START SCREEN + FREE/MTOP (10000…)     
REM ============================================================
10000 GOSUB 9500                   : REM Init
10010 GOSUB 9930                   : REM Cursor off
10020 GOSUB 9960                   : REM Clear
10030 GOSUB 9950                   : REM Home
10040 GOSUB 9985                   : REM Backlight on
REM Frame & headline
10050 $(1)="####################"
10060 $(2)="# MCS-52BASIC V1.3 #"
10070 $(3)="#  FREE:      KB   #"
10080 $(4)="#  MTOP:      KB   #"
REM Output lines
10100 ZEI=1 : GOSUB 9800
10110 ZEI=2 : GOSUB 9800
10120 ZEI=3 : GOSUB 9800
10130 ZEI=4 : GOSUB 9800

REM Convert FREE to KB and output at (3,10)
10140 TP1 = FREE/1000     : GOSUB 4000
10150 ZEI=3 : ZPO=10      : GOSUB 9700
10160 XBY(0C023H)=1       : REM RS=1
10170 FOR I=1 TO ST
10180   XBY(0C020H)=ASC($(0),I) : GOSUB 9990
10190 NEXT I

REM Convert MTOP to KB and output at (4,10)

10200 TP1 = MTOP/1000     : GOSUB 4000
10210 ZEI=4 : ZPO=10      : GOSUB 9700
10220 XBY(0C023H)=1       : REM RS=1
10230 FOR I=1 TO ST
10240   XBY(0C020H)=ASC($(0),I) : GOSUB 9990
10250 NEXT I
10260 END

REM =============================================================
REM =       END EXAMPLE A: START SCREEN + FREE/MTOP (10000…)         
REM =============================================================
REM Optional: jump directly into Knight Rider demo
REM Then the KNIGHT RIDER subroutine (10700–10740) must be
REM copied into memory (RAM).!!!
10260 GOSUB 10700
10265 GOTO 10260
10270 END

REM =============================================================
REM =       EXAMPLE B     LED & KEY CONTROL (10200…10740)
REM =============================================================
REM Note: Activate either the running light OR Knight Rider.
REM Copy the program below into memory (RAM) above Example A.
REM =============================================================

10050 $(1)="####################"
10060 $(2)="# MCS-52BASIC V1.3 #"
10070 $(3)="# O-M-S-U     V1.2 #"
10080 $(4)="####################"


10200 GOSUB 5000      : REM Scan keys → TP1
REM --- Running light variant (enable/comment as needed) ---
10205 XBY(0C021H)=LED : LED=2**Z : Z=Z+1 : IF Z>7 THEN Z=0
REM --- Knight Rider variant (alternative) ---
REM 10205 GOSUB 10700
10220 IF TP1=0 THEN 10200      : REM no key
10230 PRINT TP1                : REM show key number
10240 XBY(0C021H)=TP1          : REM output key value on Port B
10250 IF TP1=4 THEN 10010      : REM Re-init / refresh
10255 IF TP1=2 THEN 10500      : REM show FREE
10260 IF TP1=3 THEN 10270      : REM show MTOP
10265 IF TP1=1 THEN END

REM --- Key 3: show MTOP at position (3,14) ---
10270 $(3) = "# BASIC-RAM:    KB #" : ZEI=3 : GOSUB 9800
10280 TP1 = MTOP/1000 : GOSUB 4000
10290 ZEI=3 : ZPO=14  : GOSUB 9700
10310 XBY(0C023H)=1
10320 FOR TEX=1 TO ST
10330   XBY(0C020H)=ASC($(0),TEX) : GOSUB 9990
10340 NEXT TEX
10499 GOTO 10200

REM --- Key 2: show FREE at position (3,12) ---

10500 $(3) = "# FREE-RAM:    KB  #" : ZEI=3 : GOSUB 9800
10510 TP1 = FREE/1000 : GOSUB 4000
10520 ZEI=3 : ZPO=13  : GOSUB 9700
10540 XBY(0C023H)=1
10550 FOR TEX=1 TO ST
10560   XBY(0C020H)=ASC($(0),TEX) : GOSUB 9990
10570 NEXT TEX
10599 GOTO 10200
REM --- KNIGHT RIDER Sub ---
10700 REM SUB_KNIGHT RIDER
10705 IF UP>0 THEN 10730
10710 XBY(0C021H)=LED : LED=2**Z : Z=Z+1
10715 IF Z>7 THEN Z=7 : UP=1 : RETURN
10720 RETURN
10730 XBY(0C021H)=LED : LED=2**Z : Z=Z-1
10735 IF Z=0 THEN UP=0 : RETURN
10740 RETURN
REM =============================================================
REM = END     EXAMPLE B     LED & KEY CONTROL (10200…10740)
REM =============================================================

REM =============================================================
REM =   EXAMPLE C: 4-POINT MENU WITH KEYS (20000…20999)       
REM =============================================================
REM Keys: 1=Exit, 2=Enter, 3=Up, 4=Down
REM Example C is started with the command GOTO 20100
REM not with RUN!!!!
REM Example A or B remain in memory!!
REM =============================================================

20000 REM Set menu texts
20001 $(1)="  OPTION 1          "
20002 $(2)="  OPTION 2          "
20003 $(3)="  OPTION 3          "
20004 $(4)="  OPTION 4          "
20006 RETURN
20100 GOSUB 9500:GOSUB 9930:GOSUB 9960:GOSUB 9950:GOSUB 9985
20150 GOSUB 20000
20200 ZEI=1 : GOSUB 9800
20210 ZEI=2 : GOSUB 9800
20220 ZEI=3 : GOSUB 9800
20230 ZEI=4 : GOSUB 9800
REM Start arrow
20290 ZEI=1 : ZPO=1 : GOSUB 9700
20310 XBY(0C023H)=1
20320 XBY(0C020H)=ASC(>) : GOSUB 9990
20330 POS=1 : POA=1
REM Main loop
20400 GOSUB 10700: GOSUB 5000
20410 IF TP1=1 THEN 20800
20415 IF TP1=2 THEN 20700
20420 IF TP1=3 THEN 20600
20425 IF TP1=4 THEN 20500
20430 GOTO 20400

REM Key 4 = down
20500 POS=POS+1 : IF POS>4 THEN POS=1
20510 ZEI=POA : ZPO=1 : GOSUB 9700
REM clear old ">"
20515 XBY(0C023H)=1 : XBY(0C020H)=20H : GOSUB 9990
20525 ZEI=POS : ZPO=1 : GOSUB 9700
20530 XBY(0C023H)=1 : XBY(0C020H)=ASC(>) : GOSUB 9990
20540 POA=POS : GOTO 20400
REM Key 3 = up
20600 POS=POS-1 : IF POS<1 THEN POS=4
20610 ZEI=POA : ZPO=1 : GOSUB 9700
20615 XBY(0C023H)=1 : XBY(0C020H)=20H : GOSUB 9990
20625 ZEI=POS : ZPO=1 : GOSUB 9700
20630 XBY(0C023H)=1 : XBY(0C020H)=ASC(>) : GOSUB 9990
20640 POA=POS : GOTO 20400
REM Key 2 = Enter
20700 ON POS GOTO 20000,20710,20720,20730,20740
20710 PRINT "OPTION 1 GEWAEHLT" : GOTO 20400: REM Action option 1
20720 PRINT "OPTION 2 GEWAEHLT" : GOTO 20400: REM Action option 2
20730 PRINT "OPTION 3 GEWAEHLT" : GOTO 20400: REM Action option 3
20740 PRINT "OPTION 4 GEWAEHLT" : GOTO 20400: REM Action option 4

REM Key 1 = Exit
20800 PRINT "EXIT (ESC) GEWAEHLT“: END
REM =============================================================
REM =  END  EXAMPLE C: 4-POINT MENU WITH KEYS (20000…20999)   
REM =============================================================

image-20251118223425.png


Example program Buzzer
All my little ducklings (children's song)

10 REM =========================================================
20 REM  O-M-S-U  MCS-BASIC-52     PWM MELODY FROM DATA
30 REM  PWM high,low,cycles  on P1.2   (manual 4.27)
40 REM  XTAL = 11.0592 MHz  ->  1 clock = 12/XTAL s
50 REM =========================================================
60 XTAL = 11059200
70 TEMPO = 120       : REM BPM   (quarter note = 60000/TEMPO ms)
80 QMS = 60000/TEMPO : REM Duration of one quarter note in milliseconds
90 REM =========================================================
100 REM ----------------------- Tables -------------------------
110 DIM RL(12)            : REM Reload values, octave 4
120 DIM N(64),L(64): REM Melody: note code, length (quarters)
130 REM ---------- Reload table (octave 4) from manual --------
135 REM Indices:
140 REM 1=C 2=C# 3=D 4=D# 5=E 6=F 7=F# 8=G  9=G# 10=A 11=A# 12=B
150 RESTORE
160 FOR I=1 TO 12
170   READ RL(I)
180 NEXT I
190 REM --------- Melody (note code,length)  -1 = end ----------
200 REM
210 I=0
220 READ NI, LN
230 IF NI=-1 THEN 260
240 I=I+1 : N(I)=NI : L(I)=LN
250 GOTO 220
260 NES = I
270 REM
280 REM ------------------------ Playback ----------------------
290 FOR I=1 TO NES
300   DURMS = QMS * L(I)
310   REM Reload value from table (octave 4)
320   R = RL( N(I) )
330   GOSUB 3000     : REM Play tone
370 NEXT I
380 REM GOTO 150 : REM Endless loop
390 END
400 REM =========================================================
410 REM  Subroutines
420 REM =========================================================
3000 REM ---- Tone with reload R for DURMS ms (50% duty) -------
3010 REM Period duration (seconds) = 2 * R * (12/XTAL)
3020 TCLK = 12 / XTAL
3030 PSEC = 2 * R * TCLK
3040 CYC  = INT( (DURMS/1000) / PSEC )
3050 IF CYC<1 THEN CYC=1
3060 IF CYC>65535 THEN CYC=65535
3070 PWM R, R, CYC      : REM 50% duty cycle
3080 RETURN
9000 REM ===== DATA: Reload values octave 4 (manual) ===========
9010 REM C4  C#4  D4  D#4  E4  F4  F#4  G4  G#4  A4  A#4  B4
9020 DATA 1761,1662,1569,1481,1398,1319,1245,1176,1110,1047,989,933
9500 REM ===== DATA: Melody (note code, quarters)  (-1 ends) ===
9510 REM  C   D   E   F   G   G   A    A    A    A    G
9520 DATA 1,1,3,1,5,1,6,1,8,2,8,2,10,1,10,1,10,1,10,1,8,3
9530 DATA 10,1,10,1,10,1,10,1,8,3,8,1,6,1,6,1,6,1,5,2,5,2
9540 DATA 3,1,3,1,3,1,3,1,1,3,-1,0

elektor

Circuit diagram
image-20251118224656.png
Parts list
elektor
elektor
elektor


My Website
https://www.myMegaUNO.net

Elektor LAB Links
https://www.elektormagazine.com/labs/o-m-s-u-mcs-basic-52-v13
https://www.elektormagazine.com/labs/8052ah-basic-scalp-reborn

Elektor Links

https://www.elektormagazine.de/magazine/elektor-198706/48373 
Elektor 8051/8052 Basic-Prozessor (Grundlagen)
https://www.elektormagazine.com/magazine/elektor-200102/16965 
Elektor MCS BASIC- 52 VI 3
https://www.elektormagazine.com/magazine/elektor-199802/34046 
Elektor MCS-52 BASIC Language Quick Reference
https://www.elektormagazine.com/magazine/elektor-199110/32458 
Elektor Upgrade for MCS BASIC -52 V1.1 (1):
https://www.elektormagazine.com/magazine/elektor-199111/32480 
Elektor Upgrade for MCS BASIC-52 V1.1 (2)
https://www.elektormagazine.com/magazine /elektor-200002/16710 
Elektor BASIC-537 a high-level language for the 80535-537
https://www.elektormagazine.com/magazine/elektor-198711/47252 
Elektor Basic Computer
https://www.elektormagazine.com/ magazine/elektor-200306/17484 
Elektor CompactFlash (CF) Interface
https://www.elektormagazine.de/magazine/elektor-199802/31426 
80C32-BASIC-Steuercomputer (1)
https://www.elektormagazine.de/magazine/ elektor-199803/31454 
80C32-BASIC-Steuercomputer (2)
https://www.elektormagazine.de/magazine/elektor-199906/31856 
Elektor EEPROM fuer BASIC-Steuercomputer
https://www.elektormagazine.de/magazine/elektor- 199312/30358 
Elektor Interrupterweiterung fuer 8052-AH-BASIC