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.
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.
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).
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.
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.
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.
I²C BUS - Pin assignment of connector W1
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
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. 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. 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.
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
Pin assignment SV8
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 =============================================================
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 =============================================================
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 =============================================================
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
Veuillez saisir votre adresse électronique. Les instructions de réinitialisation de votre mot de passe vous seront immédiatement envoyées par courriel.
Discussion (0 commentaire(s))