summaryrefslogtreecommitdiff
path: root/apps/lcd3310/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/lcd3310/main.c')
-rw-r--r--apps/lcd3310/main.c190
1 files changed, 190 insertions, 0 deletions
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;
+}