summaryrefslogtreecommitdiff
path: root/fiken_status_panel.ino
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2014-11-30 14:44:50 +0100
committerTrygve Laugstøl <trygvis@inamo.no>2014-11-30 14:44:50 +0100
commit8c26f252fef5bc204297e2319c0fb3353bec3199 (patch)
tree9655103e461ef805aff33e49ca1ca422c172f4b5 /fiken_status_panel.ino
downloadfiken_status_panel-8c26f252fef5bc204297e2319c0fb3353bec3199.tar.gz
fiken_status_panel-8c26f252fef5bc204297e2319c0fb3353bec3199.tar.bz2
fiken_status_panel-8c26f252fef5bc204297e2319c0fb3353bec3199.tar.xz
fiken_status_panel-8c26f252fef5bc204297e2319c0fb3353bec3199.zip
o Initial import.
Diffstat (limited to 'fiken_status_panel.ino')
-rw-r--r--fiken_status_panel.ino330
1 files changed, 330 insertions, 0 deletions
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 <SPI.h>
+#include <lib_aci.h>
+#include <aci_setup.h>
+
+#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<<PLOCK))); // wait for lock pll
+#elif defined(BLEND_MICRO_16MHZ)
+ // The CPU clock in bootloader is 8MHz, change to 16MHz for sketches to run (i.e. overclock running at 3.3v).
+ CLKPR = 0x80;
+ CLKPR = 0;
+#endif
+
+ Serial.begin((unsigned int)115200);
+
+ //Wait until the serial port is available (useful only for the Leonardo)
+ //As the Leonardo board is not reseted every time you open the Serial Monitor
+ #if defined (__AVR_ATmega32U4__)
+ while(!Serial) {}
+ #elif defined(__PIC32MX__)
+ delay(1000);
+ #endif
+
+ Serial.println(F("setup()"));
+
+ // Point ACI data structures to the the setup data that the nRFgo studio generated for the nRF8001
+ if (NULL != services_pipe_type_mapping) {
+ aci_state.aci_setup_info.services_pipe_type_mapping = &services_pipe_type_mapping[0];
+ }
+ else {
+ aci_state.aci_setup_info.services_pipe_type_mapping = NULL;
+ }
+ aci_state.aci_setup_info.number_of_pipes = NUMBER_OF_PIPES;
+ aci_state.aci_setup_info.setup_msgs = (hal_aci_data_t*)setup_msgs;
+ aci_state.aci_setup_info.num_setup_msgs = NB_SETUP_MESSAGES;
+
+ /*
+ Tell the ACI library, the MCU to nRF8001 pin connections.
+ The Active pin is optional and can be marked UNUSED
+ */
+ aci_state.aci_pins.board_name = REDBEARLAB_SHIELD_V2;
+ aci_state.aci_pins.reqn_pin = 6;
+ aci_state.aci_pins.rdyn_pin = 7;
+ aci_state.aci_pins.mosi_pin = MOSI;
+ aci_state.aci_pins.miso_pin = MISO;
+ aci_state.aci_pins.sck_pin = SCK;
+
+ aci_state.aci_pins.spi_clock_divider = SPI_CLOCK_DIV8;//SPI_CLOCK_DIV8 = 2MHz SPI speed
+ //SPI_CLOCK_DIV16 = 1MHz SPI speed
+
+ aci_state.aci_pins.reset_pin = UNUSED; //4 for Nordic board, UNUSED for REDBEARLAB_SHIELD_V1_1
+ aci_state.aci_pins.active_pin = UNUSED;
+ aci_state.aci_pins.optional_chip_sel_pin = UNUSED;
+
+ aci_state.aci_pins.interface_is_interrupt = false; //Interrupts still not available in Chipkit
+ aci_state.aci_pins.interrupt_number = 4;
+
+ //We reset the nRF8001 here by toggling the RESET line connected to the nRF8001
+ //If the RESET line is not available we call the ACI Radio Reset to soft reset the nRF8001
+ //then we initialize the data structures required to setup the nRF8001
+ //The second parameter is for turning debug printing on for the ACI Commands and Events so they be printed on the Serial
+ lib_aci_init(&aci_state, false);
+ Serial.println(F("lib_aci_init done"));
+}
+
+static bool setup_required = false;
+
+static void aci_loop() {
+ // We enter the if statement only when there is a ACI event available to be processed
+ if (lib_aci_event_get(&aci_state, &aci_data)) {
+ aci_evt_t * aci_evt;
+ aci_evt = &aci_data.evt;
+
+ switch(aci_evt->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; i<aci_evt->len - 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);
+ }
+ }
+}
+