Reputation: 11
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
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 8086 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