EMU8086 coding: multi-level water level sensor and rain sensor

ORG 100h ; Start address for EMU8086

; Define Ports
PORT_B EQU 12h      ; LEDs (Green, Yellow, Red)
BUZZER_PORT EQU 18h ; Buzzer Control Port

; Define LED States
GREEN_LED EQU 01h   ; Bit 0
YELLOW_LED EQU 02h  ; Bit 1
RED_LED EQU 04h     ; Bit 2

; MAIN PROGRAM
START:
    CALL INIT        ; Initialize system
    JMP MAIN_LOOP    ; Jump to the main program loop

; Subroutine: Initialize system
INIT:
    MOV AL, 0        ; Turn off all LEDs and buzzer
    OUT PORT_B, AL   ; Clear LED states
    OUT BUZZER_PORT, AL ; Turn off buzzer
    RET

; MAIN PROGRAM LOOP
MAIN_LOOP:
    CALL GET_INPUTS       ; Get water level and rain status from user
    CALL UPDATE_STATUS    ; Update LED and buzzer status
    CALL DISPLAY_RESULTS  ; Show which LED is active and buzzer state
    JMP MAIN_LOOP         ; Repeat the loop

; Subroutine: Get inputs from user
GET_INPUTS:
    ; Prompt user for water level
    LEA DX, MSG_WATER_LEVEL_PROMPT
    CALL PRINT_STRING
    CALL PRINT_NEWLINE
    MOV BX, 0             ; Clear BX for water level
READ_WATER_LEVEL:
    CALL READ_CHAR
    CMP AL, 0Dh           ; Check for Enter key (end of input)
    JE END_WATER_INPUT
    SUB AL, '0'           ; Convert ASCII to integer
    IMUL BX, 10           ; Multiply current value by 10
    ADD BX, AX            ; Add new digit
    JMP READ_WATER_LEVEL
END_WATER_INPUT:

    ; Prompt user for rain status
    LEA DX, MSG_RAIN_PROMPT
    CALL PRINT_STRING
    CALL PRINT_NEWLINE
    CALL READ_CHAR
    SUB AL, '0'           ; Convert ASCII to integer
    MOV BH, AL            ; Store rain status in BH
    RET

; Subroutine: Update LED and buzzer status
UPDATE_STATUS:
    ; Check rain status first
    CMP BH, 1             ; Is it raining?
    JE RED_ALERT          ; If yes, jump to red alert

    ; Check water level
    CMP BX, 30            ; Water level < 30 cm
    JL GREEN_LEVEL        ; Safe level, turn on green LED
    CMP BX, 150           ; Water level <= 150 cm
    JLE YELLOW_LEVEL      ; Moderate level, turn on yellow LED

    ; Otherwise, high water level
    JMP RED_ALERT

GREEN_LEVEL:
    MOV AL, GREEN_LED     ; Turn on green LED
    OUT PORT_B, AL
    MOV AL, 0             ; Turn off buzzer
    OUT BUZZER_PORT, AL
    MOV DL, 'G'           ; G = Green LED
    JMP END_UPDATE

YELLOW_LEVEL:
    MOV AL, YELLOW_LED    ; Turn on yellow LED
    OUT PORT_B, AL
    MOV AL, 0             ; Turn off buzzer
    OUT BUZZER_PORT, AL
    MOV DL, 'Y'           ; Y = Yellow LED
    JMP END_UPDATE

RED_ALERT:
    MOV AL, RED_LED       ; Turn on red LED
    OUT PORT_B, AL
    MOV AL, 1             ; Turn on buzzer
    OUT BUZZER_PORT, AL
    MOV DL, 'R'           ; R = Red LED
    JMP END_UPDATE

END_UPDATE:
    MOV CL, DL            ; Store the active LED indicator (G, Y, R) in CL
    RET

