Statistics
| Branch: | Revision:

root / toolbox / main.c @ 94548bf4

History | View | Annotate | Download (6.28 KB)

1
#include <stdint.h>
2
#include <string.h>
3
#include <avr/io.h>
4
#include <util/delay.h>
5
#include "mb.h"
6
#include "mbport.h"
7
#include "tooltron_mb.h"
8
#include "rfid.h"
9
#include "led.h"
10
#include "current.h"
11
#include "time.h"
12

    
13
enum toolstate_t {
14
  TS_INIT,
15
  TS_OFF,
16
  TS_WAIT_ACCESS,
17
  TS_DENY,
18
  TS_REQ_DIS,
19
  TS_MISSING_ID,
20
  TS_ON
21
};
22

    
23
static enum toolstate_t toolstate = TS_INIT;
24
static uint8_t coils;
25
static uint8_t latest_reading[RFID_SERNO_SIZE];
26
static uint8_t current_user[RFID_SERNO_SIZE];
27
static uint16_t current;
28

    
29
static inline void set_coil(char coil, char bit) {
30
  coils = (coils & ~(1 << coil)) | (bit << coil);
31
}
32
static inline char get_coil(char coil) {
33
  return (coils >> coil) & 1;
34
}
35

    
36
static inline void tool_init() {DDRA |= _BV(DDA1);}
37
static inline void tool_enable() {PORTA |= _BV(PA1);}
38
static inline void tool_disable() {PORTA &= ~ _BV(PA1);}
39

    
40
static inline void serno_zero(uint8_t *serno) {
41
  memset(serno, 0, RFID_SERNO_SIZE);
42
}
43

    
44
static char serno_is_nonzero(uint8_t *serno) {
45
  int i;
46
  for (i = 0; i < RFID_SERNO_SIZE; i++) {
47
    if (serno[i]) {
48
      return 1;
49
    }
50
  }
51
  return 0;
52
}
53

    
54
static char serno_equal(uint8_t *a, uint8_t *b) {
55
  return memcmp(a, b, RFID_SERNO_SIZE) == 0;
56
}
57

    
58
static void serno_cpy(uint8_t *dest, uint8_t *src) {
59
  memcpy(dest, src, RFID_SERNO_SIZE);
60
}
61

    
62
static void tool_tick() {
63

    
64
  switch (toolstate) {
65

    
66
    case TS_INIT:
67
      if (get_coil(MB_COIL_INIT)) {
68
        set_coil(MB_COIL_NEW, 0);
69
        set_coil(MB_COIL_EN, 0);
70
        set_coil(MB_COIL_REQ_DIS, 0);
71
        toolstate = TS_OFF;
72
      }
73
      break;
74

    
75
    case TS_OFF:
76
      led_off();
77
      set_coil(MB_COIL_EN, 0);
78
      if (serno_is_nonzero(latest_reading)) {
79
        serno_cpy(current_user, latest_reading);
80
        set_coil(MB_COIL_NEW, 1);
81
        toolstate = TS_WAIT_ACCESS;
82
      }
83
      break;
84

    
85
    case TS_WAIT_ACCESS:
86
      led_yellow();
87
      if (get_coil(MB_COIL_EN)) {
88
        tool_enable();
89
        toolstate = TS_ON;
90
      } else if (!get_coil(MB_COIL_NEW)) {
91
        toolstate = TS_DENY;
92
      } else if (!serno_equal(current_user, latest_reading)) {
93
        set_coil(MB_COIL_NEW, 0);
94
        toolstate = TS_OFF;
95
      }
96
      break;
97

    
98
    case TS_DENY:
99
      led_red();
100
      if (!serno_equal(current_user, latest_reading)) {
101
        toolstate = TS_OFF;
102
        serno_zero(current_user);
103
      }
104

    
105
    case TS_REQ_DIS:
106
      if (!get_coil(MB_COIL_EN)) {
107
        tool_disable();
108
        toolstate = TS_OFF;
109
      } else if (!get_coil(MB_COIL_REQ_DIS)) {
110
        toolstate = TS_ON;
111
      } else {
112
        // TODO blink yellow for 10 seconds or something
113
        set_coil(MB_COIL_EN, 0);
114
        set_coil(MB_COIL_REQ_DIS, 0);
115
        tool_disable();
116
        serno_zero(current_user);
117
        toolstate = TS_OFF;
118
      }
119
      break;
120

    
121
    case TS_MISSING_ID:
122
      if (!get_coil(MB_COIL_EN)) {
123
        tool_disable();
124
        toolstate = TS_OFF;
125
      } else if (get_coil(MB_COIL_REQ_DIS)) {
126
        toolstate = TS_REQ_DIS;
127
      } else if (serno_equal(current_user, latest_reading)) {
128
        toolstate = TS_ON;
129
      } else {
130
        if (led_blink_done()) {
131
          set_coil(MB_COIL_EN, 0);
132
          tool_disable();
133
          serno_zero(current_user);
134
          toolstate = TS_OFF;
135
        }
136
      }
137
      break;
138

    
139
    case TS_ON:
140
      led_green();
141
      if (!get_coil(MB_COIL_EN)) {
142
        tool_disable();
143
        serno_zero(current_user);
144
        toolstate = TS_OFF;
145
      } else if(get_coil(MB_COIL_REQ_DIS)) {
146
        toolstate = TS_REQ_DIS;
147
      } else if (!serno_equal(current_user, latest_reading)) {
148
        toolstate = TS_MISSING_ID;
149
        led_blink_start(666, 15, YELLOW);
150
      }
151
      break;
152

    
153
  }
154

    
155
}
156

    
157
eMBErrorCode eMBRegCoilsCB(UCHAR *reg_buf, USHORT addr, USHORT n_coils,
158
    eMBRegisterMode mode) {
159

    
160
  addr--;
161

    
162
  if (addr+n_coils > N_COILS) {
163
    return MB_ENOREG;
164
  }
165

    
166
  if (mode == MB_REG_WRITE) {
167

    
168
    switch (addr) {
169

    
170
      case MB_COIL_NEW:
171
        /* nop */
172
        reg_buf[0] >>= 1;
173
        n_coils--;
174
        if (n_coils == 0) {
175
          return MB_ENOERR;
176
        }
177

    
178
      case MB_COIL_EN:
179
        set_coil(MB_COIL_NEW, 0);
180
        set_coil(MB_COIL_EN, reg_buf[0] & 1);
181
        reg_buf[0] >>= 1;
182
        n_coils--;
183
        if (n_coils == 0) {
184
          return MB_ENOERR;
185
        }
186

    
187
      case MB_COIL_REQ_DIS:
188
        set_coil(MB_COIL_REQ_DIS, reg_buf[0] & 1);
189
        reg_buf[0] >>= 1;
190
        n_coils--;
191
        if (n_coils == 0) {
192
          return MB_ENOERR;
193
        }
194

    
195
      case MB_COIL_INIT:
196
        set_coil(MB_COIL_INIT, reg_buf[0] & 1);
197
        reg_buf[0] >>= 1;
198
        n_coils--;
199
        if (n_coils == 0) {
200
          return MB_ENOERR;
201
        }
202
    }
203

    
204
  } else if (mode == MB_REG_READ) {
205

    
206
    reg_buf[0] = (coils >> addr) & ((1 << n_coils) - 1);
207
    return MB_ENOERR;
208

    
209
  }
210

    
211
  return MB_EIO;
212
}
213

    
214
eMBErrorCode eMBRegDiscreteCB(UCHAR *reg_buf, USHORT addr, USHORT n_coils) {
215
  return MB_ENOREG;
216
}
217

    
218
eMBErrorCode eMBRegInputCB(UCHAR *reg_buf, USHORT addr, USHORT n_regs) {
219

    
220
  addr--;
221

    
222
  switch (addr) {
223

    
224
    case MB_INP_SERNOL:
225
      *reg_buf++ = current_user[0];
226
      *reg_buf++ = current_user[1];
227
      n_regs--;
228
      if (n_regs == 0) {
229
        return MB_ENOERR;
230
      }
231

    
232
    case MB_INP_SERNOH:
233
      *reg_buf++ = current_user[2];
234
      *reg_buf++ = current_user[3];
235
      n_regs--;
236
      if (n_regs == 0) {
237
        return MB_ENOERR;
238
      }
239

    
240
    case MB_INP_CURRENT:
241
      *reg_buf++ = (uint8_t)(current >> 8);
242
      *reg_buf++ = (uint8_t)current;
243
      n_regs--;
244
      if (n_regs == 0) {
245
        return MB_ENOERR;
246
      }
247

    
248
    default:
249
      return MB_ENOREG;
250
  }
251
}
252

    
253
eMBErrorCode eMBRegHoldingCB(UCHAR *reg_buf, USHORT addr, USHORT n_regs,
254
    eMBRegisterMode mode) {
255
  if (mode == MB_REG_WRITE) {
256
    return MB_ENOREG;
257
  } else if (mode == MB_REG_READ) {
258
    return MB_ENOREG;
259
  } else {
260
    return MB_EIO;
261
  }
262
}
263

    
264
int main() {
265
  char rfid_ticks = 0;
266

    
267
  time_init();
268
  led_init();
269
  tool_init();
270
  rfid_init();
271
  current_init();
272

    
273
  eMBInit(MB_RTU, SLAVE_ADDR, 0, MB_BAUD, MB_PAR_NONE);
274
  eMBEnable();
275

    
276
  sei();
277

    
278
  rfid_start_read();
279
  while (1) {
280
    if (++rfid_ticks >= RFID_PERIOD/TICK_MS)
281
    {
282
      rfid_ticks = 0;
283
      if (rfid_poll()) {
284
        rfid_get_serno(latest_reading);
285
        rfid_start_read();
286
      } else {
287
        /* TODO count # times rfid_poll returns each value and see how often we
288
         * have to wait */
289
      }
290
    }
291
    current = current_read();
292
    tool_tick();
293
    led_tick();
294
    eMBPoll();
295
    time_wait();
296
  }
297

    
298
  return 0;
299
}