summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LiquidCrystal.c197
-rw-r--r--LiquidCrystal.h16
-rw-r--r--Makefile2
-rw-r--r--main.c38
-rw-r--r--nrf51.md101
-rw-r--r--phone_remote.c2
6 files changed, 260 insertions, 96 deletions
diff --git a/LiquidCrystal.c b/LiquidCrystal.c
index becc07e..eed30c8 100644
--- a/LiquidCrystal.c
+++ b/LiquidCrystal.c
@@ -1,13 +1,14 @@
#include "LiquidCrystal.h"
+#include "nrf_delay.h"
+#include "nrf_error.h"
#include "nrf_gpio.h"
-#include "app_timer.h"
/*
* Arduino | LCD | nrf51
* D4 | DB4 | P0.16
* D5 | DB5 | P0.17
* D6 | DB6 | P0.18
- * D7 | DB7 | P0.10
+ * D7 | DB7 | P0.19
* D8 | RS | P0.20, register select. 0=instruction (write), 0=busy (read), 1=data
* D9 | EN | P0.23, clock, data is clocked in/out on falling edge
* D10 | DB4 | P0.24
@@ -31,103 +32,109 @@ static struct {
uint8_t pin_db7;
uint8_t pin_rs;
uint8_t pin_en;
-
- app_gpiote_user_id_t gpio_user_id;
} data = { .pin_db4 = 16, .pin_db5 = 17, .pin_db6 = 18, .pin_db7 = 19, .pin_rs =
20, .pin_en = 23, };
-static uint32_t ticks_per_ms;
-
-static void event_handler() {
-}
-
-static void wait_ms(uint32_t ms) {
- uint32_t ticks;
-
- app_timer_cnt_get(&ticks);
-
- const uint32_t end_ticks = ticks + ms * ticks_per_ms;
-
- do {
- app_timer_cnt_get(&ticks);
- } while (ticks < end_ticks);
-}
-
static void write_4(uint8_t value) {
nrf_gpio_pin_write(data.pin_db4, value & 0x01);
nrf_gpio_pin_write(data.pin_db5, value & 0x02);
nrf_gpio_pin_write(data.pin_db6, value & 0x04);
nrf_gpio_pin_write(data.pin_db7, value & 0x08);
+ nrf_delay_us(10);
nrf_gpio_pin_set(data.pin_en);
+ nrf_delay_us(10); // 450ns is supposed to be sufficient
nrf_gpio_pin_clear(data.pin_en);
}
-static void write_value(uint8_t value, bool is_data) {
+static void write_value(uint8_t value, bool is_data, uint32_t delay) {
nrf_gpio_pin_write(data.pin_rs, is_data);
write_4(value >> 4);
write_4(value);
-}
-
-static void begin() {
- nrf_gpio_pin_clear(data.pin_rs);
- nrf_gpio_pin_clear(data.pin_en);
- // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
- // according to datasheet, we need at least 40ms after power rises above 2.7V
- // before sending commands. Arduino can turn on way before 4.5V so we'll wait 50
- wait_ms(50);
-
- write_4(0x03);
- wait_ms(5); // 4.5ms
-
- write_4(0x03);
- wait_ms(5); // 4.5ms
-
- write_4(0x03);
- wait_ms(5); // 4.5ms
-
- write_4(0x02);
-
- write_value(LIQUID_CRYSTAL_CMD_DISPLAY, false);
-
-// _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
- liquid_crystal_display(true, true, true);
+ nrf_delay_us(delay);
}
void liquid_crystal_write_char(char chr) {
- write_value(chr, true);
+ write_value(chr, true, 50);
}
void liquid_crystal_write_string(char *chr) {
- while (*chr != '\0') {
+ for (; *chr != '\0'; chr++) {
liquid_crystal_write_char(*chr);
}
}
-uint32_t liquid_crystal_display(bool display_on, bool cursor_on, bool blink) {
- uint8_t value = LIQUID_CRYSTAL_CMD_DISPLAY;
-
- value |= display_on ? 0x04 : 0x00;
- value |= cursor_on ? 0x02 : 0x00;
- value |= blink ? 0x01 : 0x00;
-
- write_value(value, false);
-
- return NRF_SUCCESS;
+void liquid_crystal_clear() {
+ // The documentation doesn't specify a value, but everything else is 37us
+ write_value(LIQUID_CRYSTAL_CMD_CLEAR, false, 50);
}
-uint32_t liquid_crystal_init(uint32_t _ticks_per_ms) {
- ticks_per_ms = _ticks_per_ms;
+void liquid_crystal_return_home() {
+ write_value(LIQUID_CRYSTAL_CMD_RETURN_HOME, false, 2000);
+}
- uint32_t err_code = app_gpiote_user_register(&data.gpio_user_id, 0x0000,
- 0x0000, event_handler);
+static struct {
+ union {
+ uint8_t value;
+ struct {
+ bool shift :1;
+ bool increment :1;
+ int :6;
+ } fields __attribute__((packed));
+ };
+}__attribute__((packed)) entry_mode_state;
+
+void liquid_crystal_entry_mode_set(bool increment, bool shift) {
+ /*
+ uint8_t value = LIQUID_CRYSTAL_CMD_ENTRY_MODE_SET;
+
+ value |= increment ? 0x02 : 0x00;
+ value |= shift ? 0x01 : 0x00;
+
+ write_value(value, false);
+ */
+
+ entry_mode_state.fields.increment = increment;
+ entry_mode_state.fields.shift = shift;
+ write_value(entry_mode_state.value, false, 50);
+}
- if (err_code != NRF_SUCCESS) {
- return err_code;
- }
+static struct {
+ union {
+ uint8_t value;
+ struct {
+ bool blink :1;
+ bool cursor_on :1;
+ bool display_on :1;
+ int :5;
+ } fields __attribute__((packed));
+ };
+}__attribute__((packed)) display_state;
+
+void liquid_crystal_display(bool display_on, bool cursor_on, bool blink) {
+ display_state.fields.display_on = display_on;
+ display_state.fields.cursor_on = cursor_on;
+ display_state.fields.blink = blink;
+
+ write_value(display_state.value, false, 50);
+}
+static struct {
+ union {
+ uint8_t value;
+ struct {
+ int :2;
+ bool many_dots :1;
+ bool two_line :1;
+ bool data_length :1;
+ int :3;
+ } fields __attribute__((packed));
+ };
+}__attribute__((packed)) function_set_state;
+
+void liquid_crystal_init(bool data_length, bool two_line, bool many_dots) {
nrf_gpio_cfg_output(data.pin_db4);
nrf_gpio_cfg_output(data.pin_db5);
nrf_gpio_cfg_output(data.pin_db6);
@@ -135,7 +142,61 @@ uint32_t liquid_crystal_init(uint32_t _ticks_per_ms) {
nrf_gpio_cfg_output(data.pin_rs);
nrf_gpio_cfg_output(data.pin_en);
- begin(data);
+ display_state.value = LIQUID_CRYSTAL_CMD_DISPLAY;
+ entry_mode_state.value = LIQUID_CRYSTAL_CMD_ENTRY_MODE_SET;
+ function_set_state.value = LIQUID_CRYSTAL_CMD_FUNCTION_SET;
+
+ function_set_state.fields.data_length = data_length;
+ function_set_state.fields.two_line = two_line;
+ function_set_state.fields.many_dots = many_dots;
+
+ for (int i = 0; i < 3; i++) {
+ nrf_gpio_pin_set(data.pin_en);
+ nrf_delay_ms(100);
+ nrf_gpio_pin_clear(data.pin_en);
+ nrf_delay_ms(100);
+ }
+
+ // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
+ // according to datasheet, we need at least 40ms after power rises above 2.7V
+ // before sending commands. Arduino can turn on way before 4.5V so we'll wait 50
+ nrf_delay_ms(50);
+
+ nrf_gpio_pin_clear(data.pin_rs);
+ nrf_gpio_pin_clear(data.pin_en);
+
+ write_4(0x03);
+ nrf_delay_us(4500);
+
+ write_4(0x03);
+ nrf_delay_us(4500);
+
+ write_4(0x03);
+ nrf_delay_us(150);
+
+ write_4(0x02);
+
+ write_value(function_set_state.value, false, 50);
+}
+
+void liquid_crystal_reset() {
+ liquid_crystal_clear();
+ liquid_crystal_return_home();
+ liquid_crystal_entry_mode_set(true, false);
+}
+
+void liquid_crystal_set_cursor(int column, int row) {
+ uint8_t value = LIQUID_CRYSTAL_CMD_SET_DDRAM_ADDDRESS;
+
+ if (row == 1) {
+ value += 0x40;
+ } else if (row == 2) {
+ value += 14;
+ } else if (row == 3) {
+ value += 54;
+ }
+
+ value += column;
- return NRF_SUCCESS;
+ write_value(value, false, 50);
}
diff --git a/LiquidCrystal.h b/LiquidCrystal.h
index 341d729..dd28fc9 100644
--- a/LiquidCrystal.h
+++ b/LiquidCrystal.h
@@ -6,11 +6,21 @@
#define LIQUIDCRYSTAL_H_
#include <stdint.h>
-#include "app_gpiote.h"
+#include <stdbool.h>
-uint32_t liquid_crystal_init();
+void liquid_crystal_init(bool data_length, bool two_line, bool many_dots);
-uint32_t liquid_crystal_display(bool display_on, bool cursor_on, bool blink);
+void liquid_crystal_reset();
+
+void liquid_crystal_clear();
+
+void liquid_crystal_return_home();
+
+void liquid_crystal_entry_mode_set(bool increment, bool shift);
+
+void liquid_crystal_display(bool display_on, bool cursor_on, bool blink);
+
+void liquid_crystal_set_cursor(int column, int row);
void liquid_crystal_write_char(char chr);
diff --git a/Makefile b/Makefile
index 47155d4..3e58e3a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
FLASHER ?= jlink
-BOARD := BOARD_PCA10028
+BOARD ?= BOARD_PCA10028
#TARGET_CHIP := NRF51822_QFAA_CA
#TARGET_CHIP := NRF51422_QFAC_AB
diff --git a/main.c b/main.c
index 34b8ae4..d79c12b 100644
--- a/main.c
+++ b/main.c
@@ -22,7 +22,7 @@
#include <string.h>
#include "nordic_common.h"
#include "nrf.h"
-#include "app_error.h"
+#include "nrf_delay.h"
#include "nrf51_bitfields.h"
#include "ble.h"
#include "ble_hci.h"
@@ -43,6 +43,7 @@
#include "app_timer.h"
#include "device_manager.h"
#include "pstorage.h"
+#include "app_error.h"
#include "app_trace.h"
#include "app_timer.h"
#include "app_gpiote.h"
@@ -293,7 +294,7 @@ static void on_ble_evt(ble_evt_t * p_ble_evt)
if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISEMENT)
{
- printf("re-starting advertisement");
+ printf("re-starting advertisement\n");
advertising_start();
/*
err_code = bsp_indication_set(BSP_INDICATE_IDLE);
@@ -399,7 +400,7 @@ int main(void)
{
app_trace_init();
- dbg("Soil Moisture device starting...\r\n");
+ dbg("Phone remote starting...\r\n");
ble_stack_init();
timers_init();
@@ -409,16 +410,33 @@ int main(void)
uint32_t err_code = bsp_init(BSP_INIT_LED | BSP_INIT_BUTTONS, APP_TIMER_TICKS(100, APP_TIMER_PRESCALER), NULL);
APP_ERROR_CHECK(err_code);
-// device_manager_init();
-// gap_params_init();
-// advertising_init();
-// services_init();
-// conn_params_init();
+ device_manager_init();
+ gap_params_init();
+ advertising_init();
+ services_init();
+ conn_params_init();
timers_start();
- liquid_crystal_init(APP_TIMER_TICKS(1, APP_TIMER_PRESCALER));
- liquid_crystal_write_string("hello world!");
+ liquid_crystal_init(false, true, false);
+ liquid_crystal_reset();
+ liquid_crystal_display(true, false, false);
+ liquid_crystal_write_string("01234567890123456");
+/*
+ char chars[] = "abcdefghijklmopqrstuvwxyz";
+
+ for(int i = 0; i < 10; i++) {
+ nrf_delay_ms(200);
+ liquid_crystal_write_char(chars[i]);
+ }
+
+ nrf_delay_ms(1000);
+*/
+ liquid_crystal_clear();
+// liquid_crystal_return_home();
+
+ liquid_crystal_set_cursor(1, 1);
+ liquid_crystal_write_string("hello!");
advertising_start();
diff --git a/nrf51.md b/nrf51.md
index 765af1e..0737ca0 100644
--- a/nrf51.md
+++ b/nrf51.md
@@ -1,5 +1,17 @@
# NRF51 Firmware Development Notes
+# Documentation
+
+nRF51-specific documentation:
+
+* [nRF51822 Product Specification](http://www.nordicsemi.com/eng/nordic/Products/nRF51822/nRF51822-PS/20339)
+* [nRF51822 Reference Manual](http://www.nordicsemi.com/eng/nordic/Products/nRF51822/nRF51-RM/20337)
+
+Generic ARM documentation:
+
+* [Cortex™-M0 Devices Generic User Guide](http://infocenter.arm.com/help/topic/com.arm.doc.dui0497a/DUI0497A_cortex_m0_r0p0_generic_ug.pdf)
+* [Cortex™-M0 Technical Reference Manual](http://infocenter.arm.com/help/topic/com.arm.doc.ddi0432c/DDI0432C_cortex_m0_r0p0_trm.pdf)
+
# Chip Details
## Address Map
@@ -21,26 +33,89 @@
### Flash and RAM Areas
-* nRF51822-xxAA flash: 0x0000 0000 => 0x0002 0000, RAM: 0x2000 0000 => 0x2000 4000
-* nRF51822-xxAB flash: 0x0000 0000 => 0x0001 0000, RAM: 0x2000 0000 => 0x2000 4000
-* nRF51822-xxAC flash: 0x0000 0000 => 0x0002 0000, RAM: 0x2000 0000 => 0x2000 8000
+| Device | Flash ||| RAM |||
+Device | Size | Start | End | Size | Start | End |
+ ------- | ------ | ----------- | ----------- | ------ | ----------- | ----------- |
+`xxAA` | 256kB | 0x0000 0000 | 0x0002 0000 | 16kB | 0x2000 0000 | 0x2000 4000 |
+`xxAB` | 128kB | 0x0000 0000 | 0x0001 0000 | 16kB | 0x2000 0000 | 0x2000 4000 |
+`xxAC` | 256kB | 0x0000 0000 | 0x0002 0000 | 32kB | 0x2000 0000 | 0x2000 8000 |
+[Available resources for chip variants]
# Debugging
screen /dev/ttyACM0 115200,-ixon,-ixoff
-## Documentation
+## GDB
-### Nordic
+ (gdb) print <symbol>
-* [inRF51822 Product Specification](http://www.nordicsemi.com/eng/nordic/Products/nRF51822/nRF51822-PS/20339)
-* [inRF51822 Reference Manual](http://www.nordicsemi.com/eng/nordic/Products/nRF51822/nRF51-RM/20337)
+ (gdb) info registers
-### Generic ARM
+## Remote Debugging
-* [Cortex™-M0 Devices Generic User Guide](http://infocenter.arm.com/help/topic/com.arm.doc.dui0497a/DUI0497A_cortex_m0_r0p0_generic_ug.pdf)
-* [Cortex™-M0 Technical Reference Manual](http://infocenter.arm.com/help/topic/com.arm.doc.ddi0432c/DDI0432C_cortex_m0_r0p0_trm.pdf)
+* `target remote localhost:2331`
+* `disconnect` or `detach`
+* the generic `monitor` commands sends jlink-specific commands. `monitor reset`
+
+When using GDB, make sure you use the version for arm:
+
+ arm-none-eabi-gdb
+
+I often start GDB like this:
+
+ arm-none-eabi-gdb -ex "file build/*.out" -ex "target remote localhost:2331" -ex "monitor reset"
+
+This select the correct image so you can say `break main`, connects to the JLink remote GDB server and performs a reset of the board.
+
+# The JLink tools
+
+## JLinkGDBServer
+
+This program is normally executed as
+
+ JLinkGDBServer -if SWD
+
+It should find the target and wait for an TCP connection on port 2331.
+
+Sometimes it will refuse to listen to the socket, just waiting (around 10 seconds) for a while seems to fix the problem.
+
+Example output:
+
+ $ JLinkGDBServer -if SWD
+ SEGGER J-Link GDB Server V4.98e Command Line Version
+
+ JLinkARM.dll V4.98e (DLL compiled May 5 2015 11:49:35)
+
+ -----GDB Server start settings-----
+ GDBInit file: none
+ GDB Server Listening port: 2331
+ SWO raw output listening port: 2332
+ Terminal I/O port: 2333
+ Accept remote connection: yes
+ Generate logfile: off
+ Verify download: off
+ Init regs on start: off
+ Silent mode: off
+ Single run mode: off
+ Target connection timeout: 0 ms
+ ------J-Link related settings------
+ J-Link Host interface: USB
+ J-Link script: none
+ J-Link settings file: none
+ ------Target related settings------
+ Target device: unspecified
+ Target interface: SWD
+ Target interface speed: 1000kHz
+ Target endian: little
-* nRF51822-xxAA flash: 256 kB, ram: 16kB
-* nRF51822-xxAB flash: 128 kB, ram: 16kB
-* nRF51822-xxAC flash: 256 kB, ram: 32kB
+ Connecting to J-Link...
+ J-Link is connected.
+ Firmware: J-Link OB-SAM3U128-V2-NordicSemi compiled May 4 2015 13:48:48
+ Hardware: V1.00
+ S/N: 681084376
+ Checking target voltage...
+ Target voltage: 3.30 V
+ Listening on TCP/IP port 2331
+ Connecting to target...WARNING: T-bit of XPSR is 0 but should be 1. Changed to 1.
+ Connected to target
+ Waiting for GDB connection...
diff --git a/phone_remote.c b/phone_remote.c
index c37123a..273e3d2 100644
--- a/phone_remote.c
+++ b/phone_remote.c
@@ -17,7 +17,7 @@ static uint8_t trygvis_io_uuid_type;
static uint16_t pr_service_handle;
static ble_gatts_char_handles_t pr_char_handle;
-static uint16_t conn_handle = BLE_CONN_HANDLE_INVALID;
+//static uint16_t conn_handle = BLE_CONN_HANDLE_INVALID;
// The value of the soil moisture control characteristic.
static uint8_t control_value[100] = {1, 2, 3};