mirror of
https://github.com/travisgoodspeed/goodwatch
synced 2024-11-21 23:58:31 +00:00
The RPN calculator now uses key interrupts rather than polling. Close #25.
This commit is contained in:
parent
3afe3e4649
commit
6ba460e766
@ -28,7 +28,9 @@ static struct app apps[]={
|
||||
{.name="timer", .init=stopwatch_init, .draw=stopwatch_draw, .exit=stopwatch_exit},
|
||||
|
||||
//RPN Calculator
|
||||
{.name="rpn calc", .init=rpn_init, .draw=rpn_draw, .exit=rpn_exit},
|
||||
{.name="rpn calc", .init=rpn_init, .draw=rpn_draw, .exit=rpn_exit,
|
||||
.keypress=rpn_keypress
|
||||
},
|
||||
//Hex Viewer.
|
||||
{.name="memory", .init=hex_init, .draw=hex_draw, .exit=hex_exit},
|
||||
// Diceware - passphrase generator
|
||||
|
@ -115,3 +115,11 @@ void app_packetrx(uint8_t *packet, int len){
|
||||
|
||||
apps[appindex].packetrx(packet,len);
|
||||
}
|
||||
|
||||
//! Handles a keypress, if a handler is registered.
|
||||
void app_keypress(char ch){
|
||||
/* We only pass it to applications that have a handler.
|
||||
*/
|
||||
if(apps[appindex].keypress)
|
||||
apps[appindex].keypress(ch);
|
||||
}
|
||||
|
@ -16,6 +16,16 @@ struct app {
|
||||
*/
|
||||
int (*exit)(void);
|
||||
|
||||
/* I/O can work either by interrupts or by polling. The current
|
||||
convention is to call getchar() to poll during the rendering loop
|
||||
if you are checking to see if a button is held down, but to take
|
||||
this interrupt callback when taking number entry, such as in the
|
||||
calculator.
|
||||
|
||||
Called once per unique keypress.
|
||||
*/
|
||||
void (*keypress)(char ch);//A keypress has arrived.
|
||||
|
||||
/* Callbacks for packets being sent and received. Set to null if unused. */
|
||||
void (*packetrx)(uint8_t *packet, int len); //A packet has arrived.
|
||||
void (*packettx)(void); //A packet has been sent.
|
||||
@ -34,3 +44,6 @@ void app_cleartimer();
|
||||
void app_forcehome();
|
||||
//! Provide an incoming packet.
|
||||
void app_packetrx(uint8_t *packet, int len);
|
||||
|
||||
//! Handles a keypress, if a handler is registered.
|
||||
void app_keypress(char ch);
|
||||
|
@ -100,56 +100,56 @@ int rpn_exit(){
|
||||
|
||||
//! Draws the RPN calculator.
|
||||
void rpn_draw(){
|
||||
unsigned long i, j;
|
||||
char ch=getchar();
|
||||
|
||||
//Do nothing unless a key has been pressed.
|
||||
if(oldch!=ch)
|
||||
lcd_zero();
|
||||
|
||||
//Handle key input only when first pressed.
|
||||
if(oldch==0){
|
||||
//Operators
|
||||
switch(ch){
|
||||
case '=':
|
||||
if(bufferdirty)
|
||||
rpn_pushbuffer();
|
||||
else
|
||||
rpn_push(rpn_peek());
|
||||
break;
|
||||
case '.':
|
||||
//What should this do?
|
||||
//It's out only free button.
|
||||
break;
|
||||
case '+':
|
||||
rpn_pushbuffer();
|
||||
rpn_push(rpn_pop()+rpn_pop());
|
||||
break;
|
||||
case '-':
|
||||
rpn_pushbuffer();
|
||||
j=rpn_pop();
|
||||
i=rpn_pop();
|
||||
rpn_push(i-j);
|
||||
break;
|
||||
case '*':
|
||||
rpn_pushbuffer();
|
||||
rpn_push(rpn_pop()*rpn_pop());
|
||||
break;
|
||||
case '/':
|
||||
rpn_pushbuffer();
|
||||
j=rpn_pop();
|
||||
i=rpn_pop();
|
||||
rpn_push(i/j);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Numbers are special. They modify a buffer, and the buffer is
|
||||
pushed onto the stack before an operator or when = is pressed.
|
||||
*/
|
||||
if(ch>='0' && ch<='9')
|
||||
rpn_updatebuffer(ch&0xf);
|
||||
}
|
||||
|
||||
oldch=ch;
|
||||
//We just draw the stack. All input comes from they keypress
|
||||
//callback.
|
||||
rpn_drawstack();
|
||||
}
|
||||
|
||||
//! A button has been pressed for the calculator.
|
||||
void rpn_keypress(char ch){
|
||||
unsigned long i, j;
|
||||
|
||||
//Do nothing on a keyup event.
|
||||
if(!ch)
|
||||
return;
|
||||
|
||||
//Operators
|
||||
switch(ch){
|
||||
case '=':
|
||||
if(bufferdirty)
|
||||
rpn_pushbuffer();
|
||||
else
|
||||
rpn_push(rpn_peek());
|
||||
break;
|
||||
case '.':
|
||||
//What should this do?
|
||||
//It's out only free button.
|
||||
break;
|
||||
case '+':
|
||||
rpn_pushbuffer();
|
||||
rpn_push(rpn_pop()+rpn_pop());
|
||||
break;
|
||||
case '-':
|
||||
rpn_pushbuffer();
|
||||
j=rpn_pop();
|
||||
i=rpn_pop();
|
||||
rpn_push(i-j);
|
||||
break;
|
||||
case '*':
|
||||
rpn_pushbuffer();
|
||||
rpn_push(rpn_pop()*rpn_pop());
|
||||
break;
|
||||
case '/':
|
||||
rpn_pushbuffer();
|
||||
j=rpn_pop();
|
||||
i=rpn_pop();
|
||||
rpn_push(i/j);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Numbers are special. They modify a buffer, and the buffer is
|
||||
pushed onto the stack before an operator or when = is pressed.
|
||||
*/
|
||||
if(ch>='0' && ch<='9')
|
||||
rpn_updatebuffer(ch&0xf);
|
||||
}
|
||||
|
@ -8,3 +8,6 @@ void rpn_init();
|
||||
void rpn_draw();
|
||||
//! Clears the stack to zero, or moves to the next app if already zero.
|
||||
int rpn_exit();
|
||||
|
||||
//! A button has been pressed for the calculator.
|
||||
void rpn_keypress(char ch);
|
||||
|
@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <msp430.h>
|
||||
|
||||
#include "apps.h"
|
||||
@ -25,6 +26,9 @@ void key_init(){
|
||||
P1DIR|=0x80; //P1.7 is output.
|
||||
P1REN|=0x80;
|
||||
P1OUT|=0x80; //Output high.
|
||||
|
||||
//Trigger interrupts for keypresses so we needn't scan.
|
||||
P2IE|=BIT2|BIT1|BIT0;
|
||||
}
|
||||
|
||||
//! Quickly checks to see if a key is pressed.
|
||||
@ -132,7 +136,8 @@ unsigned int key_chr(code){
|
||||
return 00;
|
||||
}
|
||||
|
||||
//! Gets a character as ASCII.
|
||||
|
||||
//! Gets the currently held button as ASCII. Don't use for typing.
|
||||
char getchar(){
|
||||
char c=key_chr(key_scan());
|
||||
if(c)
|
||||
@ -140,3 +145,19 @@ char getchar(){
|
||||
app_cleartimer();
|
||||
return c;
|
||||
}
|
||||
|
||||
//! Interrupt handler for Port2.
|
||||
void __attribute__ ((interrupt(PORT2_VECTOR))) PORT2_ISR(void){
|
||||
static char lastchar=0x00;
|
||||
char newchar=key_chr(key_scan());
|
||||
|
||||
//Bail quickly when the key is the same.
|
||||
if(lastchar==newchar) return;
|
||||
lastchar=newchar;
|
||||
app_cleartimer(); //Clear the idle timer.
|
||||
|
||||
printf("PORT2 fired, got character 0x%02x.\n",
|
||||
newchar);
|
||||
app_keypress(newchar);
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,6 @@
|
||||
unsigned int key_scan();
|
||||
//! Initialize the keypad GPIO pins.
|
||||
void key_init();
|
||||
//! Get the currently pressed button as a char.
|
||||
//! Gets the currently held button as ASCII. Don't use for typing.
|
||||
char getchar();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user