/* Many XMOS apps may call xmos_flash_init() without ever using the * XMOS flash device. We prevent the creation of many unused large files * by creating the flash emulation file only once it is actually used. */ static void lazyInit() { mos_mutex_lock (&xmos_flash_mutex); // check for race condition if (flash_file) return; // See if the flash file exists if (access(flash_file_name, F_OK)) { // write a bunch of zeros to the new file flash_file = fopen(flash_file_name, "w"); fseek(flash_file, 0, SEEK_SET); void* buf = calloc(1, flash_size); fwrite(buf, 1, flash_size, flash_file); fflush(flash_file); free(buf); fclose(flash_file); } flash_file = fopen(flash_file_name, "r+"); if (!flash_file) { perror("xmos_flash_init: fopen"); mos_mutex_unlock (&xmos_flash_mutex); return; } mos_mutex_unlock (&xmos_flash_mutex); }
uint8_t dev_ioctl_DEV_ATMEL_FLASH (int8_t request, ...) { if (!flash_file_name) return DEV_NOT_REGISTERED; if (!flash_file) lazyInit(); uint32_t arg; va_list ap; mos_mutex_lock (&xmos_flash_mutex); va_start (ap, request); switch (request) { case DEV_SEEK: arg = va_arg (ap, uint32_t); xmos_flash_addr = arg; //printf("xmos_flash_addr = %i;\n", xmos_flash_addr); break; default: return DEV_BAD_IOCTL; } va_end (ap); mos_mutex_unlock (&xmos_flash_mutex); return DEV_OK; }
/** @brief Set some protocol specific parameters. * @param request IO request * @param args Arguements */ int8_t dvdrp_ioctl(uint8_t request, va_list args) { uint8_t ret = TRUE; dvdrp_route *route; dvdrp_filter_list *pred; switch(request) { case DVDRP_IOCTL_SETPRED: // Change subscription predicate //printf("dvdrp_ioctl(): setpred\n"); pred = va_arg(args, dvdrp_filter_list *); node_delay = va_arg(args, uint32_t); mos_mutex_lock(&route_lock); route = dvdrp_route_find(node_id); if(!route) { ret = dvdrp_route_local_update(NULL, pred); } else { ret = dvdrp_route_local_update(route, pred); } mos_mutex_unlock(&route_lock); break; case DVDRP_IOCTL_SETFAILURE_LIMIT: case DVDRP_IOCTL_RESET_PROTO: default: break; } return ret; }
uint8_t com_send_IFACE_SERIAL (comBuf *buf) { uint8_t byte = PREAMBLE; uint8_t i; int retval; mos_mutex_lock (&if_send_mutexes[IFACE_SERIAL]); // Send the preamble then the size and packet for(i = 0; i < PREAMBLE_SIZE; i++) { retval = write (serialfd, &byte, 1); if (retval == -1) goto serial_send_error; } retval = write (serialfd, &buf->size, 1); if (retval == -1) goto serial_send_error; retval = write (serialfd, &buf->data, buf->size); if (retval == -1) goto serial_send_error; retval = tcdrain (serialfd); serial_send_error: if (retval == -1) perror("com_send_IFACE_SERIAL"); mos_mutex_unlock (&if_send_mutexes[IFACE_SERIAL]); return 0; }
uint16_t dev_write_DEV_AVR_I2C (const void *buf, uint16_t count) { uint8_t int_handle; mos_mutex_lock (&i2c_mutex); //initialize counting vars write_count = 0; write_max = count; write_buf = (uint8_t *)buf; if(mode == DEV_MODE_OFF) avr_i2c_enable(); state = START; reading = false; uint8_t polling = true; if(polling) { TWCR |= (1 << TWINT) | (1<<TWSTA); avr_i2c_wait_status_write(START); avr_i2c_put_byte(SLA_W); TWCR = (1 << TWINT) | (1 << TWEN); avr_i2c_wait_status_write(MT_SLA_ACK); while(write_count < write_max) { TWDR = write_buf[write_count++]; TWCR = (1 << TWINT) | (1 << TWEN); avr_i2c_wait_status_write(MT_DATA_ACK); } TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN); } else { int_handle = mos_disable_ints(); avr_i2c_interrupt_enable(); //enable interrupt mode avr_i2c_clear_int_flag(); //clear old flag avr_i2c_start_condition(); //initiate start condition mos_led_display(5); mos_enable_ints(int_handle); mos_led_display(4); mos_sem_wait(&i2c_sem_write); } if(mode == DEV_MODE_OFF) avr_i2c_disable(); mos_mutex_unlock(&i2c_mutex); return write_count; }
void send_packet(uint8_t packet_id) { static uint8_t inited = 0; uint16_t temp; uint16_t hum; if (!inited) { inited = 1; dev_open(DEV_MSP_HUMIDITY); if (dev_mode(DEV_MSP_HUMIDITY, DEV_MODE_ON) == DEV_FAILURE) { no_sensor = 1; } } mos_mutex_lock(&send_mutex); if (no_sensor) { temp = rand(); hum = rand(); } else { dev_read(DEV_MSP_TEMPERATURE, &temp, sizeof(temp)); dev_read(DEV_MSP_HUMIDITY, &hum, sizeof(hum)); } buf.size = 13; buf.data[0] = packet_id; buf_insert_WORD(buf.data, 1, mos_node_id_get()); buf_insert_WORD(buf.data, 3, temp); buf_insert_WORD(buf.data, 5, hum); if (no_sensor) { buf_insert_WORD(buf.data, 7, rand()); buf_insert_WORD(buf.data, 9, rand()); } else { buf_insert_WORD(buf.data, 7, adc_get_conversion16(4)); buf_insert_WORD(buf.data, 9, adc_get_conversion16(5)); } buf_insert_WORD(buf.data, 11, crc_compute(buf.data, 11)); com_send(IFACE_RADIO, &buf); mos_mutex_unlock(&send_mutex); }
static void checkNeighbor(uint16_t id) { uint8_t i; mos_mutex_lock(&send_lock); for (i = 0; i<neighbor_count && i<28; i++) { if (id == out->neighbors[i]) { mos_mutex_unlock(&send_lock); return; } } if (i==neighbor_count && i<28) { mos_remove_alarm(&send_alarm); out->neighbors[neighbor_count++] = id; mos_led_display(neighbor_count); rseed = rand(); send_alarm.msecs = 500 + rseed % 500; mos_alarm(&send_alarm); } mos_mutex_unlock(&send_lock); }
/** @brief Receive a packet that came using the dvdrping protocol. * * NOTE: Must subtract the sizeof route header from pkt->size so * the net layer can determine whether any more data is available. * @param pkt Packet received * @param footer Location * @return FALSE if failure, else return TRUE */ boolean dvdrp_recv(comBuf *pkt, uint8_t **footer, uint8_t port) { uint8_t hdr_size = pkt->data[pkt->size-1]; uint8_t matches_local = FALSE; dvdrp_pkt *hdr = (dvdrp_pkt*)&pkt->data[pkt->size - hdr_size - 1]; hdr->htl--; if(hdr->pkt_type == DVDRP_ADVERT_PKT) { printf(".ad"); mos_led_toggle(2); mos_mutex_lock(&route_lock); dvdrp_route_update(dvdrp_route_find(((dvdrp_advert_pkt *)hdr)->receiver_id), (dvdrp_advert_pkt *)hdr); mos_mutex_unlock(&route_lock); } else if(hdr->pkt_type == DVDRP_MESG_PKT) { printf(".msg"); //note, we do not match the message again, but just match bv_id's if(((dvdrp_mesg_pkt *)hdr)->immed_dest == node_id) { mos_mutex_lock(&route_lock); matches_local = dvdrp_mesg_send((dvdrp_mesg_pkt *)hdr, pkt); mos_mutex_unlock(&route_lock); } //else we drop the mo'fo } else if(hdr->pkt_type == DVDRP_REPAIR_PKT) { printf(".rep"); } // Pull our header off. pkt->size -= hdr_size + 1; // +1 for size at eop //Set the footer if we need to deliver info to the application *footer = (uint8_t *)hdr; //Should the higher layer give a shit? if(matches_local) { printf(".ml\n"); return TRUE; } else { printf("\n"); return FALSE; } }
//TODO: send more meaningful instructions to ultrasound, like beep duration uint16_t dev_write_DEV_MICA2_ULTRASOUND(const void *buf, uint16_t count) { mos_mutex_lock(&ultrasound_mutex); if(((uint8_t *)buf)[0] == 0) mica2_ultrasound_off(); else mica2_ultrasound_on(); mos_mutex_unlock(&ultrasound_mutex); return count; }
/* HACK to let us optimize, define our own version of putchar() the assembler "optimizes" calls to printf() with a single char argument by converting it to a putchar() */ int putchar(int character) { mos_mutex_lock(&printf_lock); printf_packet.size = 2; printf_packet.data[0] = character; printf_packet.data[1] = '\0'; //com_send(IFACE_SERIAL, &printf_packet); com_send_packet(&printf_packet); printf_packet.size = 0; mos_mutex_unlock(&printf_lock); return 0; }
void sendThread() { while (1) { mos_sem_wait(&send_sem); mos_mutex_lock(&send_lock); out->origin = out->route = mos_node_id_get(); out->type = TOPO_REPLY; out->seqNo = seqNo; npkt.size = 6 + 2*neighbor_count; net_send(&npkt, 77, 0); mos_mutex_unlock(&send_lock); } }
void mos_cond_wait(mos_cond_t *cond, mos_mutex_t *mt) { // Get the current thread ID mos_thread_t *id = mos_thread_current(); // Disable interrupts so we can unlock and wait atomically handle_t int_handle = mos_disable_ints(); // Unlock the mutex mos_mutex_unlock(mt); // Put us on the list for the condition variable mos_tlist_add(&cond->q, id); // Suspend us with interrupts already disabled mos_thread_suspend_noints(int_handle); // Lock the mutex again before returning mos_mutex_lock(mt); }
static void reinit() { uint8_t i; mos_mutex_lock(&send_lock); for (i = 0; i<28; i++) { out->neighbors[i] = -1; } neighbor_count = 0; mos_led_display(neighbor_count); for (i = 0; i<10; i++) { reply_cache[i] = -1; } reply_ndx = 0; mos_mutex_unlock(&send_lock); }
/** @brief Read from the current flash address into p, for count bytes */ uint16_t dev_read_DEV_ATMEL_FLASH (void *p, uint16_t count) { if (!flash_file_name) return DEV_NOT_REGISTERED; if (xmos_flash_addr+count > flash_size) return DEV_OUT_OF_RANGE; if (!flash_file) lazyInit(); mos_mutex_lock (&xmos_flash_mutex); fseek(flash_file, xmos_flash_addr, SEEK_SET); uint16_t len = fread(p, 1, count, flash_file); xmos_flash_addr += len; mos_mutex_unlock (&xmos_flash_mutex); return len; }
/** @brief Send a packet using the DV/DRP protocol. * @param pkt Packet to send * @param args */ int8_t dvdrp_send(comBuf *pkt, va_list args) { uint8_t i, orig_size; uint8_t num_attribs = va_arg(args, int); dvdrp_mesg_pkt *dvdrp_ptr = (dvdrp_mesg_pkt*)&(pkt->data[pkt->size]); dvdrp_attrib *attribs = va_arg(args, dvdrp_attrib *); // printf("dvdrp_send(%x): orig_size %C\n", attribs, pkt->size); orig_size = pkt->size; if(pkt->size + sizeof(dvdrp_mesg_pkt) + (num_attribs << 2) > COM_DATA_SIZE) return NET_BUF_FULL; dvdrp_ptr->header.pkt_type = DVDRP_MESG_PKT; dvdrp_ptr->header.htl = DVDRP_MAX_HTL; dvdrp_ptr->is_secondary = FALSE; dvdrp_ptr->num_attribs = num_attribs; pkt->size += 10; for(i = 0; i < num_attribs; ++i) { // printf("%x = %d\n", attribs[i].name, attribs[i].value); dvdrp_ptr->attributes[i].name = attribs[i].name; dvdrp_ptr->attributes[i].value = attribs[i].value; pkt->size += sizeof(dvdrp_attrib); } // printf("new size: %C\n", pkt->size); pkt->data[pkt->size++] = pkt->size - orig_size; mos_mutex_lock(&route_lock); dvdrp_get_splitbv(dvdrp_ptr, &dvdrp_ptr->split_bv); if(dvdrp_ptr->split_bv != 0) { dvdrp_mesg_send(dvdrp_ptr, pkt); i = pkt->size; //!!!!need to check for local delivery here - maybe we should //do such in dvdrp_mesg_send and return bytes instead } else { //no valid destinations, drop packet, don't do work printf(".NR"); i = 0; } mos_mutex_unlock(&route_lock); return i; }
/* HACK to let us optimize, define our own version of puts() the assembler "optimizes" calls to printf() with no args by converting it to a puts () */ int puts(const char *msg) { //printf("%s\n\0", msg); mos_mutex_lock(&printf_lock); send_string(msg); printf_packet.data[printf_packet.size++] = '\n'; printf_packet.data[printf_packet.size++] = '\0'; //com_send(IFACE_SERIAL, &printf_packet); com_send_packet(&printf_packet); printf_packet.size = 0; mos_mutex_unlock(&printf_lock); return 0; }
/* Allocate a handle */ static struct fsBlockHandle *allocHandle(struct fsFileControlBlock *fcb) { struct fsBlockHandle *res = NULL; size_t i; mos_mutex_lock(&fsBlkHandleMutex); for (i = 0; i < FS_MAX_OPEN_FILES; i++) { if (!blkHandles[i].fcb) { res = blkHandles + i; res->fcb = fcb; break; } } mos_mutex_unlock(&fsBlkHandleMutex); return res; }
static void *blkOpen(const char *path, fsMode_t mode) { struct fsFileControlBlock *fcb; if (mode & FS_RDWR || !(mode & (FS_READ | FS_APPEND)) || (mode & FS_READ && mode & FS_APPEND)) { fsSetError(FS_ERR_INVAL); return NULL; } fcb = fsBlockOpenFile(path, mode & FS_APPEND); if (fcb) { struct fsBlockHandle *handle = allocHandle(fcb); if (handle) { handle->mode = mode; mos_mutex_lock(&fcb->mutex); if (mode & FS_READ) /* Read mode */ { handle->pos = 0; handle->curr = fcb->first; handle->readEnd = 0; } else /* Write mode */ { /* Traverse blocks until the last one */ seekBlock(handle, fcb->size); handle->pos = fcb->size; } mos_mutex_unlock(&fcb->mutex); } else fsBlockCloseFile(fcb); return handle; } else return NULL; }
void xmos_flash_init (void) { flash_file = NULL; flash_file_name = NULL; flash_size = DEFAULT_FLASH_SIZE; mos_mutex_init (&xmos_flash_mutex); mos_mutex_lock (&xmos_flash_mutex); if (!mos_arg_check("-flashfile", &flash_file_name)) { // default name is hex of node id sprintf(namebuf, "%04hx.flash", mos_node_id_get()); flash_file_name = namebuf; } char* fsize; if (mos_arg_check("-flashsize", &fsize)) { flash_size = atol(fsize); } mos_mutex_unlock (&xmos_flash_mutex); }
uint8_t com_send_IFACE_LOOPBACK(comBuf *buf) { uint8_t i; mos_mutex_lock(&if_send_mutexes[IFACE_LOOPBACK]); if(managed_buf != NULL) { for(i = 0; i < buf->size; i++) managed_buf->data[i] = buf->data[i]; managed_buf->size = buf->size; } com_swap_bufs(IFACE_LOOPBACK, managed_buf, &managed_buf); mos_sem_post(&send_sem); mos_sem_wait(&send_sem); mos_mutex_unlock(&if_send_mutexes[IFACE_LOOPBACK]); return 0; }
/* Allocate a new file handle */ static int8_t fsAllocHandle(const struct fsOperations *ops) { int8_t i; mos_mutex_lock(&openFilesMutex); for (i = 0; i < FS_MAX_OPEN_FILES; i++) { if (!openFiles[i].ops) { openFiles[i].ops = ops; break; } } mos_mutex_unlock(&openFilesMutex); if (i == FS_MAX_OPEN_FILES) { fsSetError(FS_ERR_NOMEM); return -1; } return i; }
/* Free file handle */ static inline void fsFreeHandle(int8_t fd) { mos_mutex_lock(&openFilesMutex); openFiles[fd].ops = NULL; mos_mutex_unlock(&openFilesMutex); }
/* Free a handle */ static void freeHandle(struct fsBlockHandle *handle) { mos_mutex_lock(&fsBlkHandleMutex); handle->fcb = NULL; mos_mutex_unlock(&fsBlkHandleMutex); }
int16_t printf(const char *format, ...) { va_list arg; const char *p = format; if(format == NULL) return -1; mos_mutex_lock(&printf_lock); va_start(arg, format); printf_packet.size = 0; memset(printf_packet.data, 0, COM_DATA_SIZE); while(*p) { // If its not a conversion specifier we just send it if(*p != '%') { printf_packet.data[printf_packet.size++] = *p++; check_size(); } else { // Otherwise we need to substitute in a variable *p++; // TODO the padding options are not implemented for non-numeric stuff // Pad with zeros or spaces? if (*p == '0') { padchar = '0'; p++; } else padchar = ' '; // Width of field fieldwidth = 0; while(*p >= '0' && *p <= '9') { fieldwidth = fieldwidth * 10 + *p - '0'; p++; } switch(*p++) { case 's': { char *s; s = va_arg(arg, char *); send_string(s); break; } #ifdef ARCH_AVR case 'P': { PGM_P s; s = va_arg(arg, PGM_P); send_prog_string(s); } #endif case 'd': { uint16_t num16; num16 = va_arg(arg, uint16_t); norecurse_16(num16, 10); break; } case 'l': { num32 = va_arg(arg, uint32_t); norecurse_32(num32, 10); break; } case 'c': { uint16_t num8 = 0; num8 = (uint8_t)va_arg(arg, uint16_t); printf_packet.data[printf_packet.size++] = num8; check_size(); break; } case 'C': { uint16_t num8 = 0; num8 = (uint8_t) va_arg(arg, uint16_t); norecurse_16((uint16_t)num8, 10); break; } case 'x': printf_packet.data[printf_packet.size++] = '0'; check_size(); printf_packet.data[printf_packet.size++] = 'x'; check_size(); case 'h': { uint16_t num16; num16 = va_arg(arg, uint16_t); norecurse_16(num16, 16); break; } case 'o': { uint16_t num16; num16 = va_arg(arg, uint16_t); norecurse_16(num16, 8); break; } case '%': printf_packet.data[printf_packet.size++] = '%'; check_size(); break; case 'b': { uint16_t num16; num16 = va_arg(arg, uint16_t); norecurse_16(num16, 2); break; } default: printf_packet.data[printf_packet.size++] = '?'; check_size(); printf_packet.data[printf_packet.size++] = '?'; check_size(); printf_packet.data[printf_packet.size++] = '?'; check_size(); break; } } } va_end(arg); printf_packet.data[printf_packet.size++] = '\0'; //com_send(IFACE_SERIAL, &printf_packet); com_send_packet(&printf_packet); printf_packet.size = 0; mos_mutex_unlock(&printf_lock); return 0; }
/** @brief printf_P Same as printf, except that the format string must be stored * int program memory. * @param format Format to print */ int16_t printf_P(const ARCH_PROGMEM char *format, ...) { va_list arg; const prog_char *p = format; if(format == NULL) return -1; mos_mutex_lock(&printf_lock); va_start(arg, format); printf_packet.size = 0; char c = pgm_read_byte(p); while(c) { // If its not a conversion specifier we just send it if(c != '%') { printf_packet.data[printf_packet.size++] = c; c = pgm_read_byte(++p); check_size(); } else { // Otherwise we need to substitute in a variable c = pgm_read_byte(++p); // TODO the padding options are not implemented for non-numeric stuff // Pad with zeros or spaces? if (c == '0') { padchar = '0'; c = pgm_read_byte(++p); } else padchar = ' '; // Width of field fieldwidth = 0; while(c >= '0' && c <= '9') { fieldwidth = fieldwidth * 10 + c - '0'; c = pgm_read_byte(++p); } switch(c) { case 's': { char *s; s = va_arg(arg, char *); send_string(s); break; } case 'P': { PGM_P s; s = va_arg(arg, PGM_P); send_prog_string(s); } case 'd': { uint16_t num16; num16 = va_arg(arg, uint16_t); norecurse_16(num16,10); break; } case 'l': { // uint32_t num32; num32 = va_arg(arg, uint32_t); norecurse_32(num32, 10); break; } case 'c': { uint16_t num8 = 0; num8 = (uint8_t)va_arg(arg, uint16_t); printf_packet.data[printf_packet.size++] = num8; check_size(); break; } case 'C': { uint16_t num8 = 0; num8 = (uint8_t) va_arg(arg, uint16_t); norecurse_16((uint16_t)num8, 10); break; } case 'x': printf_packet.data[printf_packet.size++] = '0'; check_size(); printf_packet.data[printf_packet.size++] = 'x'; check_size(); case 'h': { uint16_t num16; num16 = va_arg(arg, uint16_t); norecurse_16(num16, 16); break; } case 'o': { uint16_t num16; num16 = va_arg(arg, uint16_t); norecurse_16(num16, 8); break; } case '%': printf_packet.data[printf_packet.size++] = '%'; check_size(); break; case 'b': { uint16_t num16; num16 = va_arg(arg, uint16_t); norecurse_16(num16, 2); break; } default: printf_packet.data[printf_packet.size++] = '?'; check_size(); printf_packet.data[printf_packet.size++] = '?'; check_size(); printf_packet.data[printf_packet.size++] = '?'; check_size(); break; } c = pgm_read_byte(++p); } } va_end(arg); printf_packet.data[printf_packet.size++] = '\0'; com_send(IFACE_SERIAL, &printf_packet); printf_packet.size = 0; mos_mutex_unlock(&printf_lock); return 0; }
uint16_t dev_read_DEV_AVR_I2C(void *buf, uint16_t count) { if(count == 0) return 0; if(mode == DEV_MODE_OFF) avr_i2c_enable(); read_max = count; read_count = 0; read_buf = (uint8_t *)buf; reading = true; uint8_t polling = true; if(polling) { //transmit a start condition TWCR |= (1 << TWINT) | (1<<TWSTA); //wait for response avr_i2c_wait_status_read(START); //transmit SLA+R avr_i2c_put_byte(SLA_W | 0x01); //lsb = 1 for read //wait for response TWCR = (1 << TWINT) | (1 << TWEN); avr_i2c_wait_status_read(MR_SLA_ACK); //get count -1 bytes and return ACK while(read_count < read_max - 1){ TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); //wait for response avr_i2c_wait_status_read(MR_DATA_ACK); read_buf[read_count++] = avr_i2c_get_byte(); } //get last byte, return NACK TWCR = (1 << TWINT) | (1 << TWEN); //wait for response avr_i2c_wait_status_read(MR_DATA_NACK); read_buf[read_count++] = avr_i2c_get_byte(); //issue a stop condition TWCR = (1 << TWSTO) | (1 << TWINT); } else { mos_sem_wait (&i2c_sem_read); } if(mode == DEV_MODE_OFF) avr_i2c_disable(); mos_mutex_unlock(&i2c_mutex); return read_count; }
void handleCommand(deluge_app* app, comBuf* pkt, uint8_t port) { deluge_foot_command* command = (deluge_foot_command*) &pkt->data[pkt->size - sizeof(deluge_foot_command)]; #ifdef DELUGE_PRINT_PACKETS printf_P(sRecvComm, command->seq, command->command, command->to); #endif if (checkCache(command->id, command->seq)) return; // Temporarily switch to max power to make sure the command gets through /*uint8_t oldPower; com_ioctl(IFACE_RADIO, CC1000_GET_TX_POWER, &oldPower); com_ioctl(IFACE_RADIO, CC1000_TX_POWER, 0xFF);*/ // If the command is not specifically addessed to us, forward it now /*if (command->to != mos_node_id_get()) net_send(pkt, DELUGE_PROTO_ID, port, port);*/ if (command->to != -1 && command->to != mos_node_id_get()) { //com_ioctl(IFACE_RADIO, CC1000_TX_POWER, oldPower); return; } //extern mutex epromLock; switch(command->command) { case DELUGE_COMMAND_HELLO: printf_P(sHello); logHeader(&spkt, DELUGE_COMMAND_HELLO); com_send(IFACE_SERIAL, &spkt); break; //case DELUGE_COMMAND_SEQNO: seqNo = 0; break; /*case DELUGE_COMMAND_STOPALL: //app->dcb.codeSize; //app->dcb.programcrc; memset(app->dcb.pagesNeeded, 0, sizeof(app->dcb.pagesNeeded)); //app->dcb.version; app->dcb.incomingPage = app->dcb.highPage = app->dcb.goalPage; deluge_saveState(app); deluge_app_init(app, app->index); break;*/ #ifdef DELUGE_KEEP_STATS case DELUGE_COMMAND_CLEARSTATS: #ifdef DELUGE_PRINT_EVENT printf_P(sClearStats); //printf_P(sClearTimer); // reset timer #endif memset(packet_counts, 0, sizeof(packet_counts)); logHeader(&spkt, DELUGE_COMMAND_CLEARSTATS); com_send(IFACE_SERIAL, &spkt); break; case DELUGE_COMMAND_STARTRECORD: #ifdef DELUGE_PRINT_EVENT printf_P(sStartRec); //printf_P(sClearTimer); // reset timer #endif logHeader(&spkt, DELUGE_COMMAND_STARTRECORD); com_send(IFACE_SERIAL, &spkt); deluge_recordstats = 1; break; case DELUGE_COMMAND_ENDRECORD: #ifdef DELUGE_PRINT_EVENT //printf_P(sDisplayTime); // display timer printf_P(sStopRec); #endif deluge_recordstats = 0; /*mos_mutex_lock(&epromLock); dev_ioctl(DEV_AVR_EEPROM, DEV_SEEK, DELUGE_STATS_ADDR); dev_write(DEV_AVR_EEPROM, (uint8_t*)packet_counts, sizeof(packet_counts)); mos_mutex_unlock(&epromLock);*/ logHeader(&spkt, DELUGE_COMMAND_ENDRECORD); com_send(IFACE_SERIAL, &spkt); break; case DELUGE_COMMAND_SENDSTATS: if (-1 != command->to && !sendingStats) { // it's addressed to us sendingStats = 1; statsPort = port; // This is a slow procedure that requires multiple packets to // reply, so run it in another thread. //mos_thread_new(statsThread, 256, PRIORITY_NORMAL); uint8_t r = 0; uint8_t i = 0; for (r=0; r<DELUGE_STATS_COUNT;) { logHeader(&spkt, DELUGE_COMMAND_SENDSTATS_REPLY); spkt.data[spkt.size++] = r; for (i=0; i<4 && r+i<DELUGE_STATS_COUNT; i++) { uint8_t j; for (j=0; j<4; j++) { uint16_t stat = packet_counts[r+i][j]; spkt.data[spkt.size++] = (uint8_t)(stat >> 8); spkt.data[spkt.size++] = (uint8_t)(stat); } } r += i; com_send(IFACE_SERIAL, &spkt); } sendingStats = 0; } break; #endif case DELUGE_COMMAND_VERSION: #ifdef DELUGE_PRINT_EVENT printf_P(sChangeVer, pkt->data[0]); printf_P(sClearTimer); // clear timer #endif mos_mutex_lock(&app->delugeLock); app->dcb.version = pkt->data[0]; deluge_saveState(app); app->detectedInconsistency = 1; stateTransition(app, DELUGE_STATE_MAINTAIN); mos_mutex_unlock(&app->delugeLock); if (command->to != -1) { /*command->seq = ++seqNo; command->command = DELUGE_COMMAND_VERSION_REPLY; command->to = command->id; command->id = mos_node_id_get(); command->type = DELUGE_PACKET_COMMAND; mos_thread_sleep(1000); net_send(pkt, DELUGE_PROTO_ID, port, port);*/ logHeader(&spkt, DELUGE_COMMAND_VERSION_REPLY); com_send(IFACE_SERIAL, &spkt); } break; #ifdef DELUGE_SYMMETRIC_LINKS /*case DELUGE_COMMAND_NEIGHBORS: if (-1 != command->to) { // it's addressed to us memcpy(pkt->data, app->neighbors, sizeof(app->neighbors)); pkt->size = sizeof(app->neighbors); //memcpy(&pkt->data[pkt->size], app->symdtbs, sizeof(app->symdtbs)); //pkt->size += sizeof(app->symdtbs); command = (deluge_foot_command*)&pkt->data[pkt->size]; command->seq = ++seqNo; command->command = DELUGE_COMMAND_NEIGHBORS_REPLY; command->to = -1; command->id = mos_node_id_get(); command->type = DELUGE_PACKET_COMMAND; pkt->size += sizeof(deluge_foot_command); mos_thread_sleep(1000); net_send(pkt, DELUGE_PROTO_ID, port, port); } break;*/ #endif /*case DELUGE_COMMAND_WIPE: { com_mode(IFACE_RADIO, IF_OFF); deluge_suspend(); #ifdef DELUGE_PRINT_EVENT printf_P(sWipe); #endif uint16_t zero = 0; uint16_t addr; mos_mutex_lock(&epromLock); for (addr = DELUGE_CONTROL_BLOCK_ADDR; addr < SIMPLE_FS_ADDR; addr += 2) { dev_ioctl(DEV_AVR_EEPROM, DEV_SEEK, addr); dev_write(DEV_AVR_EEPROM, (uint8_t*)&zero, 2); } simple_fs_format(); uint8_t default_portmap[DELUGE_INSTANCE_COUNT]; uint8_t i; for (i=0; i<DELUGE_INSTANCE_COUNT; i++) default_portmap[i] = i+1; dev_ioctl(DEV_AVR_EEPROM, DEV_SEEK, DELUGE_DIRECTORY_ADDR); dev_write(DEV_AVR_EEPROM, default_portmap, sizeof (default_portmap)); mos_mutex_unlock(&epromLock); #ifdef DELUGE_PRINT_EVENT printf_P(sDone); #endif deluge_init(); com_mode(IFACE_RADIO, IF_LISTEN); break; }*/ case DELUGE_COMMAND_BOOT: { mos_mutex_lock(&app->delugeLock); com_mode(IFACE_RADIO, IF_OFF); deluge_suspend(); if (pkt->data[0]==0) { // Just reboot reboot(); break; } // Open the requested backup image char name[4] = { 'b', 'k', '0'+pkt->data[0], 0 }; mos_file* file = mos_file_open(name); if (!file) { printf_P(sFileErr, name); deluge_resume(); com_mode(IFACE_RADIO, IF_LISTEN); break; } // We keep our current state, but we boot the backup image deluge_saveState(app); // Reboot. This function will copy the file location into the // boot control block for reprogramming app->image_file = file; runReprogram(app); // We shouldn't return from runReprogram mos_mutex_unlock(&app->delugeLock); break; } #if DELUGE_CACHE_PAGES > 1 case DELUGE_COMMAND_CACHESIZE: { if (pkt->data[0] >= DELUGE_CACHE_PAGES) break; #ifdef DELUGE_PRINT_EVENT printf_P(sChangeCache, pkt->data[0]); #endif mos_mutex_lock(&app->delugeLock); app->cacheSize = pkt->data[0]; int8_t i; for (i=0; i<DELUGE_CACHE_PAGES; i++) app->cache_map[i] = -1; app->outgoingCachePage = 0; app->incomingCachePage = 0; stateTransition(app, DELUGE_STATE_MAINTAIN); mos_mutex_unlock(&app->delugeLock); break; } #endif case DELUGE_COMMAND_POWER: { #ifdef DELUGE_PRINT_EVENT printf_P(sChangeTx, pkt->data[0]); #endif //oldPower = pkt->data[0]; // Will get changed at the end com_ioctl(IFACE_RADIO, CC1000_TX_POWER, pkt->data[0]); break; } default: break; }