Beispiel #1
0
THD_FUNCTION(scCmdHelpThread, arg)
{
  uint8_t i;

  (void)arg;

  chRegSetThreadName(__func__);

  for (i = 0; i < SC_CMD_MAX_COMMANDS; ++i) {
    const char *help = "No help available";

    if (commands[i].cmd == NULL) {
      break;
    }

    if (commands[i].help) {
      help = commands[i].help;
    }

    SC_LOG_PRINTF("%-16s %s\r\n", commands[i].cmd, help);

    // Prevent overflowing the transmit buffers
    chThdSleepMilliseconds(50);
  }
}
Beispiel #2
0
/*
 * Received a message over Spirit1
 */
static void cb_spirit1_msg(void)
{
  uint8_t msg[32];
  uint8_t len;
  uint8_t addr;
  uint8_t lqi;
  uint8_t rssi;

  len = sc_spirit1_read(&addr, msg, sizeof(msg));
  if (len) {
    lqi = sc_spirit1_lqi();
    rssi = sc_spirit1_rssi();
    SC_LOG_PRINTF("GOT MSG (LQI: %u, RSSI: %u): %s", lqi, rssi, msg);
  } else {
    SC_LOG_PRINTF("SPIRIT1 READ FAILED");
  }
}
Beispiel #3
0
/*
 * Message has been sent but no ACK was received
 */
static void cb_spirit1_lost(void)
{
#if ENABLE_SHUTDOWN
  enable_shutdown();
#else
  SC_LOG_PRINTF("d: spirit1 msg lost1\r\n");

  chThdSleepMilliseconds(1000);
#endif
}
Beispiel #4
0
int main(void)
{
  standby = sc_pwr_get_standby_flag();
  wkup = sc_pwr_get_wake_up_flag();

  // Enable debugging even with WFI
  // This increases the power consumption by 1.5mA
  sc_pwr_set_wfi_dbg();

  halInit();
  chSysInit();

  sc_init(SC_MODULE_GPIO | SC_MODULE_SPI | SC_MODULE_UART2);
  sc_log_output_uart(SC_UART_2);

  // Start event loop. This will start a new thread and return
  sc_event_loop_start();
  SC_LOG_PRINTF("started\r\n");

  // Register callbacks.
  // These will be called from Event Loop thread. It's OK to do some
  // calculations etc. time consuming there, but not to sleep or block
  // for longer periods of time.
  sc_event_register_handle_byte(cb_handle_byte);
  sc_event_register_spirit1_msg_available(cb_spirit1_msg);
  sc_event_register_spirit1_data_sent(cb_spirit1_sent);
  sc_event_register_spirit1_data_lost(cb_spirit1_lost);

  sc_spirit1_init(TOP_SECRET_KEY, MY_ADDRESS);
  SC_LOG_PRINTF("spirit1 init done\r\n");

  while(1) {
    uint8_t msg[] = {'t', 'e', 's', 't', '\r', '\n', '\0'};
    chThdSleepMilliseconds(1000);
    SC_LOG_PRINTF("sending: test\r\n");
    sc_spirit1_send(SPIRIT1_BROADCAST_ADDRESS, msg, sizeof(msg) - 1);
  }
}
Beispiel #5
0
/*
 * Parse echo command
 */
static void parse_command_echo(const uint8_t *param, uint8_t param_len)
{
  (void)param_len;

  switch (param[0]) {
  case '0':
    echo = 0;
    break;
  case '1':
    echo = 1;
    break;
  default:
    // Invalid value, ignoring command
    return;
  }
  SC_LOG_PRINTF("echo %s\r\n", echo ? "on" : "off");
}
Beispiel #6
0
/*
 * Parse help command
 */
static void parse_command_help(const uint8_t *param, uint8_t param_len)
{

  (void)param_len;
  (void)param;

#ifdef SC_CMD_REMOVE_HELP
  SC_LOG_PRINTF("No help available\r\n");
#else
  // Launch a thread to print longer stuff
  chThdCreateStatic(sc_cmd_help_thread,
                    sizeof(sc_cmd_help_thread),
                    NORMALPRIO,
                    scCmdHelpThread,
                    NULL);
#endif
}
Beispiel #7
0
/*
 * Parse a received command.
 */
static void parse_command(void)
{
  int i;
  uint8_t cmd_len = 0;
  bool found_param = false;
  bool found_cmd = false;

  // Find the start of the first parameter to allow using sc_str_equal later
  for (i = 1; i < recv_i; ++i) {
    if (receive_buffer[i] == ' ') {
      cmd_len = i;
      found_param = true;
      break;
    }
  }

  if (!found_param) {
    cmd_len = recv_i;
  }

  for (i = 0; i < SC_CMD_MAX_COMMANDS; i++) {
    if (commands[i].cmd == NULL) {
      break;
    }
    if (sc_str_equal(commands[i].cmd, (char*)receive_buffer, cmd_len)) {
      uint8_t *cmd = NULL;
      uint8_t len = 0;

      found_cmd = true;

      if (found_param) {
        cmd = &receive_buffer[cmd_len + 1];
        len = recv_i - (cmd_len + 1);
      }
      commands[i].cmd_cb(cmd, len);
      break;
    }
  }

  if (!found_cmd) {
    SC_LOG_PRINTF("Unknown command: %s\r\n", receive_buffer);
  }
}
Beispiel #8
0
/*
 * Receive byte. This can be called only from the main thread.
 * FIXME: per uart buffers. Now we happily mix all uarts together.
 */
