summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2016-07-16 07:57:28 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2016-07-16 10:37:06 +0200
commitffa14762a506c39d897fd63f028b39904cf22a5f (patch)
tree361c863c7851f4c41797b5ec4fa8aa9c9213c4aa /apps
parent8fdcf6b00313829230a61da4dfe210e5f82b371e (diff)
downloadintel-quark-d2000-playground-master.tar.gz
intel-quark-d2000-playground-master.tar.bz2
intel-quark-d2000-playground-master.tar.xz
intel-quark-d2000-playground-master.zip
o Changing how the toolchain create the qmsi libraries etc. Replace the hardcoded library with a function that the user can use to create its own special target. This target can be further customized by normal CMake methods by setting properties.HEADmaster
o Adding start of a app for playing with MOD-LCD3310 which is a PCD8544 connected through SPI.
Diffstat (limited to 'apps')
-rw-r--r--apps/CMakeLists.txt3
-rw-r--r--apps/accel/CMakeLists.txt3
-rw-r--r--apps/lcd3310/CMakeLists.txt7
-rw-r--r--apps/lcd3310/bits.h21
-rw-r--r--apps/lcd3310/main.c190
5 files changed, 224 insertions, 0 deletions
diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt
index 973af05..1b220e2 100644
--- a/apps/CMakeLists.txt
+++ b/apps/CMakeLists.txt
@@ -1,2 +1,5 @@
+qmsi_create(stdout)
+
add_subdirectory(accel)
+add_subdirectory(lcd3310)
#add_subdirectory(magneto)
diff --git a/apps/accel/CMakeLists.txt b/apps/accel/CMakeLists.txt
index 35948ae..2f342f7 100644
--- a/apps/accel/CMakeLists.txt
+++ b/apps/accel/CMakeLists.txt
@@ -1,4 +1,7 @@
add_executable(accel main.c)
+target_link_libraries(accel PUBLIC qmsi_stdout)
+target_link_libraries(accel PUBLIC qmsi_bmc_stdout)
+
set_target_properties(accel PROPERTIES CHIP QUARK_D2000)
toolchain_target(accel)
add_extra_commands(accel)
diff --git a/apps/lcd3310/CMakeLists.txt b/apps/lcd3310/CMakeLists.txt
new file mode 100644
index 0000000..4d77f22
--- /dev/null
+++ b/apps/lcd3310/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_executable(lcd3310 main.c bits.h)
+target_include_directories(lcd3310 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
+target_link_libraries(lcd3310 PUBLIC qmsi_stdout)
+
+set_target_properties(lcd3310 PROPERTIES CHIP QUARK_D2000)
+toolchain_target(lcd3310)
+add_extra_commands(lcd3310)
diff --git a/apps/lcd3310/bits.h b/apps/lcd3310/bits.h
new file mode 100644
index 0000000..434c390
--- /dev/null
+++ b/apps/lcd3310/bits.h
@@ -0,0 +1,21 @@
+#pragma once
+
+/*
+http://stackoverflow.com/a/5048661/245614
+*/
+/*
+NUM_ARGS(...) evaluates to the literal number of the passed-in arguments.
+*/
+#define _NUM_ARGS2(X, X64, X63, X62, X61, X60, X59, X58, X57, X56, X55, X54, X53, X52, X51, X50, X49, X48, X47, X46, X45, X44, X43, X42, X41, X40, X39, X38, X37, X36, X35, X34, X33, X32, X31, X30, X29, X28, X27, X26, X25, X24, X23, X22, X21, X20, X19, X18, X17, X16, X15, X14, X13, X12, X11, X10, X9, X8, X7, X6, X5, X4, X3, X2, X1, N, ...) N
+#define NUM_ARGS(...) _NUM_ARGS2(0, __VA_ARGS__, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
+
+#define BIT_MASK_1(a) (1 << a)
+#define BIT_MASK_2(a, b) (BIT_MASK_1(a) | BIT_MASK_1(b))
+#define BIT_MASK_3(a, b, c) (BIT_MASK_2(a, b) | BIT_MASK_1(c))
+#define BIT_MASK_4(a, b, c, d) (BIT_MASK_3(a, b, c) | BIT_MASK_1(d))
+#define BIT_MASK_5(a, b, c, d, e) (BIT_MASK_4(a, b, c, d) | BIT_MASK_1(e))
+#define BIT_MASK_6(a, b, c, d, e, f) (BIT_MASK_5(a, b, c, d, e) | BIT_MASK_1(f))
+
+#define _BIT_MASK_3(N, ...) BIT_MASK_ ## N(__VA_ARGS__)
+#define _BIT_MASK_2(N, ...) _BIT_MASK_3(N, __VA_ARGS__)
+#define BIT_MASK(...) _BIT_MASK_2(NUM_ARGS(__VA_ARGS__), __VA_ARGS__)
diff --git a/apps/lcd3310/main.c b/apps/lcd3310/main.c
new file mode 100644
index 0000000..602a804
--- /dev/null
+++ b/apps/lcd3310/main.c
@@ -0,0 +1,190 @@
+/*
+https://yogiken.files.wordpress.com/2010/02/c-register-access.pdf
+ */
+
+#include <qm_soc_regs.h>
+#include <qm_spi.h>
+#include <qm_gpio.h>
+#include <stddef.h>
+#include <assert.h>
+#include <qm_scss.h>
+#include <qm_pinmux.h>
+#include "bits.h"
+
+struct spi {
+ qm_spi_t id;
+};
+
+struct gpio_pin {
+ qm_gpio_t port;
+ uint8_t pin;
+};
+
+struct pcd8544 {
+ struct spi *spi;
+ /* 1 = data, 0 = command */
+ struct gpio_pin *pin_dc;
+ struct gpio_pin *pin_res;
+};
+
+void spi_new(struct spi *spi, qm_spi_t id) {
+ clk_periph_enable(CLK_PERIPH_SPI_M0);
+ spi->id = id;
+
+ qm_pmux_select(QM_PIN_ID_16, QM_PMUX_FN_2); /* SCL */
+ qm_pmux_select(QM_PIN_ID_17, QM_PMUX_FN_2); /* TXD */
+ qm_pmux_input_en(QM_PIN_ID_18, true);
+}
+
+void spi_enable(struct spi *spi) {
+ qm_spi_config_t cfg = {
+ .frame_size = QM_SPI_FRAME_SIZE_8_BIT,
+ .transfer_mode = QM_SPI_TMOD_TX_RX,
+ .bus_mode = QM_SPI_BMODE_0,
+ .clk_divider = 2
+ };
+ qm_spi_set_config(spi->id, &cfg);
+}
+
+void spi_delete(struct spi const *const spi) {
+}
+
+void spi_exchange(struct spi const *const spi, uint8_t *tx, size_t tx_len, uint8_t *rx, size_t rx_len) {
+ qm_spi_transfer_t transfer = {
+ .tx = tx,
+ .tx_len = tx_len,
+ .rx = rx,
+ .rx_len = rx_len
+ };
+ qm_spi_transfer(spi->id, &transfer);
+}
+
+void spi_tx(struct spi const *const spi, uint8_t *tx, size_t tx_len) {
+ qm_spi_config_t cfg = {
+ .frame_size = QM_SPI_FRAME_SIZE_8_BIT,
+ .transfer_mode = QM_SPI_TMOD_TX,
+ .bus_mode = QM_SPI_BMODE_0,
+ .clk_divider = 32 /* 8 == 4MHz */
+ };
+ qm_spi_set_config(spi->id, &cfg);
+
+ qm_spi_transfer_t transfer = {
+ .tx = tx,
+ .tx_len = tx_len,
+ .rx = 0,
+ .rx_len = 0
+ };
+ qm_spi_transfer(spi->id, &transfer);
+}
+
+void gpio_pin_new(struct gpio_pin *gp, int port, uint8_t pin) {
+ assert(port == 0);
+
+ gp->port = QM_GPIO_0;
+ gp->pin = pin;
+
+ qm_gpio_port_config_t cfg = {
+ .direction = (uint32_t) BIT_MASK(pin),
+ .int_en = 0,
+ .int_type = 0,
+ .int_polarity = 0,
+ .int_debounce = 0,
+ .int_bothedge = 0,
+ .callback = NULL
+ };
+ qm_gpio_set_config(gp->port, &cfg);
+}
+
+void gpio_pin_set(struct gpio_pin *gp) {
+ qm_gpio_set_pin(gp->port, gp->pin);
+}
+
+void gpio_pin_reset(struct gpio_pin *gp) {
+}
+
+uint8_t pcd8544_cmd_function(bool power_down, bool vertical_mode, bool extended_instruction_set) {
+ return (uint8_t) ((power_down & BIT_MASK_1(2)) |
+ (vertical_mode & BIT_MASK_1(1)) |
+ (extended_instruction_set & BIT_MASK_1(0)));
+}
+
+uint8_t pcd8544_cmd_display_function(bool d, bool e) {
+ return (uint8_t) (BIT_MASK_1(3) |
+ (d & BIT_MASK_1(2)) |
+ (e & BIT_MASK_1(0)));
+}
+
+uint8_t pcd8544_cmd_x_address(int address) {
+ return (uint8_t) (BIT_MASK_1(6) | (address & BIT_MASK_3(2, 1, 0)));
+}
+
+uint8_t pcd8544_cmd_y_address(int address) {
+ return (uint8_t) (BIT_MASK_1(7) | (address & BIT_MASK(5, 4, 3, 2, 1, 0)));
+}
+
+void pcd8544_new(struct pcd8544 *pcd8544, struct spi *spi, struct gpio_pin *pin_dc, struct gpio_pin *pin_res) {
+ pcd8544->spi = spi;
+ pcd8544->pin_dc = pin_dc;
+ pcd8544->pin_res = pin_res;
+}
+
+void pcd8544_delete(struct pcd8544 *pcd8544) {
+}
+
+void pcd8544_reset(struct pcd8544 *pcd8544) {
+ gpio_pin_reset(pcd8544->pin_res);
+ clk_sys_udelay(10 * 1000);
+ gpio_pin_set(pcd8544->pin_res);
+
+ gpio_pin_reset(pcd8544->pin_dc);
+
+ uint8_t tx[] = {
+ pcd8544_cmd_function(false, false, false),
+ pcd8544_cmd_y_address(0),
+ pcd8544_cmd_x_address(0)
+ };
+ uint8_t rx[] = {
+ 0,
+ 0,
+ 0
+ };
+
+ spi_exchange(pcd8544->spi, tx, sizeof(tx), rx, sizeof(rx));
+
+ gpio_pin_set(pcd8544->pin_dc);
+}
+
+void pcd8544_fun(struct pcd8544 *pcd8544) {
+ uint8_t tx[] = {
+ 0xaa,
+ 0x55,
+ 0xaa,
+ 0x55,
+ 0xaa,
+ 0x55,
+ };
+
+ spi_tx(pcd8544->spi, tx, sizeof(tx));
+}
+
+struct spi spi;
+struct pcd8544 pcd8544;
+struct gpio_pin pin_dc, pin_res;
+
+int main() {
+ clk_periph_enable(CLK_PERIPH_CLK);
+
+ spi_new(&spi, QM_SPI_MST_0);
+ spi_enable(&spi);
+
+ gpio_pin_new(&pin_dc, 0, 3);
+ gpio_pin_new(&pin_res, 0, 4);
+
+ pcd8544_new(&pcd8544, &spi, &pin_dc, &pin_res);
+ pcd8544_reset(&pcd8544);
+ pcd8544_fun(&pcd8544);
+ pcd8544_delete(&pcd8544);
+
+ spi_delete(&spi);
+ return 0;
+}