Statistics
| Branch: | Revision:

root / toolbox / main.c @ 10936c07

History | View | Annotate | Download (5.99 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

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

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

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

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

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

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

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

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

    
61
static void tool_main() {
62

    
63
  switch (toolstate) {
64

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

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

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

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

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

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

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

    
152
  }
153

    
154
}
155

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

    
159
  addr--;
160

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

    
165
  if (mode == MB_REG_WRITE) {
166

    
167
    switch (addr) {
168

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

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

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

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

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

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

    
208
  }
209

    
210
  return MB_EIO;
211
}
212

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

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

    
219
  addr--;
220

    
221
  switch (addr) {
222

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

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

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

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

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

    
263
int main() {
264

    
265
  led_init();
266
  tool_init();
267
  rfid_init();
268

    
269
  eMBInit(MB_RTU, SLAVE_ADDR, 0, MB_BAUD, MB_PAR_NONE);
270
  eMBEnable();
271

    
272
  sei();
273

    
274
  rfid_start_read();
275
  while (1) {
276
    if (rfid_poll()) {
277
      rfid_get_serno(latest_reading);
278
      rfid_start_read();
279
    }
280
    current = current_read();
281
    tool_main();
282
    eMBPoll();
283
    _delay_ms(100);
284
  }
285

    
286
  return 0;
287
}