More coin mech code
[uccvend-snackrom.git] / ROM2 / coinmech.c
1 #include "coinmech.h"
2 #include "vend.h"
3
4 #define COINMECH_ID   0x20
5
6 u8 last_byte;
7 u8 packet_pos = 0;
8 u16 value_1 = 0;
9 u8 value_2 = 0;
10 u8 dec_point = 0; 
11
12 u16 coin_value = 0;
13 u8 item_cost = 0;
14 bool have_change = 0;
15
16 u8 parity_test(u8 c) {
17         u8 parity = 0;
18         for (parity = 0; c; c = c>>1) {
19                 if (c&1) parity = !parity;
20         }
21         return parity;
22 }
23
24 bool parity_good(u8 c) {
25
26 /*
27  * parity_good truth table:
28  *
29  *      | parity_test(c)
30  *      | 0   1
31  * -----+---------
32  * R8 0 | 1   0
33  *    1 | 0   1
34  */
35
36         u8 R8 = (_io_ports[M6811_SCCR1] & M6811_R8)?1:0;
37         u8 p = parity_test(c)?1:0;
38         return R8 == p;
39 }
40
41 void send_byte(u8 c) {
42         last_byte = c;
43         while (!(_io_ports[M6811_SCSR] & M6811_TDRE)); /* wait for TD register empty */
44
45         if (parity_test(c))
46                 bset((void*)&_io_ports[M6811_SCCR1], M6811_T8);
47         else
48                 bclr((void*)&_io_ports[M6811_SCCR1], M6811_T8);
49 }
50
51 void ask_for_retrans() {
52         /* sends an 0xff down the line */
53         send_byte(0xff);
54 }
55
56
57 #define IS_CTRL(x) (x & 0x10) /* true if this packet is a control packet */
58 void sci_interrupt() {
59         u8 in;
60         in = _io_ports[M6811_SCDR];
61         
62         /* test for framing errors & parity bit */
63         if (_io_ports[M6811_SCSR] & M6811_FE || !parity_good(in)) {
64                 _io_ports[M6811_SCDR]; /* read of register req'd to clear FE */
65                 ask_for_retrans();
66                 return;
67         }
68
69         /* all bytes must have the correct ID in the 3 MSBs */
70         if ((in & 0xe0) != COINMECH_ID) return;
71
72         /* we have a good packet */
73         if (in == 0x3f) {
74                 /* retransmit was requested */
75                 send_byte(last_byte);
76                 return;
77         }
78
79         if (packet_pos != 0 || IS_CTRL(in&0x10)) {
80                 in &= 0x0f;
81                 switch (in) {
82                         case 0x01: 
83                                 /* just reply with ack */
84                                 /* original firmware does something with link master price holding */
85                                 send_byte(0x00);
86                         case 0x02:
87                                 /* write back how much change to give, or 0xfe to hold it. */
88                                 if (item_cost) {
89                                         send_byte(item_cost / value_2);
90                                 } else
91                                         send_byte(0xfe);
92                                 break;
93                         case 0x03:
94                                 /* hmmm, maybe we're sposed to do something here. firmware doesnt */
95                                 /* and just sets a random bit - something like "changer in use"?  */
96                                 break;
97                         case 0x08:
98                                 /* start of packet */
99                                 packet_pos = 1;
100                                 send_byte(0x00);
101                                 break;
102                         default:
103                                 /* just ack it and move on */
104                                 send_byte(0x00);
105                 }
106         } else {
107                 in &= 0x0f;
108                 switch (packet_pos) {
109                         case 1: value_1  = in;           break;
110                         case 2: value_1 |= in << 4;      break;
111                         case 3: value_1 |= in << 8;      break;
112                         case 4: value_1 |= in << 12;     break;
113                         case 5: value_2  = in;           break;
114                         case 6: value_2 |= in << 4;      break;
115                         case 7: dec_point = in;          break;
116                         case 8: have_change = (in&0x01); break;
117                         default:
118                                         if (packet_pos == 9) {
119                                                 packet_pos = 0;
120                                                 coin_value = value_1*value_2;
121                                         }
122                                         /* hmmm, else? */
123                 }
124                 packet_pos++;
125                 send_byte(0x00); /* ack */
126         }
127 }
128
129 void coin_eat() {
130         coin_cost(coin_value); /* eat everything */
131 }
132
133 void coin_cost(u16 cost) {
134         item_cost = cost;
135 }

UCC git Repository :: git.ucc.asn.au