; Макрос пересчета таймеров
.macro DecTimers
LDI ZL, Low(TimerQueue) ; Грузим начало очереди таймеров
LDI ZH, High(TimerQueue)
LDI R16, 0
Decrease: ; Цикл уменьшения таймеров
LD R17, Z+ ; Таймеры 2х-байтные
LD R18, Z
CPI R17, 0 ; побайтово сравниваем
BRNE Decr ; Если 0 - то не надо уменьшать
CPI R18, 0
BREQ NoDecrease
Decr:
SUBI R17, 1 ; уменьшаем на 1
SBCI R18, 0
LD R0, -Z ; и переписываем старые значения
ST Z+, R17
ST Z, R18
CPI R17, 0 ; если стало равно нулю - надо
BRNE NoDecrease ; запускать процесс
CPI R18, 0
BRNE NoDecrease
MOV R17, R16 ; в R17 номер процесса
RCALL StartProcess ; API StartProcess
NoDecrease:
LD R0, Z+ ; переход к следующей ячейке
INC R16 ; Inc R16; если стал равен кол-ву
CPI R16, ProcNum ; процессов - значит выход.
BRNE Decrease
.endm
Тут мы проходимся по всему массиву таймеров, уменьшаем все на 1 (если
они не равны нулю конечно), и, если таймер достиг нуля, то запускаем
соответствующий ему процесс. Алгоритм, думаю, достаточно
прокомментирован.
Да, вспомнил. Таймер в моей операционке - далеко не точный. Как понятно
из кода, число в таймере - количество переключений процессов до
следующего запуска. Его можно использовать лишь чтобы, например
примерно каждые 20 миллисекунд параллельно основной программе
сканировать клавиатуру, каждые 40мс обновлять дисплей и т.п. Вообщем