/* The "g" below really should be an "i", but gcc doesn't believe that it will
* always be an immediate value. Using "g" makes the compiler be quiet, but
- * the assembler will fail if the value is not an immediate.
+ * the assembler should fail if the value is not an immediate.
*/
extern inline void bset(void* addr, u8 mask) {
asm volatile (
void display_reset();
void display_update();
-void set_msg(char* newmsg, u8 wrap) {
- char* dest = current_message;
+void append_msg(char* newmsg, u8 wrap) {
+ char* dest = current_message[msg_length];
/* equivalent of a string copy */
- /* while (dest++ = newmsg++); */
- msg_length = 0;
while (newmsg) {
dest = newmsg;
dest++;
msg_length++;
}
wrap_mode = wrap;
+}
+
+void set_msg(char* newmsg, u8 wrap) {
+ msg_length = 0;
+ append_msg(newmsg, wrap);
scroll_point = 0;
display_update();
}
/* update the display for WRAP_SCROLL or WRAP_ALTERNATE modes */
switch (wrap_mode) {
case WRAP_SCROLL:
+ case WRAP_ALTERNATE:
scroll_point++;
if (scroll_point >= msg_length) scroll_point = 0;
display_update();
break;
- case WRAP_ALTERNATE:
- scroll_point += 10;
- if (scroll_point >= msg_length) scroll_point = 0;
- /* the above means that only sets of multiples of 10 characters
- * are shown (excess ones are not) */
- display_update();
}
}
u8 i;
for (i=0; i < 10; i++) {
- display_buffer[i] = current_message[(i+scroll_point)%msg_length];
+ display_buffer[i] = current_message[
+ (i+(wrap_mode==WRAP_ALTERNATE?scroll_point/10:scroll_point))
+ %msg_length];
}
/* hmmm, will this cause some flickering of the display? */
extern
void display_init();
+void append_msg(char* newmsg, u8 wrap);
void set_msg(char* newmsg, u8 wrap);
void set_char(char c, u8 pos);
void set_wrap_mode(u8 new_wrap_mode);
}
}
+void print_amount(u16 amt) {
+ /* take amt and show it on screen with a $ sign */
+ char str[10] = {' ', '$', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};
+ u8 pos;
+ for (pos = 7; amt; pos--, amt/=10);
+ str[pos] = amt%10 + '0';
+ }
+ set_msg(str, WRAP_NONE);
+}
u16 uid;
u16 pin;
+u8 selection;
u16 scroll_timer;
*
* Also display X's on screen as the pin is entered.
*/
+ pin = 0;
set_msg("PIN? ", WRAP_NONE);
- for (pinpos = 1; pinpos <= 5; pinpos++) {
+ for (pinpos = 1; pinpos <= 4; pinpos++) {
keypad_getkey();
if (last_key == KEY_RESET) {
pin = 0;
return 1;
}
+void make_request(u8 selection) {
+ switch(server_request(uid, pin, selection)) {
+ case REQUEST_OK:
+ set_msg("THANK YOU!", WRAP_NONE);
+ break;
+ case REQUEST_NO_MONEY:
+ set_msg("NO MONEY!", WRAP_NONE);
+ break;
+ case REQUEST_SERVFAIL:
+ set_msg("SERV FAIL!", WRAP_NONE);
+ break;
+ case REQUEST_EMPTY:
+ set_msg("NONE LEFT!", WRAP_NONE);
+ break;
+ case REQUEST_INVAL:
+ set_msg(" BAD SELN ", WRAP_NONE);
+ break;
+ }
+ delay(1000);
+}
+
void selection_menu() {
- set_msg("ENTER SELECTION OR INSERT COINS", WRAP_SCROLL);
+ /* we have a valid username & PIN number */
+ /* either ask for a 2-digit selection, or wait for coins to be entered */
+ /* get the username somehow? */
+ set_msg("ENTER SELECTION OR INSERT COINS ", WRAP_SCROLL);
+ selection = 0;
+ while(1) {
+ if (coin_value) {
+ int prev_coin = 0;
+ /* alternate between the price and a confirm message */
+ while (coin_value) {
+ if (prev_coin != coin_value) {
+ print_amount(coin_value);
+ append_msg("0: CONFIRM", WRAP_ALTERNATE);
+ prev_coin = coin_value;
+ }
+ keypad_read();
+ if (keypad_pressed()) {
+ switch (last_key) {
+ case KEY_RESET:
+ coin_refund();
+ goto reset;
+ case KEY_0:
+ switch (server_credit_account(uid, pin, coin_value)) {
+ case CREDIT_OK:
+ coin_eat();
+ set_msg(" SUCCESS! ");
+ delay(1000);
+ break;
+ case CREDIT_FAIL:
+ coin_refund();
+ set_msg(" FAILED! ");
+ delay(1000);
+ break;
+ }
+ break;
+ }
+ }
+ }
+ /* coins were refunded */
+ }
+
+ if (selection) { /* half way through a selection */
+ keypad_read();
+ if (keypad_pressed()) {
+ switch (last_key) {
+ case KEY_RESET:
+ selection = 0;
+ break;
+ case 0:
+ break;
+ default:
+ selection = selection * 10 + (last_key%10);
+ make_request(uid, pin, selection);
+ selection = 0;
+ }
+ }
+ } else { /* else listen for the first key of a selection */
+ keypad_read();
+ if (keypad_pressed()) {
+ switch (last_key) {
+ case KEY_RESET:
+ return;
+ case 0:
+ break;
+ default:
+ selection = last_key%10;
+ }
+ }
+ }
+ }
}
void load_default_msg() {
/* send msgs to server and stuff */
return AUTH_GOOD; /* for now */
}
+
+u8 server_credit_account(u16 uid, u16 pin, u16 amt) {
+ return CREDIT_OK;
+ /* alternatively credit fail? */
+}
+
+u8 server_request(u16 uid, u16 pin, u8 item) {
+ /* send a message to the server asking for item */
+ return REQUEST_OK;
+}
#define AUTH_GOOD 1
#define AUTH_BAD -1
-#define AUTH_NO_MONEY -2
+#define AUTH_NO_MONEY -2 /* for balances < $0 */
#define AUTH_LOCKED -3
+#define CREDIT_OK 1
+#define CREDIT_FAIL -1
+
+#define REQUEST_OK 1
+#define REQUEST_NO_MONEY -1 /* insufficient credit */
+#define REQUEST_SERVFAIL -2 /* server did not respond */
+#define REQUEST_EMPTY -3 /* none of item left */
+#define REQUEST_INVAL -4 /* no such item */
+
u8 server_authenticate(u16 uid, u16 pin);
#endif /* _SERVER_H_ */
/******* from helpers.c *******/
void delay(u16 ms);
+void print_amount(u16 amt);
/******** Some meaningful bits ******/
#define PORTA_DISP_RESET 0x80 /* active low */
void __attribute__((interrupt)) rti (void);
/* other one liners */
-
extern inline bool door_open() { return switch_input & A1800_DOOR_OPEN; }
extern inline void spi_enable() { bset((void*)&_io_ports[M6811_SPCR], M6811_SPE); }
extern inline void spi_disable() { bclr((void*)&_io_ports[M6811_SPCR], M6811_SPE); }