/** * \brief Command result formatting and printing. * * Prints out on device fd the values contained * in the array result, using the format specified * in fmt. * * \param ch Channel handle. * \param fmt Values format string. * \param result Array containing result to be printed. * * \return -1 in case of errors, otherwise 0. */ static int printResult(KFile *ch, const char *fmt, parms result[]) { long n; char repeat_cnt = 0; while (*fmt) { if (*fmt >= '0' && *fmt <= '9') { /* Collect repeat count digit (left to right order) */ repeat_cnt = (repeat_cnt * 10) + (*fmt - '0'); } else { /* Set default repeat cnt of 1 when not specified */ if (repeat_cnt == 0) repeat_cnt = 1; /* Loop repeat_cnt times */ do { switch (*fmt) { case 'd': kfile_printf(ch, ARG_SEP_S "%ld", (*result).l); result++; break; case 'c': kfile_print(ch, ARG_SEP_S); kfile_print(ch, (*result).s); result++; break; case 's': kfile_printf(ch, ARG_SEP_S "%s", (*result).s); result++; break; case 'n': n = (*result++).l; kfile_printf(ch, ARG_SEP_S "%ld", n); while (n--) { kfile_printf(ch, ARG_SEP_S "%ld", (*result).l); result++; } break; default: break; } } while (--repeat_cnt); } /* Skip to next format char */ ++fmt; } /* while (*fmt) */ kfile_print(ch, "\r\n"); return 0; }
/* * Print args on s, with format specified in t->result_fmt. * Return number of valid arguments or -1 in case of error. */ static bool protocol_reply(KFile *fd, const struct CmdTemplate *t, const parms *args) { unsigned short offset = strlen(t->arg_fmt) + 1; unsigned short nres = strlen(t->result_fmt); for (unsigned short i = 0; i < nres; ++i) { if (t->result_fmt[i] == 'd') { kfile_printf(fd, " %ld", args[offset+i].l); } else if (t->result_fmt[i] == 's') { kfile_printf(fd, " %s", args[offset+i].s); } else { abort(); } } kfile_printf(fd, "\r\n"); return true; }
int main(void) { init(); LOG_INFO("\r\n== BeRTOS TNC\r\n"); LOG_INFO("== Starting.\r\n"); kfile_printf(&ser_port.fd, "\r\n== BeRTOS TNC\r\n"); kfile_printf(&ser_port.fd, "== Starting.\r\n" ); while (1) { ax25_poll(&ax25); if (ax25.dcd) { LED_BLUE_ON(); } else { LED_BLUE_OFF(); } if (afsk.sending) { LED_GREEN_ON(); } else { LED_GREEN_OFF(); } kiss_serial_poll(); kiss_queue_process(); } return 0; }
void print_graph (KFile *stream, uint8_t type, uint8_t style) { MEDIAN *mArray; uint8_t i, j, index; int16_t highest, lowest, scale, value; static uint8_t last_type = 99, last_style = 99; char buf[21]; switch(type) { case MINGRAPH: mArray = &PowerMins; strncpy(buf, "Hourly", 7); break; case HOURGRAPH: mArray = &PowerHours; strncpy(buf, "Daily", 6); break; case DAYGRAPH: mArray = &PowerDays; strncpy(buf, "Monthly", 8); break; default: mArray = &PowerMins; break; } median_getHighest(mArray, &highest); median_getLowest(mArray, &lowest); scale = MAX(abs(highest), abs(lowest)); if ((last_type != type) || (last_style != style)) { kfile_putc(TERM_CLR, stream); last_type = type; last_style = style; } if ((style == GRAPHSTYLE) && scale) { for (i = 0; i < 4; i++) // for each line to be displayed { index = median_getStart(mArray); for (j = 0; j < median_getCount(mArray); j++) { median_getNext(mArray, &index, &value); buf[j] = graphmap[i][(int32_t)(value + scale) * 8 / scale]; } buf[j] = 0; kfile_printf(stream, "%c%c%c%s", TERM_CPC, TERM_ROW + i, TERM_COL, buf); } } else { kfile_printf(stream, "\r\n%s Range:\r\n %d to %d", buf, lowest, highest); } }
/** * Send a NAK asking the host to send the current message again. * * \a fd kfile handler for serial. * \a err human-readable description of the error for debug purposes. */ INLINE void NAK(KFile *fd, const char *err) { #ifdef _DEBUG kfile_printf(fd, "NAK \"%s\"\r\n", err); #else kfile_printf(fd, "NAK\r\n"); #endif }
/* * Print on console the message that we have received. */ static void message_callback(struct AX25Msg *msg) { kfile_printf(&ser.fd, "\n\nSRC[%.6s-%d], DST[%.6s-%d]\r\n", msg->src.call, msg->src.ssid, msg->dst.call, msg->dst.ssid); for (int i = 0; i < msg->rpt_cnt; i++) kfile_printf(&ser.fd, "via: [%.6s-%d]\r\n", msg->rpt_lst[i].call, msg->rpt_lst[i].ssid); kfile_printf(&ser.fd, "DATA: %.*s\r\n", msg->len, msg->info); }
static void apply_brake(bool state) { if (state) { // turn on brake kfile_printf (&serial.fd, "Brake ON\r\n"); } else { // turn off brake kfile_printf (&serial.fd, "Brake OFF\r\n"); } }
int main(void) { init(); ticks_t start = timer_clock(); unsigned char x = 0; // FIXME memcpy(path[1].call, MYCALL, 6); path[1].ssid = MYCALL_SSID; while (1) { /* As long as CONFIG_AFSK_RXTIMEOUT is set to 0, this function won't block and return immediately. */ ax25_poll(&ax25); #if 1 /* Send out message every 15sec */ if (timer_clock() - start > ms_to_ticks(APRS_BEACON_TIME * 1000L)) { kfile_printf(&ser.fd, "Beep %d\n", x++); start = timer_clock(); ax25_sendVia(&ax25, path, countof(path), APRS_BEACON_MSG, sizeof(APRS_BEACON_MSG)); } #endif } return 0; }
// This is a callback we register with the protocol, // so we can process each packet as they are decoded. // Right now it just prints the packet to the serial port. static void mp1Callback(struct MP1Packet *packet) { if (SERIAL_DEBUG) { kfile_printf(&ser.fd, "%.*s\n", packet->dataLength, packet->data); } else { for (unsigned long i = 0; i < packet->dataLength; i++) { kfile_putc(packet->data[i], &ser.fd); } } }
void NORETURN context_switch(void) { IRQ_ENABLE; timer_init(); proc_init(); #if CONFIG_USE_HP_TIMER ser_init(&out, CONFIG_CTX_DEBUG_PORT); ser_setbaudrate(&out, CONFIG_CTX_DEBUG_BAUDRATE); #endif #if CONFIG_USE_LED LED_INIT(); #endif proc_forbid(); hp_proc = proc_new(hp_process, NULL, PROC_STACK_SIZE, hp_stack); lp_proc = proc_new(lp_process, NULL, PROC_STACK_SIZE, lp_stack); main_proc = proc_current(); proc_setPri(hp_proc, 2); proc_setPri(lp_proc, 1); proc_permit(); while (1) { timer_delay(100); sig_send(lp_proc, SIG_USER0); sig_wait(SIG_USER0); #if CONFIG_USE_HP_TIMER kfile_printf(&out.fd, "Switch: %lu.%lu usec\n\r", hptime_to_us((end - start)), hptime_to_us((end - start) * 1000) % 1000); #endif } }
void protocol_run(KFile *fd) { /** * \todo to be removed, we could probably access the serial FIFO * directly */ static char linebuf[80]; if (!interactive) { kfile_gets(fd, linebuf, sizeof(linebuf)); // reset serial port error anyway kfile_clearerr(fd); // check message minimum length if (linebuf[0]) { /* If we enter lines beginning with sharp(#) they are stripped out from commands */ if(linebuf[0] != '#') { if (linebuf[0] == 0x1B && linebuf[1] == 0x1B) // ESC { interactive = true; kfile_printf(fd, "Entering interactive mode\r\n"); } else { protocol_parse(fd, linebuf); } } } } else { const char *buf; /* * Read a line from serial. We use a temporary buffer * because otherwise we would have to extract a message * from the port immediately: there might not be any * available, and one might get free while we read * the line. We also add a fake ID at the start to * fool the parser. */ buf = rl_readline(&rl_ctx); /* If we enter lines beginning with sharp(#) they are stripped out from commands */ if(buf && buf[0] != '#') { if (buf[0] != '\0') { // exit special case to immediately change serial input if (!strcmp(buf, "exit") || !strcmp(buf, "quit")) { rl_clear_history(&rl_ctx); kfile_printf(fd, "Leaving interactive mode...\r\n"); interactive = FORCE_INTERACTIVE; } else { //TODO: remove sequence numbers linebuf[0] = '0'; linebuf[1] = ' '; strncpy(linebuf + 2, buf, sizeof(linebuf) - 3); linebuf[sizeof(linebuf) - 1] = '\0'; protocol_parse(fd, linebuf); } } } } }
/* * Print on console the message that we have received. */ static void message_callback(struct AX25Msg *msg) { int i, k; static AX25Call tmp_path[AX25_MAX_RPT + 2]; static uint8_t tmp_path_size; static const char* relay_calls[] = {"RELAY\x0", "WIDE\x0\x0", "TRACE\x0", 0}; #if 1 kfile_printf(&ser.fd, "\n\nSRC[%.6s-%d], DST[%.6s-%d]\r\n", msg->src.call, msg->src.ssid, msg->dst.call, msg->dst.ssid); for (i = 0; i < msg->rpt_cnt; i++) kfile_printf(&ser.fd, "via: [%.6s-%d%s]\r\n", msg->rpt_lst[i].call, msg->rpt_lst[i].ssid, msg->rpt_lst[i].h_bit?"*":""); kfile_printf(&ser.fd, "DATA: %.*s\r\n", msg->len, msg->info); #endif if (1) { uint8_t repeat = 0; uint8_t is_wide = 0, is_trace = 0; msg->dst.ssid = 0; msg->dst.h_bit = 0; memcpy(msg->dst.call, CALL_BERTOS_APRS, 6); tmp_path[0] = msg->dst; tmp_path[1] = msg->src; for (i = 0; i < msg->rpt_cnt; ++i) tmp_path[i + 2] = msg->rpt_lst[i]; tmp_path_size = 2 + msg->rpt_cnt; /* Should we repeat the packet? * http://wa8lmf.net/DigiPaths/ */ /* * This works as follows: for every call on the repeaters list from first to last, find the first * call with the H bit (has-been-repeated) set to false. If this call is RELAY, WIDE or TRACE then * we sould repeat the packet. */ for (i = 2; i < tmp_path_size; ++i) { if (!tmp_path[i].h_bit) { AX25Call* c = &tmp_path[i]; if ((memcmp(tmp_path[i].call, MYCALL, 6) == 0) && (tmp_path[i].ssid == MYCALL_SSID)) { repeat = 0; break; } for (k=0; relay_calls[k]; ++k) { if (memcmp(relay_calls[k], c->call, 6) == 0) { repeat = 1; tmp_path[i].h_bit = 1; break; } } if (repeat) break; if (tmp_path[i].ssid > 0) { is_wide = memcmp("WIDE", c->call, 4) == 0; is_trace = memcmp("TRACE", c->call, 5) == 0; if (is_wide || is_trace) { repeat = 1; tmp_path[i].ssid--; if (tmp_path[i].ssid == 0) tmp_path[i].h_bit = 1; /* Add the Digi Call to the path*/ if (is_trace && (tmp_path_size < (AX25_MAX_RPT + 2))) { for (k = tmp_path_size; k > i; --k) { tmp_path[k] = tmp_path[k - 1]; } memcpy(tmp_path[i].call, MYCALL, 6); tmp_path[i].ssid = MYCALL_SSID; tmp_path[i].h_bit = 1; tmp_path_size++; i++; } break; } } } else { if ((memcmp(tmp_path[i].call, MYCALL, 6) == 0) && (tmp_path[i].ssid == MYCALL_SSID)) { repeat = 1; tmp_path[i].h_bit = 1; break; } } } if ((memcmp(tmp_path[1].call, MYCALL, 6) == 0) && (tmp_path[i].ssid == MYCALL_SSID)) { repeat = 0; } if (repeat) { ax25_sendVia(&ax25, tmp_path, tmp_path_size, msg->info, msg->len); kfile_print(&ser.fd, "REPEATED\n"); } else { kfile_print(&ser.fd, "NOT REPEATED\n"); } } }