@.CHARSET CP1251

@ GNU AS
.syntax unified
.cpu cortex-m4
.thumb

.INCLUDE  "/src/inc/gpio.inc"

@ +------------------------------------------------------------+
@ |        Модуль проверки функционирования кнопок базы        |
@ +------------------------------------------------------------+
@ |                                                            |
@ | Подключения кнопок:                                        |
.equ gpio_button,  GPIOB                 @                     |
@ |  +--------------------------+--------------------------+   |
@ |  |  Menu   Pin  3           |  Exit   Pin   4          |   |
@ |  +--------------------------+--------------------------+   |
@ |  |  Up     Pin  5           |  Down   Pin   6          |   |
@ |  +--------------------------+--------------------------+   |
@ |  |  Left   Pin  7           |  Right   Pin  8          |   |
@ |  +--------------------------+--------------------------+   |
@ |  |  Power  Pin  9           |                          |   |
@ |  +--------------------------+--------------------------+   |
@ | Прочитанные значения кнопок очищаются от остальных пинов   |
@ | gpio_button начиная с метки GPIO_TUNE                      |
@ | В данном примере состояния пинов прочитанных кнопок будут  |
@ | сдвинуты вправо на 3 бита (Menu встанет на бит 0)          |
@ |                                                            |
@ | Пауза антидребезга\автоповтора, в мс (1\1000 с)            |
.EQU  Key_Delay_Const, 400                         @           |
@ +------------------------------------------------------------+

.SECTION  .bss
.align(1)
@ временные переменные
Key_Prev_state:     .SPACE     1                  @ последнее прочитанное значение
Key_Curr_time:      .SPACE     2                  @ количество тактов нажатия

@ настройки
Key_Delay_time:     .SPACE     2                  @ константа антидребезга

@ выходные значения
KEY_PRESS:          .space     1                   @ код нажатой кнопки

.SECTION .asmcode
.align(4)

@.DESC name=KEY_READER_INIT type=proc
@ +-------------------------------------------------------------+
@ |            Инициализация констрант модуля кнопок            |
@ +-------------------------------------------------------------+
@ |                                                             |
@ | Процедура вызывается из прерывания systick для организации  |
@ | опроса кнопок с функциями антидребезга                      |
@ |                                                             |
@ +-------------------------------------------------------------+
.global KEY_READER_INIT
KEY_READER_INIT:
                    @ сохранение значения константы антидребезга (автоповтора)
                    LDR        R0, = Key_Delay_Const
                    LDR        R1, = Key_Delay_time
                    STRH       R0, [ R1 ]
                    @ сброс кода нажатых кнопок
                    LDR        R1, = KEY_PRESS
                    MOV        R0, 0
                    STRB       R0, [ R1 ]

                    BX         LR

@.DESC name=IRQ_KEY_READER type=proc
@ +-------------------------------------------------------------+
@ |                  Процедура опроса кнопок                    |
@ +-------------------------------------------------------------+
@ |                                                             |
@ | Процедура вызывается из прерывания systick для организации  |
@ | опроса кнопок с функциями антидребезга                      |
@ |                                                             |
@ +-------------------------------------------------------------+
.global IRQ_KEY_READER
IRQ_KEY_READER:
                    @ прочитаем нажатые кнопки
                    LDR        R3, = Key_Prev_state  @ базовый вадрес констант модуля

                    @ читаем кнопки с GPIO_BUTTON
                    LDR        R1, = gpio_button
                    LDR        R0, [ R1, GPIO_IDR ]

                    @ Сдвиг и лог. И с прочитанными кнопками чтобы очистить прочитанное
                    @ состояние GPIO_BUTTON от других состояний пинов (кроме кнопок)
GPIO_TUNE:          LSR        R0, R0, 3
                    AND        R0, R0, 0b01111111

                    @ проверим есть ли нажатые кнопки
                    CMP        R0, 0
                    BEQ        key_exit

                    @ сравним с прошлым состояним нажатых кнопок
                    LDRB       R1, [ R3, Key_Prev_state - Key_Prev_state ]
                    CMP        R0, R1
                    BNE        Key_othner

                    @ загрузим время удержания кнопки
                    LDRH       R1, [ R3, Key_Curr_time - Key_Prev_state ]
                    CMP        R1, 0
                    BNE        key_exit  @ если антидребезг не прошел то выходим

Key_othner:         @ нажата кнопка
                    STRB       R0, [ R3, KEY_PRESS - Key_Prev_state ]    @ регистрируем нажатие
                    LDRH       R2, [ R3, Key_Delay_time - Key_Prev_state ]    @ обновляем счетчик антидребезга
                    STRH       R2, [ R3, Key_Curr_time - Key_Prev_state ]

key_exit:           @ сохраним  предыдущие нажатые кнопки
                    STRB       R0, [ R3 , Key_Prev_state - Key_Prev_state]

                    @ уменьшим счетчик антидребезга
                    LDRH       R2, [ R3, Key_Curr_time - Key_Prev_state ]
                    CMP        R2, 0
                    ITT        NE
                    SUBNE      R2, R2, 1
                    STRHNE     R2, [ R3, Key_Curr_time - Key_Prev_state ]

                    BX         LR

@.DESC name=KEY_READER type=proc
@ +-------------------------------------------------------------+
@ |             Функция получения нажатых кнопок                |
@ +-------------------------------------------------------------+
@ |                                                             |
@ | Функция возвращает код нажатой кнопки в R0                  |
@ |                                                             |
@ +-------------------------------------------------------------+
.global KEY_READER
KEY_READER:
                    PUSH       { R1, R2 }

                    @ прочитаем код нажатой кнопки с учетом антидребезга и автоповтора
                    LDR        R1, = KEY_PRESS
                    LDRB       R0, [ R1 ]

                    @ сбросим код нажатой кнопки
                    MOV        R2, 0
                    STRB       R2, [ R1 ]

                    POP        { R1, R2 }
                    BX         LR


