diff --git a/include/fifo.h b/include/fifo.h index 42a90a5..8baf0fa 100644 --- a/include/fifo.h +++ b/include/fifo.h @@ -9,7 +9,7 @@ struct fifo { uint16_t pdc_tx; uint16_t pdc_rx; - + uint32_t size; char buf[0]; }; @@ -23,6 +23,8 @@ uint32_t fifo_txpdc(struct fifo *fifo, AT91S_PDC *pdc, uint16_t maxsize); uint32_t fifo_putbyte(struct fifo *fifo, char c); uint32_t fifo_getbyte(struct fifo *fifo, char *p); +char * fifo_peek(struct fifo *fifo, uint32_t len); + struct fifo * fifo_alloc(uint32_t size); #endif /*FIFO_H_*/ diff --git a/include/telemetrie.h b/include/telemetrie.h index 26d07dd..a72a19e 100644 --- a/include/telemetrie.h +++ b/include/telemetrie.h @@ -48,7 +48,7 @@ struct tdc_getvars_reply { uint8_t size; uint8_t id; // variable ID (max 256 vars / board) uint32_t flags; // variable parameters (type, size, ro/rw) - uint8_t name[0]; // variable name, excluding '\0' + char name[0]; // variable name, excluding '\0' } __attribute__ ((packed)); struct tdc_getvalue_request { @@ -87,8 +87,8 @@ struct tdc_reqvalues_reply { struct tdc_value { - const void *ptr; - const uint8_t *name; + void *data; + const char *name; uint32_t flags; }; diff --git a/src/fifo.c b/src/fifo.c index 63a8263..a17584b 100644 --- a/src/fifo.c +++ b/src/fifo.c @@ -16,6 +16,7 @@ * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +#include #include "AT91SAM7S256.h" #include "atomic.h" #include "fifo.h" @@ -45,6 +46,7 @@ static uint32_t fifo_used(struct fifo *fifo) uint32_t fifo_put(struct fifo *fifo, const char *buf, uint32_t len) { uint32_t left = fifo->size - fifo_used(fifo); + // TODO: check semantic if (len > left) len = left; @@ -72,6 +74,19 @@ uint32_t fifo_get(struct fifo *fifo, char *buf, uint32_t len) return len; } +/* + * returns a pointer to the data in the fifo + * (without changing internal state) + */ +char * fifo_peek(struct fifo *fifo, uint32_t len) +{ + uint32_t used = fifo_used(fifo); + if (len > used) + return NULL; + + return fifo->buf + (fifo->out & FIFO_MASK(fifo)); +} + /* * receive data via PDC and put it into fifo */ diff --git a/src/telemetrie.c b/src/telemetrie.c index 5ce39e1..4860673 100644 --- a/src/telemetrie.c +++ b/src/telemetrie.c @@ -27,12 +27,18 @@ extern struct tdc_value _tdc_value_table; extern struct tdc_value _tdc_value_table_end; -typedef uint32_t (txfunc_t)(const uint8_t *data, uint32_t size); +/* + * transmit function + * returns: + * -1 : could not sent data (e.g. fifo full) + * >= 0 : bytes sent + */ +typedef uint32_t (txfunc_t)(struct tdc_pkt_header *head); /* just eat the packet */ -static uint32_t txdummy(const uint8_t *data, uint32_t size) +static uint32_t txdummy(struct tdc_pkt_header *head) { - return -1; + return head->size; } /* table of txfuncs for routing/forwarding */ @@ -53,88 +59,84 @@ void tdc_register_txfunc(uint32_t addr, txfunc_t *txfunc) transmit_table[addr] = txfunc; } -int32_t tdc_transmit(uint32_t addr, const uint8_t *data, uint32_t size) +int32_t tdc_transmit(uint32_t addr, struct tdc_pkt_header *head) { if (addr <= ARRAY_SIZE(transmit_table)) - return transmit_table[addr](data, size); + return transmit_table[addr](head); return -1; } /* -void *blub = NULL; -func(&blub); -*/ -int32_t tdc_get_vars(void **privdata) + * send all variable names & flags + * returns: + * 0 - success (*id = 0) + * -1 - not all data was sent, restart request later (*id has restart-point) + */ +int32_t tdc_get_vars(uint32_t *id) { - struct tdc_value **value = (struct tdc_value **)privdata; + struct tdc_value *value = &_tdc_value_table + *id; - if (*value == NULL) - *value = &_tdc_value_table; - - uint32_t id = (*value - &_tdc_value_table) / sizeof(struct tdc_value); - - while (*value < &_tdc_value_table_end) { - uint32_t datalen = strlen((*value)->name); + while (value < &_tdc_value_table_end) { + uint32_t datalen = strlen(value->name); struct tdc_getvars_reply *reply = alloc(sizeof(struct tdc_getvars_reply) + datalen); reply->cmd = TDC_REPLY | TDC_ADDR1 | TDC_GETVARS; reply->size = sizeof(struct tdc_getvars_reply) + datalen; - reply->id = id; - reply->flags = (*value)->flags; - memcpy(reply->name, (*value)->name, datalen); + reply->id = *id; + reply->flags = value->flags; + memcpy(reply->name, value->name, datalen); - int32_t ret = transmit_table[TDC_ADDR0]((const uint8_t *)reply, reply->size); + uint32_t txerror = (tdc_transmit(TDC_ADDR0, ((struct tdc_pkt_header *)reply)) != reply->size); free(reply); - if (ret != reply->size) + /* transmit fifo is full, remember position (*id) and restart */ + if (txerror) return -1; - id++; - (*value)++; + (*id)++; + value++; } - - /* TODO: all done */ - (*value) = NULL; + *id = 0; return 0; } -#if 0 - -static int32_t tdc_get_values(uint8_t *buf, uint32_t size, void **key) +int32_t tdc_get_value(uint32_t id) { - if (*key == NULL) - *key = &_tdc_value_table; + struct tdc_value *value = &_tdc_value_table + id; + uint32_t datalen = value->flags & TDC_SIZEMASK; - uint32_t id = (*key - &_tdc_value_table) / sizeof(struct tdc_value); - uint32_t pos = 0; + struct tdc_getvalue_reply *reply = alloc(sizeof(struct tdc_getvalue_reply) + datalen); + reply->cmd = TDC_REPLY | TDC_ADDR1 | TDC_GETVALUE; + reply->size = sizeof(struct tdc_getvars_reply) + datalen; + reply->id = id; + memcpy(reply->data, value->data, datalen); - while (*key < &_tdc_value_table_end) { - struct tdc_value *tmp = (struct tdc_value *)*key; - uint32_t datalen = (tmp->flags & TDC_SIZEMASK); + int32_t txerror = (tdc_transmit(TDC_ADDR0, ((struct tdc_pkt_header *)reply)) != reply->size); + free(reply); - /* fits in buffer? */ - if ((size - pos) < (2 + 1 + datalen)) - return (pos > 0) ? pos : -1; - - buf[pos++] = TDC_VALUEOP; - buf[pos++] = 1 + datalen; - buf[pos++] = id++; - - memcpy(buf + pos, tmp->ptr, datalen); - pos += datalen; - - *key += sizeof(struct tdc_value); - } - return pos; + return (txerror) ? -1 : 0; +} + +void tdc_set_value(uint32_t id, uint8_t *data) +{ + struct tdc_value *value = &_tdc_value_table + id; + uint32_t datalen = value->flags & TDC_SIZEMASK; + + // TODO: atomic? + memcpy(value->data, data, datalen); } -#endif /* * parses tdc data + * returns: + * -1 : data too short / error + * >= 0 : data read, come back if there is more */ int32_t tdc_parse_pkt(txfunc_t *txfunc, const uint8_t *data, uint32_t size) { + // TODO: use a fifo, with a peek function? + struct tdc_pkt_header *head = (struct tdc_pkt_header *)data; if (size < sizeof(struct tdc_pkt_header)) @@ -142,41 +144,55 @@ int32_t tdc_parse_pkt(txfunc_t *txfunc, const uint8_t *data, uint32_t size) /* if it's a hello-request, remember the txfunc as path to the host */ if ((head->cmd & (TDC_OPCODEMASK & TDC_DIR)) == TDC_HELLO) - transmit_table[TDC_ADDR0] = txfunc; + tdc_register_txfunc(TDC_ADDR0, txfunc); /* all replys go to the HOST */ if (head->cmd & TDC_REPLY) { - return transmit_table[TDC_ADDR0](data, head->size); + // TODO: wrong returncode + return tdc_transmit(TDC_ADDR0, head); } /* forward this packet? */ if ((head->cmd & TDC_ADDRMASK) != TDC_ADDR1) { uint32_t addr = (head->cmd & TDC_ADDRMASK) >> 4; - return transmit_table[addr](data, head->size); + // TODO: wrong returncode + return tdc_transmit(addr, head); } /* parse the packet */ switch (head->cmd & TDC_OPCODEMASK) { /* HELLO from HOST */ case TDC_HELLO: - transmit_table[TDC_ADDR0]((const uint8_t *)&hello_reply, sizeof(hello_reply)); + tdc_transmit(TDC_ADDR0, (struct tdc_pkt_header *)&hello_reply); break; - case TDC_GETVARS: - // TODO: exec func - break; + case TDC_GETVARS: { + static uint32_t i; - case TDC_GETVALUE: - // TODO: exec func - break; + /* tx-fifo is full, complete request later */ + if (tdc_get_vars(&i) == -1) + return 0; - case TDC_SETVALUE: - // TODO: exec func - break; + } break; - case TDC_REQVALUES: - // TODO: exec func - break; + case TDC_GETVALUE: { + struct tdc_getvalue_request *pkt = (struct tdc_getvalue_request *)data; + + /* tx-fifo is full, retry request later */ + if (tdc_get_value(pkt->id) == -1) + return 0; + + } break; + + case TDC_SETVALUE: { + struct tdc_setvalue_request *pkt = (struct tdc_setvalue_request *)data; + tdc_set_value(pkt->id, pkt->data); + } break; + + case TDC_REQVALUES: { + struct tdc_reqvalues_request *pkt = (struct tdc_reqvalues_request *)data; + + } break; case TDC_TERMINAL: // TODO: not possible?