Click, Double Click, Long Click 구분하기
전 글에 이어서 KCC426V와 ATtiny2313으로 FM radio 만들기를 계속합니다. 이번 글에서는 KCC426V radio에 부착한 엔코더의 push switch를 활용하는 방법을 탐구해 봅니다.
전자 기기들을 사용하다 보면 같은 버튼을 단순 click했을 때와 double click 했을 때 또는 길게 눌렀을 때에 각각 다른 역할을 하도록 하는 경우가 많습니다. 이 글에서도 엔코더의 push switch의 단순 click, double click, long click을 구분해서 각각 다른 용도로 활용할 수 있도록 하겠습니다. 본 글에서 구현한 논리는 어떤 자료를 보고 학습한 것이 아니라, 필자의 생각으로만 구현한 것이라서 일반적 방법이 아닐 수도 있다는 점을 참고해 주시기 바랍니다.
다음은 대략의 순서도입니다.
이 순서도에서는 push switch 처리를 인터럽트로 하지 않고 polling 방식으로 합니다. 위 순서도를 간단히 설명하면 다음과 같습니다.
1) 스위치가 눌렸는가? 안 눌렸으면 Encoder_sw에 0을 넣고 돌아감.
2) LongClickTime 이상 스위치를 누르고 있으면, Long Click으로 판단하고 스위치를 놓을 때까지 기다렸다가 종료
3) LongClickTime 이전에 스위치를 놓으면, DoubleClickTime 이전에 다시 스위치가 눌리면 Double Click으로 판단하고 스위치를 놓을 때까지 기다렸다가 종료
4) 3)단계에서 DoubleClickTime이 경과해도 스위치를 누르지 않으면 그냥 Click으로 판단하고 종료
위의 순서도에 따라 AVR 어셈블리어로 작성한 소스프로그램입니다.
대부분 순서도에 따라 프로그래밍 했으나, 함수명이나 변수명이 조금 다릅니다.
그래도 함수명이나 변수명을 보면 그 역할을 쉽게 알 수 있을 것이며, 간단히 주석도 달아 놓았습니다.
ENCODER_SW_PRESSED:
LDS AL,NO_CLICK
SBIC KCC426V_PIN,ENCODER_SW_BIT
RJMP ENCODER_SW_PRESSED_QUIT // if SW released
PUSH AH
PUSH YL
PUSH YH
PUSH ZL
PUSH ZH
LDI AL,SHORT_CLICK
LDI YL,LOW(LONG_CLICK_TIME)
LDI YH,HIGH(LONG_CLICK_TIME)
LDI ZL,0 // ZH:ZL LapTIme = 0
LDI ZH,0
ENCODER_SW_PRESSED_WAIT_RELEASE1:
SBIC KCC426V_PIN,ENCODER_SW_BIT
RJMP ENCODER_SW_PRESSED_RELEASED1 // if SW released
RCALL DELAY_1MS // Delay 1ms
ADIW Z,1 // LapTime += 1
CP ZL,YL
CPC ZH,YH
BRLO ENCODER_SW_PRESSED_WAIT_RELEASE1 // if LapTime < LongClickTime
LDI AL,LONG_CLICK
RJMP ENCODER_SW_PRESSED_WAIT_RELEASE_SAVE_SW
ENCODER_SW_PRESSED_RELEASED1:
LDI ZL,0
LDI ZH,0 // LapTime = 0
LDI YL,LOW(DOUBLE_CLICK_TIME)
LDI YH,HIGH(DOUBLE_CLICK_TIME)
ENCODER_SW_PRESSED_WAIT_DOUBLE:
CP ZL,YL
CPC ZH,YH
BRSH ENCODER_SW_PRESSED_SAVE_SW // if LapTime >= DoubleClickTime
RCALL DELAY_1MS // Delay 1ms
ADIW Z,1 // LapTime += 1
SBIC KCC426V_PIN,ENCODER_SW_BIT
RJMP ENCODER_SW_PRESSED_WAIT_DOUBLE // if SW not pressed
LDI AL,DOUBLE_CLICK
ENCODER_SW_PRESSED_WAIT_RELEASE_SAVE_SW:
SBIS KCC426V_PIN,ENCODER_SW_BIT
RJMP ENCODER_SW_PRESSED_WAIT_RELEASE_SAVE_SW // if SW not released
ENCODER_SW_PRESSED_SAVE_SW:
POP ZH
POP ZL
POP YH
POP YL
POP AH
ENCODER_SW_PRESSED_QUIT:
STS ENCODER_SWITCH,AL
RET
ENCODER_SW_PRESSED 함수를 호출한 다음에 AL 값 또는 ENCODER_SWITCH 값을 읽어서 필요한 조치를 취하면됩니다.
지금까지 완성한 소스프로그램을 압축 파일 KCC426V_2313(1).zip을 첨부합니다.
압축 파일 안에 KCC426V_2313.asm, CLCD.asm, Delay8MHz.asm 등 3개의 소스프로그램들이 있습니다. 메인 프로그램은 KCC426V_2313.asm이고 나머지 두 프로그램은 파일명에서 알 수 있는 기능을 하는 루틴들을 담아 놨습니다.
KCC426V-2313.asm 안에 DO_ENCODER_SWITCH 함수 안에
DO_CLICK, DO_LONG_CLICK, DO_DOUBLE_CLICK에 각각의 클릭에 따라 원하는 동작을 하는 기능을 넣으면 됩니다.
예를 들어 단순 클릭시에는 현 주파수 값을 EEPROM에 기록하고, LONG_CLICK을 하면 방송을 검색하고, LONG_CLICK을 하면 메뉴를 표시하게 하는 등 다양하게 응용할 수 있습니다.
현재는 LCD 2행 1열에 CLICK시에는 문자 A, LONG CLICK시에는 문자 B, DOUBLE CLICK시에는 문자 C를 출력하도록 해 두었습니다.