void sc_cmd_push_byte(uint8_t byte)
{

  // If in a middle of blob transfer, store raw data without interpretation
  chMtxLock(&blob_mtx);
  if (blob_i < blob_len) {

    // FIXME: HACK: Assume \n is from the previous command and not
    // part of the blob
    if (blob_i == 0 && byte == '\n') {
      chMtxUnlock(&blob_mtx);
      return;
    }

    if (blob_i+1 >= SC_BLOB_MAX_SIZE) {
      chDbgAssert(0, "blob_i out of bounds");
      chMtxUnlock(&blob_mtx);
      return;
    }
    blob_buf[blob_i++] = byte;

    if (blob_i % 1024 == 0) {
      SC_DBG("1K received\r\n");
    }

    if (blob_i == blob_len) {
      msg_t drdy;
      // Create and send blob ready notification
      drdy = sc_event_msg_create_type(SC_EVENT_TYPE_BLOB_AVAILABLE);
      sc_event_msg_post(drdy, SC_EVENT_MSG_POST_FROM_NORMAL);
    }
  }
  chMtxUnlock(&blob_mtx);

  // Convert all different types of newlines to single \n
  if (byte == '\r') {
    byte = '\n';
  }

  // Do nothing on \n if there's no previous command in the buffer
  if ((byte == '\n') && (recv_i == 0 || receive_buffer[recv_i - 1] == '\n')) {
    return;
  }

  if (echo) {
    if (byte == '\n') {
      SC_LOG_PRINTF("\r\n");
    } else {
      SC_LOG_PRINTF("%c", byte);
    }
  }

  // Store the received character
  receive_buffer[recv_i] = byte;

  // Check for full command in the buffer
  if (byte == '\n') {

    // Null terminate
    receive_buffer[recv_i] = '\0';

    // Parse the received command
    parse_command();

    // Mark buffer empty
    recv_i = 0;
    return;
  }

  // Discard all data in buffer if buffer is full.
  if (++recv_i == SC_CMD_MAX_RECV_BUF_LEN) {
    // FIXME: increase some overflow stat?
    recv_i = 0;
  }
}
THD_FUNCTION(scMS5611Thread, arg)
{
  systime_t sleep_until;
  systime_t interval_st = MS2ST(ms5611_interval_ms);
  
  (void)arg;
  chRegSetThreadName(__func__);

  SC_LOG_PRINTF("d: ms5611 init\r\n");
  
  // We need to give a bit of time to the chip until we can ask it to shut down
  // i2c not ready initially? (This is inherited from the LSM9DS0 driver)
  chThdSleepMilliseconds(20);

  ms5611_reset();
  chThdSleepMilliseconds(100);
  ms5611_reset();
  chThdSleepMilliseconds(100);
  ms5611_reset();
  chThdSleepMilliseconds(100);
  ms5611_read_prom();
  uint8_t ref_crc = ms5611_prom[MS5611_PROM_SIZE - 1] & 0x0F;
  uint8_t calc_crc = ms5611_calc_crc();
  if (ref_crc != calc_crc) {
    SC_LOG_PRINTF("e: ms5611 crc failure: 0x%x vs 0x%x\r\n", ref_crc, calc_crc);
  }

  sleep_until = chVTGetSystemTime() + interval_st;
  
  // Loop initiating measurements and waiting for results
  while (!chThdShouldTerminateX()) {
    systime_t now = chVTGetSystemTime();
    systime_t wait_time = sleep_until - now;
    uint32_t temp;
    uint32_t pres;
    msg_t msg;

    // Using a semaphore allows to cancel the sleep outside the thread
    if (chBSemWaitTimeout(&ms5611_wait_sem, wait_time) != MSG_TIMEOUT) {
      continue;
    }

    sleep_until += interval_st;
    now = chVTGetSystemTime();
    
    temp = ms5611_read(true);
    
    if (chThdShouldTerminateX()) {
      break;
    }
    
    pres = ms5611_read(false);

    chMtxLock(&data_mtx);
    ms5611_temp = temp;
    ms5611_pres = pres;
    ms5611_time_st = now;
    chMtxUnlock(&data_mtx);

    // Notify main app about new measurements being available
    msg = sc_event_msg_create_type(SC_EVENT_TYPE_MS5611_AVAILABLE);
    sc_event_msg_post(msg, SC_EVENT_MSG_POST_FROM_NORMAL);
  }
}