The RPN calculator now uses key interrupts rather than polling. Close #25.

This commit is contained in:
Travis Goodspeed 2018-01-27 17:08:55 -05:00
parent 3afe3e4649
commit 6ba460e766
7 changed files with 101 additions and 54 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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();