From 2b30370b42fc641510b541c4370a3473b92099cc Mon Sep 17 00:00:00 2001 From: Antonio Lignan Date: Sun, 15 May 2016 11:20:23 +0200 Subject: [PATCH] AT driver (master) and example --- apps/at-master/Makefile.at-master | 1 + apps/at-master/at-master.c | 148 ++++++ apps/at-master/at-master.h | 123 +++++ examples/zolertia/zoul/at-test/Makefile | 7 + .../zolertia/zoul/at-test/at-master-test.c | 487 ++++++++++++++++++ examples/zolertia/zoul/at-test/project-conf.h | 67 +++ 6 files changed, 833 insertions(+) create mode 100644 apps/at-master/Makefile.at-master create mode 100644 apps/at-master/at-master.c create mode 100644 apps/at-master/at-master.h create mode 100644 examples/zolertia/zoul/at-test/Makefile create mode 100644 examples/zolertia/zoul/at-test/at-master-test.c create mode 100644 examples/zolertia/zoul/at-test/project-conf.h diff --git a/apps/at-master/Makefile.at-master b/apps/at-master/Makefile.at-master new file mode 100644 index 000000000..9ab561a16 --- /dev/null +++ b/apps/at-master/Makefile.at-master @@ -0,0 +1 @@ +at-master_src = at-master.c diff --git a/apps/at-master/at-master.c b/apps/at-master/at-master.c new file mode 100644 index 000000000..c9e0597b6 --- /dev/null +++ b/apps/at-master/at-master.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include "contiki.h" +#include "contiki-lib.h" +#include "at-master.h" +#include "cpu.h" +#include "dev/uart.h" +#include "dev/serial-line.h" +#include "dev/sys-ctrl.h" +#include "lib/list.h" +#include "sys/cc.h" + +#include +#include +#include +#include +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +LIST(at_cmd_list); +process_event_t at_cmd_received_event; +/*---------------------------------------------------------------------------*/ +static uint8_t at_uart = 0; +/*---------------------------------------------------------------------------*/ +PROCESS(at_process, "AT process"); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(at_process, ev, data) +{ + uint8_t plen; + char *pch, *buf; + struct at_cmd *a; + PROCESS_BEGIN(); + + while(1) { + PROCESS_WAIT_EVENT_UNTIL(ev == serial_line_event_message && data != NULL); + buf = (char *)data; + plen = strlen(buf); + for(a = list_head(at_cmd_list); a != NULL; a = list_item_next(a)) { + pch = strstr(buf, a->cmd_header); + if((plen <= a->cmd_max_len) && (pch != NULL)) { + if(strncmp(a->cmd_header, pch, a->cmd_hdr_len) == 0) { + if((a->cmd_hdr_len == plen) || (a->cmd_max_len > a->cmd_hdr_len)) { + a->event_callback(a, plen, (char *)pch); + process_post(a->app_process, at_cmd_received_event, NULL); + break; + } + } + } + } + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +struct at_cmd * +at_list(void) +{ + return list_head(at_cmd_list); +} +/*---------------------------------------------------------------------------*/ +uint8_t +at_send(char *s, uint8_t len) +{ + uint8_t i = 0; + while(s && *s != 0) { + if(i >= len) { + break; + } + uart_write_byte(at_uart, *s++); + i++; + } + return i; +} +/*---------------------------------------------------------------------------*/ +void +at_init(uint8_t uart_sel) +{ + static uint8_t inited = 0; + if(!inited) { + list_init(at_cmd_list); + at_cmd_received_event = process_alloc_event(); + inited = 1; + + at_uart = uart_sel; + uart_init(at_uart); + uart_set_input(at_uart, serial_line_input_byte); + serial_line_init(); + + process_start(&at_process, NULL); + PRINTF("AT: Started (%u)\n", at_uart); + } +} +/*---------------------------------------------------------------------------*/ +at_status_t +at_register(struct at_cmd *cmd, struct process *app_process, + const char *cmd_hdr, const uint8_t hdr_len, + const uint8_t cmd_max_len, at_event_callback_t event_callback) +{ + if((hdr_len < 1) || (cmd_max_len < 1) || (!strncmp(cmd_hdr, "AT", 2) == 0) || + (event_callback == NULL)) { + PRINTF("AT: Invalid argument\n"); + return AT_STATUS_INVALID_ARGS_ERROR; + } + + memset(cmd, 0, sizeof(struct at_cmd)); + cmd->event_callback = event_callback; + cmd->cmd_header = cmd_hdr; + cmd->cmd_hdr_len = hdr_len; + cmd->cmd_max_len = cmd_max_len; + cmd->app_process = app_process; + list_add(at_cmd_list, cmd); + PRINTF("AT: registered HDR %s LEN %u MAX %u\n", cmd->cmd_header, + cmd->cmd_hdr_len, + cmd->cmd_max_len); + return AT_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ diff --git a/apps/at-master/at-master.h b/apps/at-master/at-master.h new file mode 100644 index 000000000..ad625c0dc --- /dev/null +++ b/apps/at-master/at-master.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#ifndef AT_MASTER_H_ +#define AT_MASTER_H_ +#include "contiki.h" +/*---------------------------------------------------------------------------*/ +#define AT_DEFAULT_RESPONSE_OK "\r\nOK\r\n" +#define AT_DEFAULT_RESPONSE_ERROR "\r\nERROR\r\n" +/*---------------------------------------------------------------------------*/ +#define AT_RESPONSE(x) at_send((x), (strlen(x))) +/*---------------------------------------------------------------------------*/ +extern process_event_t at_cmd_received_event; +struct at_cmd; +/*---------------------------------------------------------------------------*/ +typedef enum { + AT_STATUS_OK, + AT_STATUS_ERROR, + AT_STATUS_INVALID_ARGS_ERROR, +} at_status_t; +/*---------------------------------------------------------------------------*/ +/** + * \brief AT initialization + * \param uart selects which UART to use + * + * The AT driver invokes this function upon registering a command, this will + * wait for the serial_line_event_message event + */ +void at_init(uint8_t uart); +/*---------------------------------------------------------------------------*/ +/** + * \brief AT initialization + * \param uart selects which UART to use + * + * The AT driver invokes this function upon registering a command, this will + * wait for the serial_line_event_message event + */ +uint8_t at_send(char *s, uint8_t len); +/*---------------------------------------------------------------------------*/ +/** + * \brief AT event callback + * \param cmd A pointer to the AT command placeholder + * \param len Lenght of the received data (including the AT command header) + * \param data A user-defined pointer + * + * The AT event callback function gets called whenever there is an + * event on an incoming AT command + */ +typedef void (*at_event_callback_t)(struct at_cmd *cmd, + uint8_t len, + char *data); +/*---------------------------------------------------------------------------*/ +struct at_cmd { + struct at_cmd *next; + const char *cmd_header; + uint8_t cmd_hdr_len; + uint8_t cmd_max_len; + at_event_callback_t event_callback; + struct process *app_process; +}; +/*---------------------------------------------------------------------------*/ +/** + * \brief Registers the callback to return an AT command + * \param cmd A pointer to the CMD placeholder + * \param cmd_hdr String to compare when an AT command is received + * \param cmd_len Lenght of cmd_hdr + * \param event_callback Callback function to handle the AT command + * \return AT_STATUS_OK or AT_STATUS_INVALID_ARGS_ERROR + * + * Register the commands to search for when a valid AT frame has been received + */ +at_status_t at_register(struct at_cmd *cmd, + struct process *app_process, + const char *cmd_hdr, + const uint8_t cmd_hdr_len, + const uint8_t cmd_max_len, + at_event_callback_t event_callback); +/*---------------------------------------------------------------------------*/ +struct at_cmd *at_list(void); +/*---------------------------------------------------------------------------*/ +/** + * \brief Registers the callback to return an AT command + * \param cmd A pointer to the CMD placeholder + * \param cmd_hdr String to compare when an AT command is received + * \param cmd_len Lenght of cmd_hdr + * \param event_callback Callback function to handle the AT command + * \return AT_STATUS_OK or AT_STATUS_INVALID_ARGS_ERROR + * + * Register the commands to search for when a valid AT frame has been received + */ +at_status_t at_register(struct at_cmd *cmd, + struct process *app_process, + const char *cmd_hdr, + const uint8_t cmd_hdr_len, + const uint8_t cmd_max_len, + at_event_callback_t event_callback); +#endif /* AT_MASTER_H_ */ diff --git a/examples/zolertia/zoul/at-test/Makefile b/examples/zolertia/zoul/at-test/Makefile new file mode 100644 index 000000000..14ab8b54b --- /dev/null +++ b/examples/zolertia/zoul/at-test/Makefile @@ -0,0 +1,7 @@ +DEFINES+=PROJECT_CONF_H=\"project-conf.h\" +CONTIKI_PROJECT = at-master-test +APPS = at-master +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/zolertia/zoul/at-test/at-master-test.c b/examples/zolertia/zoul/at-test/at-master-test.c new file mode 100644 index 000000000..520c28bdb --- /dev/null +++ b/examples/zolertia/zoul/at-test/at-master-test.c @@ -0,0 +1,487 @@ +/* + * Copyright (c) 2016, Zolertia - http://www.zolertia.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup zoul-AT-master-test + * @{ + * + * Test the Zoul hardware using AT commands + * @{ + * + * \author + * Antonio Lignan + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "cpu.h" +#include "at-master.h" +#include "sys/ctimer.h" +#include "sys/process.h" +#include "dev/adc.h" +#include "dev/leds.h" +#include "dev/watchdog.h" +#include "dev/sys-ctrl.h" +#include "dev/gpio.h" +#include "dev/ioc.h" +#include "net/rime/rime.h" +#include "lib/list.h" +#include "dev/sha256.h" +#include +#include +#include +/*---------------------------------------------------------------------------*/ +PROCESS(at_test_process, "AT test process"); +AUTOSTART_PROCESSES(&at_test_process); +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +static struct at_cmd at_cmd_test; +static struct at_cmd at_cmd_board; +static struct at_cmd at_cmd_led; +static struct at_cmd at_cmd_addr; +static struct at_cmd at_cmd_gpio; +static struct at_cmd at_cmd_read; +static struct at_cmd at_cmd_flop; +static struct at_cmd at_cmd_reset; +static struct at_cmd at_cmd_sha256; +static struct at_cmd at_cmd_adc; +/*---------------------------------------------------------------------------*/ +#define HWTEST_GPIO_INPUT 0 +#define HWTEST_GPIO_OUTPUT 1 +#define HWTEST_GPIO_OUTPUT_ODD 3 +#define HWTEST_GPIO_OUTPUT_LIST 4 +#define HWTEST_GPIO_OUTPUT_MASK 0x55 +#define HWTEST_GPIO_OUTPUT_ODD_MASK 0xAA +/*---------------------------------------------------------------------------*/ +typedef struct { + char *name; + uint8_t port; + uint8_t pin; +} gpio_list_t; +/*---------------------------------------------------------------------------*/ +static struct ctimer ct; +/*---------------------------------------------------------------------------*/ +static void +floppin(uint8_t port, uint8_t pin) +{ + uint8_t i; + GPIO_CLR_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); + clock_delay_usec(500); + for(i = 0; i < 50; i++) { + GPIO_SET_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); + clock_delay_usec(500); + GPIO_CLR_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); + clock_delay_usec(500); + } +} +/*---------------------------------------------------------------------------*/ +#if DEBUG +static char * +pname(uint8_t num) +{ + if(num == GPIO_A_NUM) { + return "PA"; + } + if(num == GPIO_B_NUM) { + return "PB"; + } + if(num == GPIO_C_NUM) { + return "PC"; + } + if(num == GPIO_D_NUM) { + return "PD"; + } + return "INVALID"; +} +#endif +/*---------------------------------------------------------------------------*/ +static void +config_gpio(uint8_t port, uint8_t pin, uint8_t type) +{ + GPIO_SOFTWARE_CONTROL(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); + if(type == HWTEST_GPIO_OUTPUT) { + GPIO_SET_OUTPUT(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); + } else if(type == HWTEST_GPIO_INPUT) { + GPIO_SET_INPUT(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); + } +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_test_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + AT_RESPONSE("Hello!"); + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_board_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + AT_RESPONSE(BOARD_STRING); + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_flop_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + /* Format: AT&FLOP=PN where P(ort)N(number) */ + uint8_t port; + uint8_t pin = atoi(&data[9]); + + if((pin < 0) || (pin > 9)) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + if(strncmp(&data[8], "A", 1) == 0) { + port = GPIO_A_NUM; + } else if(strncmp(&data[8], "B", 1) == 0) { + port = GPIO_B_NUM; + } else if(strncmp(&data[8], "C", 1) == 0) { + port = GPIO_C_NUM; + } else if(strncmp(&data[8], "D", 1) == 0) { + port = GPIO_D_NUM; + } else { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + config_gpio(port, pin, HWTEST_GPIO_OUTPUT); + floppin(port, pin); + + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_address_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + static char _lladdr[17]; + snprintf(_lladdr, 17, "%02x%02x%02x%02x%02x%02x%02x%02x", + linkaddr_node_addr.u8[0], linkaddr_node_addr.u8[1], + linkaddr_node_addr.u8[2], linkaddr_node_addr.u8[3], + linkaddr_node_addr.u8[4], linkaddr_node_addr.u8[5], + linkaddr_node_addr.u8[6], linkaddr_node_addr.u8[7]); + + AT_RESPONSE(_lladdr); + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_reset_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + uint8_t reset_val = atoi(&data[9]); + /* AT&RESET=n, where n: + * 0 : CC2538 soft reset + */ + if((reset_val != 0) && (reset_val != 1)) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + /* Send the response and wait a second until executing the command */ + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); + + if(reset_val == 0) { + ctimer_set(&ct, CLOCK_SECOND, sys_ctrl_reset, NULL); + } +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_leds_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + /* Format: AT&LED=L,s where L(ed)=R/G/B, s(tate)=1/0*/ + uint8_t led; + uint8_t state = strncmp(&data[9], "1", 1) ? 0 : 1; + + if(strncmp(&data[8], ",", 1) != 0) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + if(strncmp(&data[7], "R", 1) == 0) { + led = LEDS_RED; + } else if(strncmp(&data[7], "G", 1) == 0) { + led = LEDS_GREEN; + } else if(strncmp(&data[7], "B", 1) == 0) { + led = LEDS_BLUE; + } else { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + if(state) { + leds_on(led); + } else { + leds_off(led); + } + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_gpio_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + /* Format: AT&GPIO=PN,s where P(ort)N(number), s(tate)=1/0 */ + uint8_t port; + uint8_t state = strncmp(&data[11], "1", 1) ? 0 : 1; + uint8_t pin = atoi(&data[9]); + + if(strncmp(&data[10], ",", 1) != 0) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + if((pin < 0) || (pin > 7)) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + if((state < 0) || (state > 1)) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + if(strncmp(&data[8], "A", 1) == 0) { + port = GPIO_A_NUM; + } else if(strncmp(&data[8], "B", 1) == 0) { + port = GPIO_B_NUM; + } else if(strncmp(&data[8], "C", 1) == 0) { + port = GPIO_C_NUM; + } else if(strncmp(&data[8], "D", 1) == 0) { + port = GPIO_D_NUM; + } else { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + config_gpio(port, pin, HWTEST_GPIO_OUTPUT); + + if(state) { + GPIO_SET_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); + } else { + GPIO_CLR_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); + } + + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_adc_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + /* Format: AT&ADC=N where N is 4-7, it can be "*" to read all */ + uint8_t i, pin; + uint16_t res[4]; + char read_result[24]; + + if(strncmp(&data[7], "*", 1) == 0) { + pin = 8; + } else { + pin = atoi(&data[7]); + } + + if((pin < 4) || (pin > 8)) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + if(pin < 8) { + config_gpio(GPIO_A_NUM, pin, HWTEST_GPIO_INPUT); + ioc_set_over(GPIO_A_NUM, pin, IOC_OVERRIDE_ANA); + res[pin - 4] = adc_get((SOC_ADC_ADCCON_CH_AIN0 + pin), + SOC_ADC_ADCCON_REF_AVDD5, + SOC_ADC_ADCCON_DIV_512); + res[pin - 4] = res[pin - 4] / 10; + PRINTF("ADC%u: %04d\n", pin, res[pin - 4]); + snprintf(read_result, 5, "%04d", res[pin - 4]); + } else { + for(i = 4; i < 8; i++) { + config_gpio(GPIO_A_NUM, i, HWTEST_GPIO_INPUT); + ioc_set_over(GPIO_A_NUM, i, IOC_OVERRIDE_ANA); + res[i - 4] = adc_get((SOC_ADC_ADCCON_CH_AIN0 + i), + SOC_ADC_ADCCON_REF_AVDD5, + SOC_ADC_ADCCON_DIV_512); + res[i - 4] = res[i - 4] / 10; + } + snprintf(read_result, 24, "%04d %04d %04d %04d", res[0], res[1], + res[2], res[3]); + } + + AT_RESPONSE(read_result); + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_read_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + /* Format: AT&READ=PN where P(ort)N(number), N can be "*" to read all */ + uint8_t port, pin; + char read_result[5]; + + if(strncmp(&data[9], "*", 1) == 0) { + pin = 0xFF; + } else { + pin = atoi(&data[9]); + } + + if((pin < 0) || (pin > 7)) { + if(pin != 0xFF) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + } + + if(pin < 8) { + pin = GPIO_PIN_MASK(pin); + } + + /* Exclude PA0-PA3 */ + if(strncmp(&data[8], "A", 1) == 0) { + port = GPIO_A_NUM; + if(pin < 0x1F) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } else { + if(pin == 0xFF) { + pin = 0xF0; + } + } + } else if(strncmp(&data[8], "B", 1) == 0) { + port = GPIO_B_NUM; + } else if(strncmp(&data[8], "C", 1) == 0) { + port = GPIO_C_NUM; + } else if(strncmp(&data[8], "D", 1) == 0) { + port = GPIO_D_NUM; + } else { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + config_gpio(port, pin, HWTEST_GPIO_INPUT); + snprintf(read_result, 5, "0x%02X", + (uint16_t)GPIO_READ_PIN(GPIO_PORT_TO_BASE(port), pin)); + AT_RESPONSE(read_result); + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_sha256_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + /* Format: AT&SHA256=s, where s is a string up to 64 bytes */ + uint8_t i; + char tmp[4], sha256[32], sha256_res[64]; + static sha256_state_t state; + + crypto_init(); + if(sha256_init(&state) != CRYPTO_SUCCESS) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + if(sha256_process(&state, &data[10], + len - (cmd->cmd_hdr_len)) != CRYPTO_SUCCESS) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + if(sha256_done(&state, sha256) != CRYPTO_SUCCESS) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + crypto_disable(); + + PRINTF("Input: %s:\n", &data[10]); + snprintf(tmp, 3, "%02X", sha256[0]); + strncpy(sha256_res, tmp, 3); + for(i = 1; i < 32; i++) { + PRINTF("0x%02X ", sha256[i]); + snprintf(tmp, 3, "%02X", sha256[i]); + strcat(sha256_res, tmp); + } + PRINTF("\nSHA256: %s\n", sha256_res); + AT_RESPONSE(sha256_res); + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(at_test_process, ev, data) +{ + PROCESS_BEGIN(); + struct at_cmd *a; + + /* Initialize the driver, default is UART0 */ + at_init(0); + + /* Register a list of commands, is mandatory to start with "AT" */ + at_register(&at_cmd_test, &at_test_process, "AT", 2, 2, + at_cmd_test_callback); + at_register(&at_cmd_board, &at_test_process, "AT&V", 4, 4, + at_cmd_board_callback); + at_register(&at_cmd_led, &at_test_process, "AT&LED", 6, 10, + at_cmd_leds_callback); + at_register(&at_cmd_addr, &at_test_process, "AT&A", 4, 4, + at_cmd_address_callback); + at_register(&at_cmd_gpio, &at_test_process, "AT&GPIO=", 8, 12, + at_cmd_gpio_callback); + at_register(&at_cmd_read, &at_test_process, "AT&READ=", 8, 10, + at_cmd_read_callback); + at_register(&at_cmd_adc, &at_test_process, "AT&ADC=", 7, 8, + at_cmd_adc_callback); + at_register(&at_cmd_flop, &at_test_process, "AT&FLOP=", 8, 10, + at_cmd_flop_callback); + at_register(&at_cmd_reset, &at_test_process, "AT&RESET=", 9, 10, + at_cmd_reset_callback); + at_register(&at_cmd_sha256, &at_test_process, "AT&SHA256=", 10, 64, + at_cmd_sha256_callback); + + /* Print the command list */ + PRINTF("AT command list:\n"); + for(a = at_list(); a != NULL; a = list_item_next(a)) { + PRINTF("* HDR %s LEN %u MAX %u\n", a->cmd_header, a->cmd_hdr_len, + a->cmd_max_len); + } + + /* + * When an AT command is received over the serial line, the registered + * callbacks will be invoked, let the process spin until then + */ + while(1) { + PROCESS_YIELD(); + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + * @} + */ diff --git a/examples/zolertia/zoul/at-test/project-conf.h b/examples/zolertia/zoul/at-test/project-conf.h new file mode 100644 index 000000000..4a29f1d59 --- /dev/null +++ b/examples/zolertia/zoul/at-test/project-conf.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016, Zolertia - http://www.zolertia.com + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup remote-examples + * @{ + * + * \defgroup zoul-AT-master-test + * + * Test the Zoul hardware over AT API + * @{ + * + * \file + * Test the Zoul hardware over AT API + * + * \author + * Antonio Lignan + */ +/*---------------------------------------------------------------------------*/ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +/* Drop maximum to PM1 to have the UART on all the time */ +#define LPM_CONF_MAX_PM 1 + +/* the radio is not used */ +#define CONTIKI_NO_NET 1 + +/* Override serial-line defaults */ +#define SERIAL_LINE_CONF_BUFSIZE 128 +#undef IGNORE_CHAR +#undef END +#define IGNORE_CHAR(c) (c == 0x0d) +#define END 0x0a + +#define NETSTACK_CONF_RDC nullrdc_driver + +#endif /* PROJECT_CONF_H_ */ + +/** @} */