From 8c26f252fef5bc204297e2319c0fb3353bec3199 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sun, 30 Nov 2014 14:44:50 +0100 Subject: o Initial import. --- Makefile | 14 +++ fiken_status_panel.ino | 330 +++++++++++++++++++++++++++++++++++++++++++++++++ fiken_status_panel.xml | 116 +++++++++++++++++ services.h | 154 +++++++++++++++++++++++ 4 files changed, 614 insertions(+) create mode 100644 Makefile create mode 100644 fiken_status_panel.ino create mode 100644 fiken_status_panel.xml create mode 100644 services.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..03e0b0f --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +BOARD_TAG = leonardo +#BOARD_TAG = blendmicro16 +#DEVICE_PORT = /dev/ttyACM0 +MONITOR_BAUDRATE = 115200 +MONITOR_PORT ?= /dev/ttyACM0 + +ARDUINO_LIBS = BLE SPI + +ARDMK_DIR ?= /usr/share/arduino +include $(ARDMK_DIR)/Arduino.mk + +#/usr/share/arduino/hardware/tools/avr/bin/avr-g++ -x c++ -include Arduino.h -MMD -c -mmcu=atmega32u4 -DF_CPU=16000000L -DARDUINO=105 -D__PROG_TYPES_COMPAT__ -I. -I/usr/share/arduino/hardware/arduino/cores/arduino -I/usr/share/arduino/hardware/arduino/variants/leonardo -I/usr/share/arduino/libraries/SPI -I/home/trygvis/sketchbook/libraries/BLE -Wall -ffunction-sections -fdata-sections -Os -DUSB_VID=0x2341 -DUSB_PID=0x8036 -fno-exceptions bitraf_door.ino -o build-leonardo/bitraf_door.o + +#/home/trygvis/opt/arduino-1.0.5/hardware/tools/avr/bin/avr-g++ -c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega32u4 -DF_CPU=8000000L -MMD -DUSB_VID=0x03EB -DUSB_PID=0x2404 -DARDUINO=105 -I/home/trygvis/opt/arduino-1.0.5/hardware/arduino/cores/arduino -I/home/trygvis/sketchbook/hardware/blend/variants/BlendMicro-8MHz -I/home/trygvis/opt/arduino-1.0.5/libraries/SPI -I/home/trygvis/sketchbook/libraries/BLE /tmp/build8653612679895592527.tmp/bitraf_door.cpp -o /tmp/build8653612679895592527.tmp/bitraf_door.cpp.o diff --git a/fiken_status_panel.ino b/fiken_status_panel.ino new file mode 100644 index 0000000..6283201 --- /dev/null +++ b/fiken_status_panel.ino @@ -0,0 +1,330 @@ +#include +#include +#include + +#include "services.h" + +static services_pipe_type_mapping_t services_pipe_type_mapping[NUMBER_OF_PIPES] = SERVICES_PIPE_TYPE_MAPPING_CONTENT; +static hal_aci_data_t setup_msgs[NB_SETUP_MESSAGES] PROGMEM = SETUP_MESSAGES_CONTENT; + +static struct aci_state_t aci_state; +static hal_aci_evt_t aci_data; +static bool timing_change_done = false; + +void __ble_assert(const char *file, uint16_t line) +{ + Serial.print("ERROR "); + Serial.print(file); + Serial.print(": "); + Serial.print(line); + Serial.print("\n"); + while(1); +} + +void setup() { +#if defined(BLEND_MICRO_8MHZ) + // As the F_CPU = 8000000UL, the USB core make the PLLCSR = 0x02 + // But the external xtal is 16000000Hz, so correct it here. + PLLCSR |= 0x10; // Need 16 MHz xtal + while (!(PLLCSR & (1<evt_opcode) { + /** + As soon as you reset the nRF8001 you will get an ACI Device Started Event + */ + case ACI_EVT_DEVICE_STARTED: + Serial.println(F("ACI_EVT_DEVICE_STARTED")); + aci_state.data_credit_total = aci_evt->params.device_started.credit_available; + switch(aci_evt->params.device_started.device_mode) { + case ACI_DEVICE_SETUP: + Serial.println(F("ACI_DEVICE_SETUP")); + setup_required = true; + break; + + case ACI_DEVICE_STANDBY: + Serial.println(F("ACI_DEVICE_STANDBY")); + //Looking for an iPhone by sending radio advertisements + //When an iPhone connects to us we will get an ACI_EVT_CONNECTED event from the nRF8001 + if (aci_evt->params.device_started.hw_error) { + delay(20); //Magic number used to make sure the HW error event is handled correctly. + } + else { + lib_aci_connect(180/* in seconds */, 0x0050 /* advertising interval 50ms*/); + Serial.println(F("Advertising started")); + } + break; + case ACI_DEVICE_INVALID: + case ACI_DEVICE_TEST: + case ACI_DEVICE_SLEEP: + // ignored + break; + } + break; + + case ACI_EVT_CMD_RSP: +// Serial.println(F("ACI_EVT_CMD_RSP")); +// Serial.print(F("aci_evt->params.cmd_rsp.cmd_opcode=")); +// Serial.println(aci_evt->params.cmd_rsp.cmd_opcode, HEX); +// Serial.print(F("aci_evt->params.cmd_rsp.cmd_status=")); +// Serial.println(aci_evt->params.cmd_rsp.cmd_status, HEX); + + //If an ACI command response event comes with an error -> stop + if (aci_evt->params.cmd_rsp.cmd_status != ACI_STATUS_SUCCESS) { + //ACI ReadDynamicData and ACI WriteDynamicData will have status codes of + //TRANSACTION_CONTINUE and TRANSACTION_COMPLETE + //all other ACI commands will have status code of ACI_STATUS_SCUCCESS for a successful command// +// Serial.print(F("ACI Command ")); +// Serial.println(aci_evt->params.cmd_rsp.cmd_opcode, HEX); +// Serial.print(F("Evt Cmd respone: Status ")); +// Serial.println(aci_evt->params.cmd_rsp.cmd_status, HEX); + } + if (aci_evt->params.cmd_rsp.cmd_opcode == ACI_CMD_GET_DEVICE_VERSION) { + //Store the version and configuration information of the nRF8001 in the Hardware Revision String Characteristic +// lib_aci_set_local_data(&aci_state, PIPE_DEVICE_INFORMATION_HARDWARE_REVISION_STRING_SET, +// (uint8_t *)&(aci_evt->params.cmd_rsp.params.get_device_version), +// sizeof(aci_evt_cmd_rsp_params_get_device_version_t)); + } + break; + + case ACI_EVT_CONNECTED: + Serial.println(F("ACI_EVT_CONNECTED")); +// uart_over_ble_init(); + timing_change_done = false; + aci_state.data_credit_available = aci_state.data_credit_total; + + // Get the device version of the nRF8001 and store it in the Hardware Revision String + lib_aci_device_version(); + break; + + case ACI_EVT_PIPE_STATUS: + Serial.println(F("ACI_EVT_PIPE_STATUS")); + /* + if (lib_aci_is_pipe_available(&aci_state, PIPE_UART_OVER_BTLE_UART_TX_TX) && (false == timing_change_done)) + { + lib_aci_change_timing_GAP_PPCP(); // change the timing on the link as specified in the nRFgo studio -> nRF8001 conf. -> GAP. + // Used to increase or decrease bandwidth + timing_change_done = true; + } + */ + break; + + case ACI_EVT_TIMING: + Serial.println(F("ACI_EVT_TIMING")); +// lib_aci_set_local_data(&aci_state, +// PIPE_UART_OVER_BTLE_UART_LINK_TIMING_CURRENT_SET, +// (uint8_t *)&(aci_evt->params.timing.conn_rf_interval), /* Byte aligned */ +// PIPE_UART_OVER_BTLE_UART_LINK_TIMING_CURRENT_SET_MAX_SIZE); + break; + + case ACI_EVT_DISCONNECTED: + Serial.println(F("ACI_EVT_DISCONNECTED")); + lib_aci_connect(180/* in seconds */, 0x0100 /* advertising interval 100ms*/); + Serial.println(F("Advertising started")); + break; + + case ACI_EVT_DATA_RECEIVED: + Serial.print(F("ACI_EVT_DATA_RECEIVED: pipe_number=")); + Serial.println(aci_evt->params.data_received.rx_data.pipe_number, DEC); + if (aci_evt->params.data_received.rx_data.pipe_number == PIPE_FIKEN_STATUS_PANEL_GAUGE_RX_ACK) { + if (aci_evt->len != PIPE_FIKEN_STATUS_PANEL_GAUGE_RX_ACK_MAX_SIZE) { + break; + } + set_gauge_req(aci_evt->params.data_received.rx_data.aci_data); + lib_aci_send_ack(&aci_state, PIPE_FIKEN_STATUS_PANEL_GAUGE_RX_ACK); + } + /* + if (PIPE_UART_OVER_BTLE_UART_RX_RX == aci_evt->params.data_received.rx_data.pipe_number) + { + Serial.print(F(" Data(Hex) : ")); + for(int i=0; ilen - 2; i++) + { + Serial.print((char)aci_evt->params.data_received.rx_data.aci_data[i]); + uart_buffer[i] = aci_evt->params.data_received.rx_data.aci_data[i]; + Serial.print(F(" ")); + } + + uart_buffer_len = aci_evt->len - 2; + Serial.println(F("")); + if (lib_aci_is_pipe_available(&aci_state, PIPE_UART_OVER_BTLE_UART_TX_TX)) + { + } + } + if (PIPE_UART_OVER_BTLE_UART_CONTROL_POINT_RX == aci_evt->params.data_received.rx_data.pipe_number) + { + uart_process_control_point_rx(&aci_evt->params.data_received.rx_data.aci_data[0], aci_evt->len - 2); //Subtract for Opcode and Pipe number + } + */ + break; + + case ACI_EVT_DATA_CREDIT: + Serial.println(F("ACI_EVT_DATA_CREDIT")); + aci_state.data_credit_available = aci_state.data_credit_available + aci_evt->params.data_credit.credit; + break; + + case ACI_EVT_PIPE_ERROR: + Serial.println(F("ACI_EVT_PIPE_ERROR")); + //See the appendix in the nRF8001 Product Specication for details on the error codes + Serial.print(F("ACI Evt Pipe Error: Pipe #:")); + Serial.print(aci_evt->params.pipe_error.pipe_number, DEC); + Serial.print(F(" Pipe Error Code: 0x")); + Serial.println(aci_evt->params.pipe_error.error_code, HEX); + + //Increment the credit available as the data packet was not sent. + //The pipe error also represents the Attribute protocol Error Response sent from the peer and that should not be counted + //for the credit. + if (ACI_STATUS_ERROR_PEER_ATT_ERROR != aci_evt->params.pipe_error.error_code) + { + aci_state.data_credit_available++; + } + break; + + case ACI_EVT_HW_ERROR: + Serial.println(F("ACI_EVT_HW_ERROR")); + Serial.print(F("HW error: ")); + Serial.println(aci_evt->params.hw_error.line_num, DEC); + + for(uint8_t counter = 0; counter <= (aci_evt->len - 3); counter++) + { + Serial.write(aci_evt->params.hw_error.file_name[counter]); //uint8_t file_name[20]; + } + Serial.println(); + lib_aci_connect(180/* in seconds */, 0x0050 /* advertising interval 50ms*/); + Serial.println(F("Advertising started")); + break; + + case ACI_EVT_INVALID: + Serial.println(F("ACI_EVT_INVALID")); + break; + case ACI_EVT_ECHO: + Serial.println(F("ACI_EVT_ECHO")); + break; + case ACI_EVT_BOND_STATUS: + Serial.println(F("ACI_EVT_BOND_STATUS")); + break; + case ACI_EVT_DATA_ACK: + Serial.println(F("ACI_EVT_DATA_ACK")); + break; + case ACI_EVT_DISPLAY_PASSKEY: + Serial.println(F("ACI_EVT_DISPLAY_PASSKEY")); + break; + case ACI_EVT_KEY_REQUEST: + Serial.println(F("ACI_EVT_KEY_REQUEST")); + break; + } + } + else { +// Serial.println(F("No ACI Events available")); + // No event in the ACI Event queue and if there is no event in the ACI command queue the arduino can go to sleep + // Arduino can go to sleep now + // Wakeup from sleep from the RDYN line + } + + /* setup_required is set to true when the device starts up and enters setup mode. + * It indicates that do_aci_setup() should be called. The flag should be cleared if + * do_aci_setup() returns ACI_STATUS_TRANSACTION_COMPLETE. + */ + if (setup_required) { + int ret = do_aci_setup(&aci_state); +// Serial.print(F("ret=")); +// Serial.println(ret, DEC); + if (SETUP_SUCCESS == ret) { + setup_required = false; + } + } +} + +void set_gauge_req(uint8_t *data) { + Serial.print(F("set_gauge_req, channel=")); + Serial.print(data[0], DEC); + Serial.print(F(", value=")); + Serial.println(data[1], DEC); +} + +static uint8_t value = 0; +void loop() { + static unsigned long last = 0, now; + + //Process any ACI commands or events + aci_loop(); + + if (Serial.available()) { + Serial.write(Serial.read()); + } + + if (!setup_required) { + now = millis(); + if (now - last > 3000) { + value++; + lib_aci_set_local_data(&aci_state, PIPE_FIKEN_STATUS_PANEL_GAUGE_SET, &value, 1); + last = now; + Serial.print(F("value=")); + Serial.println(value, DEC); + } + } +} + diff --git a/fiken_status_panel.xml b/fiken_status_panel.xml new file mode 100644 index 0000000..d86c69f --- /dev/null +++ b/fiken_status_panel.xml @@ -0,0 +1,116 @@ + + + + 1 + nRF8001_Dx + + Fiken Status Panel + 0001 + + Gauge + 0002 + 1234 + 0 + 2 + 1 + false + false + + false + true + false + false + false + + true + false + + 0 + + + + Led + 0003 + 0 + 0 + 3 + 1 + false + false + + false + true + false + false + false + + false + false + + 0 + + + + + Fiken Display + 13 + true + 0 + 0000 + 0 + 0 + 0 + 600 + 10 + 7 + 16 + 0 + 5a + 40 + 0 + 5a + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 65535 + 65535 + 0 + 65535 + false + false + 5 + + + 19 + 0000 + + + 18 + + + + + + 0 + 1 + 3 + 0 + 0 + 0 + 0 + false + + + 220 + 10 + 1000 + 70.12 + 6.94 + 1280 + + diff --git a/services.h b/services.h new file mode 100644 index 0000000..fad505a --- /dev/null +++ b/services.h @@ -0,0 +1,154 @@ +/** +* This file is autogenerated by nRFgo Studio 1.17.1.3252 +*/ + +#ifndef SETUP_MESSAGES_H__ +#define SETUP_MESSAGES_H__ + +#include "hal_platform.h" +#include "aci.h" + + +#define SETUP_ID 1 +#define SETUP_FORMAT 3 /** nRF8001 D */ +#define ACI_DYNAMIC_DATA_SIZE 133 + +/* Service: Gap - Characteristic: Device name - Pipe: SET */ +#define PIPE_GAP_DEVICE_NAME_SET 1 +#define PIPE_GAP_DEVICE_NAME_SET_MAX_SIZE 13 + +/* Service: Fiken Status Panel - Characteristic: Gauge - Pipe: RX_ACK */ +#define PIPE_FIKEN_STATUS_PANEL_GAUGE_RX_ACK 2 +#define PIPE_FIKEN_STATUS_PANEL_GAUGE_RX_ACK_MAX_SIZE 2 + +/* Service: Fiken Status Panel - Characteristic: Gauge - Pipe: SET */ +#define PIPE_FIKEN_STATUS_PANEL_GAUGE_SET 3 +#define PIPE_FIKEN_STATUS_PANEL_GAUGE_SET_MAX_SIZE 2 + +/* Service: Fiken Status Panel - Characteristic: Led - Pipe: RX_ACK */ +#define PIPE_FIKEN_STATUS_PANEL_LED_RX_ACK 4 +#define PIPE_FIKEN_STATUS_PANEL_LED_RX_ACK_MAX_SIZE 3 + + +#define NUMBER_OF_PIPES 4 + +#define SERVICES_PIPE_TYPE_MAPPING_CONTENT {\ + {ACI_STORE_LOCAL, ACI_SET}, \ + {ACI_STORE_LOCAL, ACI_RX_ACK}, \ + {ACI_STORE_LOCAL, ACI_SET}, \ + {ACI_STORE_LOCAL, ACI_RX_ACK}, \ +} + +#define GAP_PPCP_MAX_CONN_INT 0xffff /**< Maximum connection interval as a multiple of 1.25 msec , 0xFFFF means no specific value requested */ +#define GAP_PPCP_MIN_CONN_INT 0xffff /**< Minimum connection interval as a multiple of 1.25 msec , 0xFFFF means no specific value requested */ +#define GAP_PPCP_SLAVE_LATENCY 0 +#define GAP_PPCP_CONN_TIMEOUT 0xffff /** Connection Supervision timeout multiplier as a multiple of 10msec, 0xFFFF means no specific value requested */ + +#define NB_SETUP_MESSAGES 18 +#define SETUP_MESSAGES_CONTENT {\ + {0x00,\ + {\ + 0x07,0x06,0x00,0x00,0x03,0x02,0x42,0x07,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x10,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x04,0x00,0x01,0x00,0x00,0x06,0x00,0x00,\ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x10,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x03,0x90,0x01,0xff,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x10,0x38,0xff,0xff,0x02,0x58,0x0a,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x00,0x00,\ + 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x05,0x06,0x10,0x54,0x00,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0x00,0x04,0x04,0x02,0x02,0x00,0x01,0x28,0x00,0x01,0x00,0x18,0x04,0x04,0x05,0x05,0x00,\ + 0x02,0x28,0x03,0x01,0x0e,0x03,0x00,0x00,0x2a,0x04,0x14,0x0d,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0x1c,0x0d,0x00,0x03,0x2a,0x00,0x01,0x46,0x69,0x6b,0x65,0x6e,0x20,0x44,0x69,0x73,0x70,\ + 0x6c,0x61,0x79,0x04,0x04,0x05,0x05,0x00,0x04,0x28,0x03,0x01,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0x38,0x02,0x05,0x00,0x01,0x2a,0x06,0x04,0x03,0x02,0x00,0x05,0x2a,0x01,0x01,0x00,0x00,\ + 0x04,0x04,0x05,0x05,0x00,0x06,0x28,0x03,0x01,0x02,0x07,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0x54,0x04,0x2a,0x06,0x04,0x09,0x08,0x00,0x07,0x2a,0x04,0x01,0xff,0xff,0xff,0xff,0x00,\ + 0x00,0xff,0xff,0x04,0x04,0x02,0x02,0x00,0x08,0x28,0x00,0x01,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0x70,0x01,0x18,0x04,0x04,0x10,0x10,0x00,0x09,0x28,0x00,0x01,0x3f,0xd8,0x1f,0x4a,0x8e,\ + 0xbc,0xd3,0x70,0xc5,0x59,0x5d,0x03,0x01,0x00,0xd0,0x32,0x04,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0x8c,0x04,0x13,0x13,0x00,0x0a,0x28,0x03,0x01,0x0e,0x0b,0x00,0x3f,0xd8,0x1f,0x4a,0x8e,\ + 0xbc,0xd3,0x70,0xc5,0x59,0x5d,0x03,0x02,0x00,0xd0,0x32,0x46,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x20,0xa8,0x14,0x03,0x02,0x00,0x0b,0x00,0x02,0x02,0x12,0x34,0x04,0x04,0x13,0x13,0x00,0x0c,\ + 0x28,0x03,0x01,0x0a,0x0d,0x00,0x3f,0xd8,0x1f,0x4a,0x8e,0xbc,\ + },\ + },\ + {0x00,\ + {\ + 0x1a,0x06,0x20,0xc4,0xd3,0x70,0xc5,0x59,0x5d,0x03,0x03,0x00,0xd0,0x32,0x46,0x14,0x04,0x03,0x00,0x0d,\ + 0x00,0x03,0x02,0x00,0x00,0x00,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x1f,0x06,0x40,0x00,0x2a,0x00,0x01,0x00,0x80,0x04,0x00,0x03,0x00,0x00,0x00,0x02,0x02,0x00,0x90,0x04,\ + 0x00,0x0b,0x00,0x00,0x00,0x03,0x02,0x00,0x10,0x04,0x00,0x0d,\ + },\ + },\ + {0x00,\ + {\ + 0x05,0x06,0x40,0x1c,0x00,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x13,0x06,0x50,0x00,0x3f,0xd8,0x1f,0x4a,0x8e,0xbc,0xd3,0x70,0xc5,0x59,0x5d,0x03,0x00,0x00,0xd0,0x32,\ + },\ + },\ + {0x00,\ + {\ + 0x0c,0x06,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\ + },\ + },\ + {0x00,\ + {\ + 0x06,0x06,0xf0,0x00,0x03,0xf7,0x6c,\ + },\ + },\ +} + +#endif + -- cgit v1.2.3