; Subroutine: Display results
DISPLAY_RESULTS:
    ; Print active LED
    LEA DX, MSG_LED_STATUS
    CALL PRINT_STRING
    CALL PRINT_NEWLINE
    MOV DL, CL            ; LED status (G, Y, R)
    CALL PRINT_CHAR
    CALL PRINT_NEWLINE

    ; Print buzzer status
    LEA DX, MSG_BUZZER_STATUS
    CALL PRINT_STRING
    CALL PRINT_NEWLINE
    IN AL, BUZZER_PORT     ; Read buzzer state
    CMP AL, 1
    JE BUZZER_ON
    LEA DX, MSG_BUZZER_OFF
    JMP PRINT_BUZZER_MSG

BUZZER_ON:
    LEA DX, MSG_BUZZER_ON

PRINT_BUZZER_MSG:
    CALL PRINT_STRING
    CALL PRINT_NEWLINE
    RET

; Subroutine: Print a string
PRINT_STRING:
    MOV AH, 09h           ; DOS function to display a string
    INT 21h
    RET

; Subroutine: Print a character
PRINT_CHAR:
    MOV AH, 02h           ; DOS function to display a single character
    INT 21h
    RET

; Subroutine: Print a newline
PRINT_NEWLINE:
    MOV AH, 02h
    MOV DL, 0Dh           ; Carriage return
    INT 21h
    MOV DL, 0Ah           ; Line feed
    INT 21h
    RET

; Subroutine: Read a character from user
READ_CHAR:
    MOV AH, 01h           ; DOS function to read a character
    INT 21h
    RET

; Messages
MSG_WATER_LEVEL_PROMPT DB 'Enter water level in cm: $'
MSG_RAIN_PROMPT DB 'Enter rain status (0 = No Rain, 1 = Rain): $'
MSG_LED_STATUS DB 'Active LED: $'
MSG_BUZZER_STATUS DB 'Buzzer is: $'
MSG_BUZZER_ON DB 'ON$', 0
MSG_BUZZER_OFF DB 'OFF$', 0

END START

The problem is this code is missing the yellow led, for example when user put input 80. it shows green or red only. on top of that, the buzzer are not supposed to depend on rain status. if its red only then the buzzer will be on. how to fix this?

i did change the circuit but it keeps messing up. and i notice that maybe the water lever cannot be read properly. when i add display the input water level on emulator screen, it shows different value from the one that i input. for example when i put 80, it just read it as 0

Upvotes: 1

Views: 30

Answers (1)

Sep Roland
Sep Roland

Reputation: 39506

maybe the water lever cannot be read properly ... for example when i put 80, it just read it as 0

Good observation!

IMUL BX, 10           ; Multiply current value by 10
ADD  BX, AX           ; Add new digit

emu8086 is an emulator for the processor and that particular CPU didn't know about the imul bx, 10 instruction (that uses an immediate operand and that can leave its result in a register other than the accumulator). Because emu8086 is also known for its many bugs, it could well have accepted your IMUL BX, 10 and encoded it as a simple AX * BX.
Furthermore, the addition of the new digit is adding-in whatever happens to be in the AH register. You should make sure AH is emptied beforehand.

Next is a replacement code:

    xor  bx, bx           ; Clear BX for water level
READ_WATER_LEVEL:
    CALL READ_CHAR
    CMP  AL, 13           ; Check for Enter key (end of input)
    JE   END_WATER_INPUT
    SUB  AL, '0'          ; Convert ASCII to integer
    cbw                   ; -> AX is [0,9]
    xchg ax, bx           ; Swap new digit and current value
    mov  dx, 10
    mul  dx               ; Multiply current value by 10
    add  bx, ax           ; Add new digit
    JMP  READ_WATER_LEVEL
END_WATER_INPUT:
CMP BH, 1             ; Is it raining?
JE RED_ALERT          ; If yes, jump to red alert
; Check water level
CMP BX, 30            ; Water level < 30 cm

You're playing a dangerous game by putting the rain status in BH. The good news is that it will work fine because both your checks CMP BX, 30 and CMP BX, 150 come at a moment when you already have established that BH is not 1, ergo BH must be 0. However, be aware that this limits the water level (in BL) to just 255 cm. So don't input numbers that are 256 or more.
You could easily opt to put the rain status in the CH register instead.

Upvotes: 1

Related Questions