avr: removed LED, renamed LED_SIMPLE to LED, introduces LED1, LED2, LED3

This commit is contained in:
Martin Preuss
2026-05-04 13:58:39 +02:00
parent a9a87ab94b
commit a9147f911c
12 changed files with 480 additions and 565 deletions

View File

@@ -30,16 +30,16 @@ modulesOnEvery100ms:
bigcall Clock_Every100ms ; generates calls to onEverySecond/Minute/Hour/Day
#endif
#ifdef MODULES_LED_SIMPLE
bigcall LedSimple_Every100ms
#ifdef MODULES_LED1
bigcall Led1_Every100ms
#endif
#ifdef MODULES_LED_SIGNAL
bigcall LedSignal_Every100ms
#ifdef MODULES_LED2
bigcall Led2_Every100ms
#endif
#ifdef MODULES_LED_ACTIVITY
bigcall LedActivity_Every100ms
#ifdef MODULES_LED3
bigcall Led3_Every100ms
#endif
#ifdef MODULES_BEEPER_SIMPLE

View File

@@ -144,18 +144,22 @@ MODULE_END_COM2W:
.include "modules/clock/main.asm"
#endif
#ifdef MODULES_LED_SIMPLE
.include "modules/led_simple/main.asm"
; unconditionally include led defs (doesn't occupy ram or flash)
.include "modules/led/defs.asm"
#ifdef MODULES_LED1
.include "modules/led/led1.asm"
#endif
#ifdef MODULES_LED_SIGNAL
.include "modules/led_signal/main.asm"
#ifdef MODULES_LED2
.include "modules/led/led2.asm"
#endif
#ifdef MODULES_LED_ACTIVITY
.include "modules/led_activity/main.asm"
#ifdef MODULES_LED3
.include "modules/led/led3.asm"
#endif
#ifdef MODULES_BEEPER_SIMPLE
.include "modules/beeper_simple/main.asm"
#endif

View File

@@ -43,25 +43,18 @@ modulesInit:
bigcall XRAM_Init
#endif
#ifdef MODULES_LED
ldi zl, LOW(ledA3Flash)
ldi zh, HIGH(ledA3Flash)
ldi yl, LOW(ledA3Sram)
ldi yh, HIGH(ledA3Sram)
bigcall Led_Init
#ifdef MODULES_LED1
bigcall Led1_Init
#endif
#ifdef MODULES_LED_SIMPLE
bigcall LedSimple_Init
#ifdef MODULES_LED2
bigcall Led2_Init
#endif
#ifdef MODULES_LED_SIGNAL
bigcall LedSignal_Init
#ifdef MODULES_LED3
bigcall Led3_Init
#endif
#ifdef MODULES_LED_ACTIVITY
bigcall LedActivity_Init
#endif
#ifdef MODULES_BEEPER_SIMPLE
bigcall BeeperSimple_Init

View File

@@ -13,7 +13,6 @@
lcd
lcd2
led
led_simple
motion
owimaster
reed

View File

@@ -3,7 +3,10 @@
<gwbuild>
<extradist>
main.asm
defs.asm
led1.asm
led2.asm
led3.asm
</extradist>
</gwbuild>

184
avr/modules/led/defs.asm Normal file
View File

@@ -0,0 +1,184 @@
; ***************************************************************************
; copyright : (C) 2026 by Martin Preuss
; email : martin@libchipcard.de
;
; ***************************************************************************
; * This file is part of the project "AqHome". *
; * Please see toplevel file COPYING of that project for license details. *
; ***************************************************************************
#ifndef AVR_MODULES_LED_DEFS_ASM
#define AVR_MODULES_LED_DEFS_ASM
; ***************************************************************************
; defines
.equ LED_FAST_REPEATS = 20
.equ LED_FAST_ONTIME = 2
.equ LED_FAST_OFFTIME = 2
.equ LED_ACTIVITY_REPEATS = 1
.equ LED_ACTIVITY_ONTIME = 3
.equ LED_ACTIVITY_OFFTIME = 5
.equ LED_ID_REPEATS = 30
.equ LED_ID_ONTIME = 5
.equ LED_ID_OFFTIME = 5
; ***************************************************************************
; macros
; ---------------------------------------------------------------------------
; @macro M_LED_INIT
;
; @param @0 idx (e.g. "1" for "LED1")
.macro M_LED_INIT
sbi LED@0_DDR, LED@0_PINNUM ; out
cbi LED@0_PORT, LED@0_PINNUM ; on
rcall Led@0_SetDefaultTiming ; (R16)
sec
.endmacro
; @end
; ---------------------------------------------------------------------------
; @macro M_LED_EVERY100MS
;
; @param @0 idx (e.g. "1" for "LED1")
.macro M_LED_EVERY100MS
lds r16, led@0Timer
tst r16
breq l_ret
dec r16
breq l_zero
rjmp l_setTimer
l_zero:
sbic LED@0_PORT, LED@0_PINNUM ; skip next op if LED is on
rjmp l_isOff
; is on
sbi LED@0_PORT, LED@0_PINNUM ; off
lds r16, led@0OffTime
rjmp l_setTimer
l_isOff:
lds r16, led@0Repeat
tst r16
breq l_restartTimer
cpi r16, 0xff
brne l_decRepeat
clr r16
rjmp l_setTimer
l_decRepeat:
dec r16
sts led@0Repeat, r16
brne l_restartTimer
; repeat counter reached 0, enter heartbeat mode
rcall Led@0_SetDefaultTiming
rjmp l_ret
l_restartTimer:
cbi LED@0_PORT, LED@0_PINNUM ; on
lds r16, led@0OnTime
l_setTimer:
sts led@0Timer, r16
l_ret:
.endmacro
; @end
; ---------------------------------------------------------------------------
; @macro M_LED_SETDEFAULTTIMING
;
; @param @0 idx (e.g. "1" for "LED1")
.macro M_LED_SETDEFAULTTIMING
ldi r18, LED@0_DEFAULT_ONTIME
ldi r19, LED@0_DEFAULT_OFFTIME
ldi r20, LED@0_DEFAULT_REPEATS
rcall Led@0_SetTiming
.endmacro
; @end
; ---------------------------------------------------------------------------
; @macro M_LED_SETFASTTIMING
;
; @param @0 idx (e.g. "1" for "LED1")
.macro M_LED_SETFASTTIMING
ldi r18, 5
ldi r19, 3
ldi r20, LED_FAST_REPEATS
rcall Led@0_SetTiming
.endmacro
; @end
; ---------------------------------------------------------------------------
; @macro M_LED_SETIDTIMING
;
; @param @0 idx (e.g. "1" for "LED1")
.macro M_LED_SETIDTIMING
ldi r18, LED_ID_ONTIME
ldi r19, LED_ID_OFFTIME
ldi r20, LED_ID_REPEATS
rcall Led@0_SetTiming
.endmacro
; @end
; ---------------------------------------------------------------------------
; @macro M_LED_SETACTIVITYTIMING
;
; @param @0 idx (e.g. "1" for "LED1")
.macro M_LED_SETACTIVITYTIMING
ldi r18, LED_ACTIVITY_ONTIME
ldi r19, LED_ACTIVITY_OFFTIME
ldi r20, LED_ACTIVITY_REPEATS
rcall Led@0_SetTiming
.endmacro
; @end
; ---------------------------------------------------------------------------
; @macro M_LED_SETTIMING
;
; @param @0 idx (e.g. "1" for "LED1")
.macro M_LED_SETTIMING
sts led@0OnTime, r18
sts led@0Timer, r18
sts led@0OffTime, r19
sts led@0Repeat, r20
tst r18
brne l_1
sbi LED@0_PORT, LED@0_PINNUM ; off
rjmp l_ret
l_1:
cbi LED@0_PORT, LED@0_PINNUM ; on
l_ret:
.endmacro
; @end
#endif

90
avr/modules/led/led1.asm Normal file
View File

@@ -0,0 +1,90 @@
; ***************************************************************************
; copyright : (C) 2026 by Martin Preuss
; email : martin@libchipcard.de
;
; ***************************************************************************
; * This file is part of the project "AqHome". *
; * Please see toplevel file COPYING of that project for license details. *
; ***************************************************************************
#ifndef AVR_MODULES_LED_LED1_ASM
#define AVR_MODULES_LED_LED1_ASM
; ***************************************************************************
; data
.dseg
led1Timer: .byte 1
led1OnTime: .byte 1
led1OffTime: .byte 1
led1Repeat: .byte 1
; ***************************************************************************
; code
.cseg
Led1_Init:
M_LED_INIT 1
ret
; @end
Led1_Every100ms:
M_LED_EVERY100MS 1
ret
; @end
Led1_SetDefaultTiming:
M_LED_SETDEFAULTTIMING 1
ret
; @end
Led1_SetFastTiming:
M_LED_SETFASTTIMING 1
ret
; @end
Led1_SetIdTiming:
M_LED_SETIDTIMING 1
ret
; @end
Led1_SetActivityTiming:
M_LED_SETACTIVITYTIMING 1
ret
; @end
Led1_SetTiming:
M_LED_SETTIMING 1
ret
; @end
#endif

90
avr/modules/led/led2.asm Normal file
View File

@@ -0,0 +1,90 @@
; ***************************************************************************
; copyright : (C) 2026 by Martin Preuss
; email : martin@libchipcard.de
;
; ***************************************************************************
; * This file is part of the project "AqHome". *
; * Please see toplevel file COPYING of that project for license details. *
; ***************************************************************************
#ifndef AVR_MODULES_LED_LED2_ASM
#define AVR_MODULES_LED_LED2_ASM
; ***************************************************************************
; data
.dseg
led2Timer: .byte 1
led2OnTime: .byte 1
led2OffTime: .byte 1
led2Repeat: .byte 1
; ***************************************************************************
; code
.cseg
Led2_Init:
M_LED_INIT 2
ret
; @end
Led2_Every100ms:
M_LED_EVERY100MS 2
ret
; @end
Led2_SetDefaultTiming:
M_LED_SETDEFAULTTIMING 2
ret
; @end
Led2_SetFastTiming:
M_LED_SETFASTTIMING 2
ret
; @end
Led2_SetIdTiming:
M_LED_SETIDTIMING 2
ret
; @end
Led2_SetActivityTiming:
M_LED_SETACTIVITYTIMING 2
ret
; @end
Led2_SetTiming:
M_LED_SETTIMING 2
ret
; @end
#endif

90
avr/modules/led/led3.asm Normal file
View File

@@ -0,0 +1,90 @@
; ***************************************************************************
; copyright : (C) 2026 by Martin Preuss
; email : martin@libchipcard.de
;
; ***************************************************************************
; * This file is part of the project "AqHome". *
; * Please see toplevel file COPYING of that project for license details. *
; ***************************************************************************
#ifndef AVR_MODULES_LED_LED3_ASM
#define AVR_MODULES_LED_LED3_ASM
; ***************************************************************************
; data
.dseg
led3Timer: .byte 1
led3OnTime: .byte 1
led3OffTime: .byte 1
led3Repeat: .byte 1
; ***************************************************************************
; code
.cseg
Led3_Init:
M_LED_INIT 3
ret
; @end
Led3_Every100ms:
M_LED_EVERY100MS 3
ret
; @end
Led3_SetDefaultTiming:
M_LED_SETDEFAULTTIMING 3
ret
; @end
Led3_SetFastTiming:
M_LED_SETFASTTIMING 3
ret
; @end
Led3_SetIdTiming:
M_LED_SETIDTIMING 3
ret
; @end
Led3_SetActivityTiming:
M_LED_SETACTIVITYTIMING 3
ret
; @end
Led3_SetTiming:
M_LED_SETTIMING 3
ret
; @end
#endif

View File

@@ -1,333 +0,0 @@
; ***************************************************************************
; copyright : (C) 2023 by Martin Preuss
; email : martin@libchipcard.de
;
; ***************************************************************************
; * This file is part of the project "AqHome". *
; * Please see toplevel file COPYING of that project for license details. *
; ***************************************************************************
; ***************************************************************************
; defs
.equ LED_DATA_OFFS_ADDRDDR = 0
.equ LED_DATA_OFFS_ADDRPORT = 1
.equ LED_DATA_OFFS_ADDRPIN = 2
.equ LED_DATA_OFFS_PINMASK = 3
.equ LED_SRAM_OFFS_PATTERNADDR = 0
.equ LED_SRAM_OFFS_COUNTER = 2
.equ LED_SRAM_OFFS_POS = 3
.equ LED_SRAM_SIZE = 4
; ***************************************************************************
; data
.dseg
ledA3Sram: .byte LED_SRAM_SIZE
; ***************************************************************************
; code
.cseg
LED_BEGIN:
; ---------------------------------------------------------------------------
; Led_Init
;
; IN:
; - Y: pointer to SRAM data
; - Z: pointer to FLASH data
; OUT:
; - CFLAG: set if okay, clear on error
; USED: R1, R2, R3, R4, R16, R17, X
Led_Init:
mov xh, yh
mov xl, yl
clr r16
ldi r17, LED_SRAM_SIZE
rcall Utils_FillSram
rcall ledGetFlashDataIntoRegs
brcc Led_Init_end
; set bit in DDR register (-> output)
mov xl, r1 ; DDR register address
clr xh
ld r16, x
or r16, r4 ; output
st x, r16
; turn off led
rcall ledOff
sec
Led_Init_end:
ret
; ---------------------------------------------------------------------------
; Led_SetPattern
;
; IN:
; - X: pointer to led pattern in flash
; - Y: pointer to SRAM data
; - Z: pointer to FLASH data
; OUT:
; - CFLAG: set if okay, clear on error
; USED: R1, R2, R3, R4, R16, R17, Z
Led_SetPattern:
rcall ledGetFlashDataIntoRegs
brcc Led_SetPattern_l2
std y+LED_SRAM_OFFS_PATTERNADDR, xl ; param 1
std y+LED_SRAM_OFFS_PATTERNADDR+1, xh ; param 2
; reset pos in pattern
clr r19
std y+LED_SRAM_OFFS_POS, r19
; store counter for current pattern element
mov zl, xl
mov zh, xh
lsl zl ; multiplay Z by 2
rol zh
lpm r19, z ; read current pattern counter
std y+LED_SRAM_OFFS_COUNTER, r19
; each pattern starts with LED on
rcall ledOn
Led_SetPattern_l2:
ret
; ---------------------------------------------------------------------------
; Led_Tick
;
; IN:
; - Y: pointer to SRAM data
; - Z: pointer to FLASH data
; OUT:
; - CFLAG: set if something done, reset otherwise
; USED:
Led_Tick:
rcall ledGetFlashDataIntoRegs
brcs Led_Tick_l1
ret
Led_Tick_l1:
ldd zl, y+LED_SRAM_OFFS_PATTERNADDR
ldd zh, y+LED_SRAM_OFFS_PATTERNADDR+1
ldd r18, y+LED_SRAM_OFFS_POS
ldd r19, y+LED_SRAM_OFFS_COUNTER
; test NULL ptr
mov r16, zl;
or r16, zh
breq Led_Tick_end ; no current pattern, end
cpi r19, 2 ; current counter less than 2?
brcs Led_Tick_nextPhase
dec r19
std y+LED_SRAM_OFFS_COUNTER, r19
ret
Led_Tick_nextPhase:
lsl zl ; multiplay Z by 2
rol zh
inc r18 ; next pos
rcall Led_Tick_getPattern
cpi r16, 0xff
breq Led_Tick_restart
cpi r16, 0
breq Led_Tick_stop
std y+LED_SRAM_OFFS_POS, r18
std y+LED_SRAM_OFFS_COUNTER, r16
mov r17, r18
andi r17, 1 ; even?
breq Led_Tick_switchOn
rjmp ledOff
Led_Tick_switchOn:
; turn on led
rjmp ledOn
Led_Tick_stop:
clr r16
std y+LED_SRAM_OFFS_PATTERNADDR, r16
std y+LED_SRAM_OFFS_PATTERNADDR+1, r16
std y+LED_SRAM_OFFS_COUNTER, r16
std y+LED_SRAM_OFFS_POS, r16
; LED off
rcall ledOff
Led_Tick_restart:
ldi r18, 0
rcall Led_Tick_getPattern
cpi r16, 0xff
breq Led_Tick_stop ; stop, because restart as first pattern is invalid
cpi r16, 0
breq Led_Tick_stop
std y+LED_SRAM_OFFS_POS, r18 ; incremented pos in pattern
std y+LED_SRAM_OFFS_COUNTER, r16 ; new counter value
rcall ledOn
ret
Led_Tick_getPattern: ; r18=pos
ldd zl, y+LED_SRAM_OFFS_PATTERNADDR
ldd zh, y+LED_SRAM_OFFS_PATTERNADDR+1
lsl zl ; multiplay Z by 2
rol zh
ldi r16, 0
add zl, r18
adc zh, r16
lpm r16, z
ret
Led_Tick_end:
ret
; ---------------------------------------------------------------------------
; ledGetFlashDataIntoRegs
;
; IN:
; - R28/ZL: pointer to data in flash (low)
; - R29/ZH: pointer to data in flash (hi)
; OUT:
; - CARRY flag set if okay, clear on error
; - R1: memory address of DDR register
; - R2: memory address of PORT register
; - R3: memory address of PIN register
; - R4: mask for used pin
; USED: R16
ledGetFlashDataIntoRegs:
push zh
push zl
mov r16, zl
or r16, zh
breq ledGetFlashDataIntoRegs_error
lsl zl
rol zh
lpm r1, z+ ; DDR
lpm r2, z+ ; PORTR
lpm r3, z+ ; PINR
lpm r4, z ; pin mask
pop zl
pop zh
sec
ret
ledGetFlashDataIntoRegs_error:
pop zl
pop zh
clc
ret
; ---------------------------------------------------------------------------
; ledOff
;
; IN:
; - R2: port register address (low part only)
; - R4: bit mask for pin to use
; OUT:
; - nothing
; MODIFIED REGS: none
; CYCLES: 26 (if R2 and R4 valid)
ledOff:
tst r2 ; 1
breq ledOff_end ; 1 if not taken
tst r4 ; 1
breq ledOff_end ; 1 if not taken
push xh ; 2
push xl ; 2
push r16 ; 2
mov xl, r2 ; 1 PORT register address
clr xh ; 1
ld r16, x ; 1
or r16, r4 ; 1
st x, r16 ; 2
pop r16 ; 2
pop xl ; 2
pop xh ; 2
ledOff_end:
ret ; 4
; ---------------------------------------------------------------------------
; ledOn
;
; IN:
; - R2: port register address (low part only)
; - R4: bit mask for pin to use
; OUT:
; - nothing
; MODIFIED REGS: none
; CYCLES: 28
ledOn: ; clock cycles
tst r2 ; 1
breq ledOn_end ; 1 if not taken
tst r4 ; 1
breq ledOn_end ; 1 if not taken
push xh ; 2
push xl ; 2
push r16 ; 2
mov xl, r2 ; 1 PORT register address
clr xh ; 1
ld r16, x ; 1
com r4 ; 1 invert bit mask for following AND
and r16, r4 ; 1
com r4 ; 1 undo inversion
st x, r16 ; 2
pop r16 ; 2
pop xl ; 2
pop xh ; 2
ledOn_end:
ret ; 4
LED_END:
.equ MODULE_SIZE_LED = LED_END-LED_BEGIN

View File

@@ -1,11 +0,0 @@
<?xml?>
<gwbuild>
<extradist>
main.asm
</extradist>
</gwbuild>

View File

@@ -1,194 +0,0 @@
; ***************************************************************************
; copyright : (C) 2026 by Martin Preuss
; email : martin@libchipcard.de
;
; ***************************************************************************
; * This file is part of the project "AqHome". *
; * Please see toplevel file COPYING of that project for license details. *
; ***************************************************************************
; ***************************************************************************
; defines
.equ LED_SIMPLE_LED_FAST_REPEATS = 20
.equ LED_SIMPLE_LED_FAST_ONTIME = 2
.equ LED_SIMPLE_LED_FAST_OFFTIME = 2
.equ LED_SIMPLE_LED_ACTIVITY_REPEATS = 1
.equ LED_SIMPLE_LED_ACTIVITY_ONTIME = 3
.equ LED_SIMPLE_LED_ACTIVITY_OFFTIME = 5
.equ LED_SIMPLE_LED_ID_REPEATS = 30
.equ LED_SIMPLE_LED_ID_ONTIME = 5
.equ LED_SIMPLE_LED_ID_OFFTIME = 5
; ***************************************************************************
; data
.dseg
ledSimpleTimer: .byte 1
ledSimpleOnTime: .byte 1
ledSimpleOffTime: .byte 1
ledSimpleRepeat: .byte 1
; ***************************************************************************
; code
.cseg
LED_SIMPLE_BEGIN:
; ---------------------------------------------------------------------------
; LedSimple_Init
;
; IN:
; - nothing
; OUT:
; - CFLAG: set if okay, clear on error
; USED: R1, R2, R3, R4, R16, R17, X
LedSimple_Init:
sbi LED_SIMPLE_DDR, LED_SIMPLE_PINNUM ; out
cbi LED_SIMPLE_PORT, LED_SIMPLE_PINNUM ; on
rcall LedSimple_SetDefaultTiming ; (R16)
sec
ret
; ---------------------------------------------------------------------------
; @routine LedSimple_Every100ms @global
;
; @clobbers r16, r18, r19, r20
LedSimple_Every100ms:
lds r16, ledSimpleTimer
dec r16
breq LedSimple_Every100ms_zero
rjmp LedSimple_Every100ms_setTimer
LedSimple_Every100ms_zero:
sbic LED_SIMPLE_PORT, LED_SIMPLE_PINNUM ; skip next op if LED is on
rjmp LedSimple_Tick_isOff
; is on
sbi LED_SIMPLE_PORT, LED_SIMPLE_PINNUM ; off
lds r16, ledSimpleOffTime
rjmp LedSimple_Every100ms_setTimer
LedSimple_Tick_isOff:
lds r16, ledSimpleRepeat
tst r16
breq LedSimple_Tick_restartTimer
dec r16
sts ledSimpleRepeat, r16
brne LedSimple_Tick_restartTimer
; repeat counter reached 0, enter heartbeat mode
rcall LedSimple_SetDefaultTiming
rjmp LedSimple_Every100ms_ret
LedSimple_Tick_restartTimer:
cbi LED_SIMPLE_PORT, LED_SIMPLE_PINNUM ; on
lds r16, ledSimpleOnTime
LedSimple_Every100ms_setTimer:
sts ledSimpleTimer, r16
LedSimple_Every100ms_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine LedSimple_SetDefaultTiming @global
;
; Set default timing for LED.
; @clobbers R18, R19, R20
LedSimple_SetDefaultTiming:
ldi r18, LED_SIMPLE_ONTIME
ldi r19, LED_SIMPLE_OFFTIME
clr r20
rjmp LedSimple_SetTiming
; @end
; ---------------------------------------------------------------------------
; @routine LedSimple_SetFastTiming @global
;
; Set fast blinking timing for LED. Switch LED on.
; @clobbers R18, R19, R20
LedSimple_SetFastTiming:
ldi r18, 5
ldi r19, 3
ldi r20, LED_SIMPLE_LED_FAST_REPEATS
rjmp LedSimple_SetTiming
; @end
; ---------------------------------------------------------------------------
; @routine LedSimple_SignalId @global
;
; Set ID timing for LED (used to id a device).
; @clobbers R18, R19, R20
LedSimple_SignalId:
ldi r18, LED_SIMPLE_LED_ID_ONTIME
ldi r19, LED_SIMPLE_LED_ID_OFFTIME
ldi r20, LED_SIMPLE_LED_ID_REPEATS
rjmp LedSimple_SetTiming
; @end
; ---------------------------------------------------------------------------
; @routine LedSimple_SignalActivity @global
;
; Set ID timing for LED (used to id a device).
; @clobbers R18, R19, R20
LedSimple_SignalActivity:
ldi r18, LED_SIMPLE_LED_ACTIVITY_ONTIME
ldi r19, LED_SIMPLE_LED_ACTIVITY_OFFTIME
ldi r20, LED_SIMPLE_LED_ACTIVITY_REPEATS
rjmp LedSimple_SetTiming
; @end
; ---------------------------------------------------------------------------
; @routine LedSimple_SetTiming @global
;
; Set blinking timing for LED. Switch LED on.
; @param r18 ontime (in 1/10s)
; @param r19 offtime (in 1/10s)
; @param r20 repeats (stop after this number of repeats, 0 for continuous mode)
; @clobbers none
;
LedSimple_SetTiming:
sts ledSimpleOnTime, r18
sts ledSimpleTimer, r18
sts ledSimpleOffTime, r19
sts ledSimpleRepeat, r20
cbi LED_SIMPLE_PORT, LED_SIMPLE_PINNUM ; on
ret
; @end
LED_SIMPLE_END:
.equ MODULE_SIZE_LED_SIMPLE = LED_SIMPLE_END-LED_SIMPLE_BEGIN