X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=ROM2%2Fmain_basic.c;h=0f9d3eab01f5bddf7e057d16dc192a0b074fdbcf;hb=HEAD;hp=f6a5b9f9d1a107d69886af2a019f74af799311f2;hpb=a1106ee52492a26f91897578c0761d1aedf6b44c;p=uccvend-snackrom.git diff --git a/ROM2/main_basic.c b/ROM2/main_basic.c index f6a5b9f..0f9d3ea 100644 --- a/ROM2/main_basic.c +++ b/ROM2/main_basic.c @@ -4,8 +4,7 @@ * and snacks. */ -#define VERSION_STRING "R 20040622" - +#include "version.h" #include "display_basic.h" #include "keypad.h" #include "chime.h" @@ -14,7 +13,7 @@ #include "sci.h" #include "vend.h" #include "xmodem.h" -#include "sha1.h" +#include "mic.h" u8 last_standalone; u8 last_switch_input; @@ -34,6 +33,14 @@ bool check_standalone() { return 0; } +bool check_badpoke() { + if (cant_poke()) { + send_string("099 Can't poke without flipping DIP SW 3." CRLF); + return 1; + } + return 0; +} + void unknown_command() { send_string("012 Unknown command. Type HELP for help." CRLF); } @@ -63,6 +70,10 @@ void dispense_something() { u8 slot; if (check_standalone()) return; + if (must_verify() && !mic_verify((void*)sci_rx_buf)) { + send_string("019 Message verification failed." CRLF); + return; + } if (my_strncmp("ALL", (char*)sci_rx_buf+1, 3)) { char motor[3]; @@ -70,10 +81,11 @@ void dispense_something() { send_string("102 Vend all motors starting." CRLF); for (motor[0] = '0'; motor[0] <= '9'; motor[0]++) { for (motor[1] = '0'; motor[1] <= '9'; motor[1]++) { + if (motor[1] == '5') continue; /* there is now row 5 */ send_string("101 Vending "); send_string(motor); send_string(CRLF); - motor_reply(dispense_motor(motor[0]*10+motor[1])); + motor_reply(dispense_motor((motor[0]-'0')*10+(motor[1]-'0'))); } } send_string("102 Vend all motors complete." CRLF); @@ -134,7 +146,7 @@ void give_change() { (sci_rx_buf[3] < '0') || (sci_rx_buf[3] > '9') || (sci_rx_buf[4] < '0') || (sci_rx_buf[4] > '9') || (sci_rx_buf[5] < '0') || (sci_rx_buf[5] > '9')) { - send_nack(); + //send_nack(); } cost = sci_rx_buf[1] - '0'; cost *= 10; cost = sci_rx_buf[2] - '0'; @@ -143,7 +155,7 @@ void give_change() { cost *= 10; cost = sci_rx_buf[5] - '0'; coin_cost(cost); - send_ack(); + //send_ack(); } void send_keypress(u8 key) { @@ -163,6 +175,20 @@ void send_keypress(u8 key) { send_string(" key." CRLF); } +void send_timer() { + /* send a packet of the form KX with X being the key, or R for reset */ + unsigned int t=get_timer_counter(); + + send_string("013 "); + sci_tx_buf[0] = '0'+(t/10000)%10; + sci_tx_buf[1] = '0'+(t/1000)%10; + sci_tx_buf[2] = '0'+(t/100)%10; + sci_tx_buf[3] = '0'+(t/10)%10; + sci_tx_buf[4] = '0'+t%10; + sci_tx_buf[5] = 0; + send_buffer(1); +} + void send_door_msg(bool open) { if (is_standalone()) return; sci_tx_buf[0] = '4'; @@ -175,42 +201,56 @@ void send_door_msg(bool open) { send_string(" door closed." CRLF); } -u8 hexchar2u8(char b) { - if (b >= '0' && b <= '9') return b-'0'; - if (b >= 'a' && b <= 'f') return b-'a'+0x0a; - if (b >= 'A' && b <= 'F') return b-'A'+0x0a; - return 0; -} - -char nibble2hexchar(u8 b) { - if (b <= 9) return b+'0'; - if (b >= 10 && b <= 15) return b+'A'-10; - return 'X'; -} - -u8 hex2u8(char msb, char lsb) { - return (hexchar2u8(msb) << 4) + hexchar2u8(lsb); -} - -static char hexconv_buf[3]; -char* u82hex(u8 a) { - hexconv_buf[0] = nibble2hexchar((a&0xf0) >> 4); - hexconv_buf[1] = nibble2hexchar(a&0x0f); - hexconv_buf[2] = '\0'; - return hexconv_buf; -} - void do_chime() { if (check_standalone()) return; if (sci_rx_buf[1] == '\0') chime_start(); - else if (sci_rx_buf[2] != '\0' && sci_rx_buf[3] == '\0') + else if (sci_rx_buf[1] == 'S') { /* synchronous beep */ + if (sci_rx_buf[2] == '\0') + chime_start(); + else if (sci_rx_buf[3] != '\0' && sci_rx_buf[4] == '\0') + chime_for(hex2u8(sci_rx_buf[2], sci_rx_buf[3])); + else { + send_string("510 Unknown chime duration." CRLF); + return; + } + while (chime_count); /* spin */ + send_string("500 Chimed." CRLF); + return; + } else if (sci_rx_buf[2] != '\0' && sci_rx_buf[3] == '\0') chime_for(hex2u8(sci_rx_buf[1], sci_rx_buf[2])); else { send_string("510 Unknown chime duration." CRLF); return; } - send_string("500 Chimed." CRLF); + send_string("500 Chime started." CRLF); + return; +} + +void do_silence() { + if (check_standalone()) return; + if (sci_rx_buf[1] == '\0') + unchime_start(); + else if (sci_rx_buf[1] == 'S') { /* synchronous beep */ + if (sci_rx_buf[2] == '\0') + unchime_start(); + else if (sci_rx_buf[3] != '\0' && sci_rx_buf[4] == '\0') + unchime_for(hex2u8(sci_rx_buf[2], sci_rx_buf[3])); + else { + send_string("511 Unknown silence duration." CRLF); + return; + } + while (unchime_count); /* spin */ + send_string("501 Silenced." CRLF); + return; + } else if (sci_rx_buf[2] != '\0' && sci_rx_buf[3] == '\0') + unchime_for(hex2u8(sci_rx_buf[1], sci_rx_buf[2])); + else { + send_string("511 Unknown silence duration." CRLF); + return; + } + send_string("501 Silence started." CRLF); + return; } void print_switches(u8 prompted) { @@ -234,8 +274,92 @@ void ping_pong() { send_string("000 PONG!" CRLF); } +u16 hex2addr(char* addrptr) { + u16 v; + v = hex2u8(addrptr[0], addrptr[1]) << 8; + v |= hex2u8(addrptr[2], addrptr[3]); + return v; +} + +void peek() { + if (!my_strncmp("EEK", (char*)sci_rx_buf+1, 3)) { + unknown_command(); + return; + } + if (check_badpoke()) return; + if (ishex(sci_rx_buf[4]) && ishex(sci_rx_buf[5]) && ishex(sci_rx_buf[6]) && + ishex(sci_rx_buf[7]) && sci_rx_buf[8] == '\0') { + u16 v = hex2addr((char*)(sci_rx_buf+4)); + v = *((u8*)v); + send_string("090 "); + send_string(u82hex(v)); + send_string(CRLF); + return; + } + send_string("091 Invalid location given." CRLF); +} + +void poke() { + if (!my_strncmp("OKE", (char*)sci_rx_buf+1, 3)) { + unknown_command(); + return; + } + if (check_badpoke()) return; + if (ishex(sci_rx_buf[4]) && ishex(sci_rx_buf[5]) && ishex(sci_rx_buf[6]) && + ishex(sci_rx_buf[7]) && ishex(sci_rx_buf[8]) && ishex(sci_rx_buf[9]) + && sci_rx_buf[10] == '\0') { + u16 v; + v = hex2addr((char*)(sci_rx_buf+4)); + *(u8*)v = hex2u8(sci_rx_buf[8], sci_rx_buf[9]); + send_string("080 Written." CRLF); + return; + } + send_string("081 Invalid location or byte given." CRLF); +} + +void jump() { + if (!my_strncmp("UMP", (char*)sci_rx_buf+1, 3)) { + unknown_command(); + return; + } + if (check_badpoke()) return; + if (ishex(sci_rx_buf[4]) && ishex(sci_rx_buf[5]) && ishex(sci_rx_buf[6]) && + ishex(sci_rx_buf[7]) && sci_rx_buf[8] == '\0') { + u16 v = hex2addr((char*)(sci_rx_buf+4)); + send_string("070 Jumping now." CRLF); + asm volatile ("jsr %0" : : "m"(*(u16*)v) : "d"); + send_string("071 And back." CRLF); + return; + } + send_string("079 Invalid location given." CRLF); +} + +void do_set_password() { + u8 i; + bool good = 1; + if (check_badpoke()) return; + for (i=1; i < 17; i++) { + if (sci_rx_buf[i] == '\0') { + good = 0; + break; + } + } + if (good && sci_rx_buf[17] != '\0') good = 0; + if (!good) { + send_string("061 Password must be exactly 16 characters." CRLF); + return; + } + + mic_set_secret((char*)(sci_rx_buf+1)); + send_string("060 Password has been set." CRLF); +} + void send_prompt() { - send_string(is_standalone()?"$ ":"# "); + if (must_verify()) { + send_string(u82hex(mic_challenge >> 8)); + send_string(u82hex(mic_challenge & 0xff)); + } + send_string(is_standalone()?"% ":"# "); } void about() { @@ -244,19 +368,18 @@ void about() { return; } send_string( - "-----------------------------------------------------------------" CRLF - " ROM2 (C) 2004 Bernard Blackham " CRLF - "-----------------------------------------------------------------" CRLF - " Revision " VERSION_STRING CRLF - "" CRLF + CRLF + " ROM2 (C) 2004 Bernard Blackham " CRLF + " Revision: " VERSION_STRING " Built: " DATEBUILT_STRING CRLF "" CRLF CRLF " This snack machine was brought to you by " CRLF " Bernard Blackham" CRLF - " Mark Tearle" CRLF " Harry McNally" CRLF + " Mark Tearle" CRLF " Michal Gornisiewicz" CRLF + " Nick Bannon" CRLF " and others." CRLF "" CRLF - " Another UCC project in action. http://www.ucc.asn.au/" CRLF + " Another UCC project in action. http://www.ucc.asn.au/" CRLF ); } @@ -296,20 +419,38 @@ void moo() { ); } +void identify() { + send_string( + "086 ROM " VERSION_STRING " " DATEBUILT_STRING CRLF + ); +} + void help() { send_string( "Valid commands are:" CRLF " ABOUT ROM information" CRLF - " PING pongs" CRLF + " B[S][nn] beep [synchronously] for a duration nn (optional)" CRLF + " C[S][nn] silence [synchronously] for a duration nn (optional)" CRLF + " Dxxxxxxxxxx show a message on the display" CRLF " ECHO {ON|OFF} turn echo on or off" CRLF - " Vnn vend an item" CRLF - " VALL vend all items" CRLF - " DXXXXXXXXXX show a message on the display" CRLF - " B[nn] beep for a duration nn (optional)" CRLF - " S[...] query all internal switch states" CRLF - " H[...] this help screen" CRLF " GETROM download the ROM source code using xmodem" CRLF - "Comments start with a #" CRLF + " H[...] this help screen" CRLF + " IDENTIFY report ROM version" CRLF + "*JUMPxxxx jumps to a subroutine at location xxxx" CRLF + "*PEEKxxxx returns the value of the byte at location xxxx" CRLF + "*POKExxxxyy sets the value of location xxxx to yy" CRLF + " PING pongs" CRLF + " S[...] query all internal switch states" CRLF + "+Vnn vend an item" CRLF + "+VALL vend all items" CRLF + "*Wxxxxxxxxxxxx set a new password for authenticated vends. xxx=16 chars" CRLF + " password will be converted to uppercase" CRLF + "" CRLF + "Very few functions are available when the machine is in standalone " CRLF + "mode (DIP SW 1 is set)" CRLF + "+ denotes that this item requires authentication if DIP SW 2 is set" CRLF + "* denotes that DIP SW 3 must be set to use these" CRLF + "Commands starting with # are ignored (comments)" CRLF ); } @@ -321,19 +462,29 @@ void getrom() { return; } char s[4]; + + u16 rom_addr; + rom_addr = (u16)(&_rom_src_data); + send_string("Writing to serial port (maybe). Size is 0x"); send_string(u82hex(_rom_src_len >> 8)); send_string(u82hex(_rom_src_len & 0xff)); + send_string("@0x"); + send_string(u82hex(rom_addr >> 8)); + send_string(u82hex(rom_addr & 0xff)); send_string(" with signature "); s[0] = _rom_src_data[0]; s[1] = _rom_src_data[1]; s[2] = _rom_src_data[2]; s[3] = '\0'; send_string(s); - send_string(CRLF " Type YES to download rom.tar.bz2 via XMODEM: "); + send_string(CRLF " Type YES to download rom.tar.lz via XMODEM: "); msg_clr(); while (!sci_have_packet); /* spin */ - if (!my_strncmp("YES", (char*)sci_rx_buf, 3)) return; + if (!my_strncmp("YES", (char*)sci_rx_buf, 3)) { + send_string(CRLF "Transfer cancelled." CRLF); + return; + } sci_init(); sci_doing_xmodem = 1; @@ -346,16 +497,19 @@ void getrom() { char *end = (char*)_rom_src_data+_rom_src_len; bool aborted = 0; while (1) { - if (!xmodem_send_packet((char*)p, 128)) { - aborted = 1; - break; - } - p += 128; if (p + 128 > end) { /* send partial packet */ if (!xmodem_send_packet((char*)p, end-p)) aborted = 1; break; + } if ((u16)p == 0xb600) { + /* we have an eeprom here. skip it. */ + p += 0x0200; + continue; + } else if (!xmodem_send_packet((char*)p, 128)) { + aborted = 1; + break; } + p += 128; } xmodem_finish_xfer(); @@ -373,9 +527,6 @@ void quit() { unknown_command(); } -//SHA1_CTX ctx; -//u8 sha1_digest[SHA1_SIGNATURE_SIZE]; - int main() { u8 i; for (i = 0; i < 11; i++) @@ -397,7 +548,6 @@ int main() { set_msg(" CRUEL "); - //comm_init(); //coinmech_init(); sci_init(); keypad_init(); @@ -412,7 +562,7 @@ int main() { chime_start(); send_string("5N4X0RZ R US" CRLF); - + last_standalone = is_standalone(); if (last_standalone) cur_motor[0] = 0xff; @@ -433,7 +583,8 @@ int main() { last_door_open = door_open(); send_door_msg(last_door_open); chime_start(); - set_msg(last_door_open?"DOOR OPEN ":"DOOR CLOSE"); + if (is_standalone()) + set_msg(last_door_open?"DOOR OPEN ":"DOOR CLOSE"); } if (last_standalone != is_standalone()) { @@ -455,48 +606,61 @@ int main() { } if (sci_have_packet) { - if (must_verify()) { - //SHA1_Init(&ctx); - //SHA1_Update(&ctx, sci_rx_buf, my_strlen(sci_rx_buf)); - //SHA1_Final(sha1_digest, &ctx); - } + send_string(CRLF); switch (sci_rx_buf[0]) { case '\0': case '#': send_string(CRLF); break; - case 'E': - set_echo(); + case 'A': + about(); break; - case 'H': - help(); + case 'B': + do_chime(); break; - case 'V': - dispense_something(); + case 'C': + do_silence(); break; case 'D': write_to_display(); break; - case 'B': - do_chime(); + case 'E': + set_echo(); break; - case 'P': - ping_pong(); + case 'G': + getrom(); break; - case 'A': - about(); + case 'H': + help(); break; - case 'S': - print_switches(1); + case 'I': + identify(); break; case 'M': moo(); break; + case 'P': + if (sci_rx_buf[1] == 'I') + ping_pong(); + else if (sci_rx_buf[1] == 'O') + poke(); + else if (sci_rx_buf[1] == 'E') + peek(); + break; + case 'J': + jump(); + break; case 'Q': quit(); break; - case 'G': - getrom(); + case 'S': + print_switches(1); + break; + case 'V': + dispense_something(); + break; + case 'W': + do_set_password(); break; default: // shurg @@ -552,6 +716,7 @@ int main() { } } else send_keypress(last_key); + send_timer(); } /*