/* ss-hw/pressure.c * * Pressure sensor functions. * * Copyright (C) 2003, 2004 * Andy Goth * * This code is available under the GNU General Public License; see COPYING. */ #include #include #include #include "evlist/evlist.h" #include "prjlibs/vec.h" #include "ss-hw/pressure.h" #define BUF VEC_ELTS(byte_t, &dev->buf_in) #define PACKET_LEN 13 #define PACKET_DELIM "\r\n>" typedef struct pressure { device_t* user; int state; int doors; } pressure_t; static int pressure_cleanup (device_t* dev); static int pressure_open (device_t* dev); static int pressure_incoming(device_t* dev); int pressure_init(device_t* dev, device_t* user) { pressure_t* state = malloc(sizeof(pressure_t)); if (state == NULL) return -1; state->user = user; dev->sw_state = state ; dev->buf_size = PACKET_LEN ; dev->sw_cleanup = pressure_cleanup ; dev->sw_open = pressure_open ; dev->sw_incoming = pressure_incoming; return 0; } static int pressure_cleanup(device_t* dev) { free(dev->sw_state); dev->buf_size = 0 ; dev->sw_state = NULL; dev->sw_cleanup = NULL; dev->sw_open = NULL; dev->sw_incoming = NULL; return 0; } static int pressure_open(device_t* dev) { ((pressure_t*)dev->sw_state)->state = 0; ((pressure_t*)dev->sw_state)->doors = 4; return 0; } static int pressure_incoming(device_t* dev) { /* BUF[ 0 1 2 3456 789a b c ] * Packet format: \r\n> aaaa aaaa d d * `-.-' |||| | * | |||| `- door sensors * | |||`---------- pressure sensor 4 * | ||`----------- pressure sensor 3 * | |`------------ pressure sensor 2 * | `------------- pressure sensor 1 * `----------------- framing marker (3 bytes) * *state: * 0 - out of sync 2 - found \n * 1 - found \r 3 - in sync * *doors: * 0 - no doors open 2 - right door open 4 - uninitialized * 1 - left door open 3 - both doors open */ int i; int cursor = 0; pressure_t* pressure = dev->sw_state; int* state = &pressure->state; if (VEC_LEN(byte_t, &dev->buf_in) != PACKET_LEN) { /* Not a full buffer... try again later. */ return 0; } if (*state == 3) { if (strncmp(BUF, PACKET_DELIM, 3) != 0) { /* Lost sync... :^( */ *state = 0; } else { /* Still have sync. */ goto have_sync; } } /* Attempt to resync. */ for (i = 0; i < PACKET_LEN; ++i) { if (BUF[i] == PACKET_DELIM[*state]) { /* Possible sync. */ ++*state; if (*state == 3) { /* Sync success. Realign data. */ i -= 2; if (i > 0) { /* Discard junk data at start of buffer. */ VEC_SHIFTN(byte_t, &dev->buf_in, i); return 0; } else if (i < 0) { /* Place delimiter at start of buffer. */ VEC_POPN(byte_t, &dev->buf_in, -i); VEC_UNSHIFTN(byte_t, &dev->buf_in, PACKET_DELIM, -i); cursor = -i; } goto have_sync; } } else { /* Sync failure. Maybe next byte? */ *state = 0; } } /* Sync failure. Discard buffer. Try again next packet. */ VEC_TRUNC(byte_t, &dev->buf_in, 0); return 0; have_sync: /* Good data. */ user_send_pressure(pressure->user, BUF[3], BUF[4], BUF[5], BUF[6]); if (pressure->doors != (BUF[12] & 3)) { /* Door change. */ pressure->doors = BUF[12] & 3; user_send_doors(pressure->user, (BUF[12] & 2) ? 1 : 0, (BUF[12] & 1) ? 1 : 0); } VEC_TRUNC(byte_t, &dev->buf_in, cursor); return 0; } /* vim: set ts=4 sts=4 sw=4 tw=80 et: */