commit
89c1857d57
@ -0,0 +1,3 @@ |
|||||||
|
build/ |
||||||
|
cmake-build-* |
||||||
|
.idea/ |
@ -0,0 +1,23 @@ |
|||||||
|
cmake_minimum_required(VERSION 3.13) |
||||||
|
|
||||||
|
# initialize the SDK based on PICO_SDK_PATH |
||||||
|
# note: this must happen before project() |
||||||
|
include(pico_sdk_import.cmake) |
||||||
|
|
||||||
|
project(zavlaha) |
||||||
|
|
||||||
|
# initialize the Raspberry Pi Pico SDK |
||||||
|
pico_sdk_init() |
||||||
|
|
||||||
|
# rest of your project |
||||||
|
|
||||||
|
add_executable(zavlaha |
||||||
|
src/main.c |
||||||
|
src/lcd.c |
||||||
|
) |
||||||
|
|
||||||
|
# Add pico_stdlib library which aggregates commonly used features |
||||||
|
target_link_libraries(zavlaha pico_stdlib hardware_i2c hardware_adc hardware_irq) |
||||||
|
|
||||||
|
# create map/bin/hex/uf2 file in addition to ELF. |
||||||
|
pico_add_extra_outputs(zavlaha) |
@ -0,0 +1,14 @@ |
|||||||
|
.PHONY: build |
||||||
|
|
||||||
|
TARGET=build/zavlaha.elf
|
||||||
|
TARGET_U2F=build/zavlaha.uf2
|
||||||
|
|
||||||
|
build: |
||||||
|
cd build && cmake .. && make -j
|
||||||
|
arm-none-eabi-size ${TARGET}
|
||||||
|
|
||||||
|
upload: build $(TARGET_U2F) |
||||||
|
cp $(TARGET_U2F) /run/media/ondra/RPI-RP2/
|
||||||
|
|
||||||
|
flash: build |
||||||
|
pico-openocd -f target/rp2040.cfg -c "adapter speed 1000" -c "program ${TARGET} verify reset exit"
|
@ -0,0 +1,73 @@ |
|||||||
|
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake |
||||||
|
|
||||||
|
# This can be dropped into an external project to help locate this SDK |
||||||
|
# It should be include()ed prior to project() |
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) |
||||||
|
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) |
||||||
|
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") |
||||||
|
endif () |
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) |
||||||
|
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) |
||||||
|
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") |
||||||
|
endif () |
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) |
||||||
|
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) |
||||||
|
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") |
||||||
|
endif () |
||||||
|
|
||||||
|
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") |
||||||
|
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") |
||||||
|
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") |
||||||
|
|
||||||
|
if (NOT PICO_SDK_PATH) |
||||||
|
if (PICO_SDK_FETCH_FROM_GIT) |
||||||
|
include(FetchContent) |
||||||
|
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) |
||||||
|
if (PICO_SDK_FETCH_FROM_GIT_PATH) |
||||||
|
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") |
||||||
|
endif () |
||||||
|
# GIT_SUBMODULES_RECURSE was added in 3.17 |
||||||
|
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0") |
||||||
|
FetchContent_Declare( |
||||||
|
pico_sdk |
||||||
|
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk |
||||||
|
GIT_TAG master |
||||||
|
GIT_SUBMODULES_RECURSE FALSE |
||||||
|
) |
||||||
|
else () |
||||||
|
FetchContent_Declare( |
||||||
|
pico_sdk |
||||||
|
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk |
||||||
|
GIT_TAG master |
||||||
|
) |
||||||
|
endif () |
||||||
|
|
||||||
|
if (NOT pico_sdk) |
||||||
|
message("Downloading Raspberry Pi Pico SDK") |
||||||
|
FetchContent_Populate(pico_sdk) |
||||||
|
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) |
||||||
|
endif () |
||||||
|
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) |
||||||
|
else () |
||||||
|
message(FATAL_ERROR |
||||||
|
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." |
||||||
|
) |
||||||
|
endif () |
||||||
|
endif () |
||||||
|
|
||||||
|
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") |
||||||
|
if (NOT EXISTS ${PICO_SDK_PATH}) |
||||||
|
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") |
||||||
|
endif () |
||||||
|
|
||||||
|
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) |
||||||
|
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) |
||||||
|
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") |
||||||
|
endif () |
||||||
|
|
||||||
|
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) |
||||||
|
|
||||||
|
include(${PICO_SDK_INIT_CMAKE_FILE}) |
@ -0,0 +1,396 @@ |
|||||||
|
#include <stdbool.h> |
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
#include <pico/stdlib.h> |
||||||
|
#include "lcd.h" |
||||||
|
#include "pinout.h" |
||||||
|
|
||||||
|
#define LCD_D7 PIN_LCD_D7 |
||||||
|
#define LCD_D6 PIN_LCD_D6 |
||||||
|
#define LCD_D5 PIN_LCD_D5 |
||||||
|
#define LCD_D4 PIN_LCD_D4 |
||||||
|
#define LCD_RS PIN_LCD_RS |
||||||
|
#define LCD_RW PIN_LCD_RW |
||||||
|
#define LCD_E PIN_LCD_E |
||||||
|
|
||||||
|
#define set_pin(num, val) gpio_put((num), (val)) |
||||||
|
#define get_pin(num) gpio_get((num)) |
||||||
|
#define pin_high(num) set_pin((num), 1) |
||||||
|
#define pin_low(num) set_pin((num), 0) |
||||||
|
#define get_bit(a, pos) (((a) >> (pos)) & 1) |
||||||
|
#define as_output(pin) gpio_set_dir((pin), 1) |
||||||
|
#define as_input_pu(pin) do { gpio_set_dir((pin), 0); gpio_pull_up((pin)); } while (0) |
||||||
|
#define _delay_ms(ms) sleep_ms((ms)) |
||||||
|
#define _delay_us(us) sleep_us((us)) |
||||||
|
#define _delay_ns(ns) sleep_us(1 + ((ns) / 1000)) // TODO
|
||||||
|
|
||||||
|
// Start address of rows
|
||||||
|
const uint8_t LCD_ROW_ADDR[] = {0x00, 0x40, 0x14, 0x54}; |
||||||
|
|
||||||
|
// Internal prototypes
|
||||||
|
void _lcd_mode_r(); |
||||||
|
|
||||||
|
void _lcd_mode_w(); |
||||||
|
|
||||||
|
void _lcd_clk(); |
||||||
|
|
||||||
|
void _lcd_wait_bf(); |
||||||
|
|
||||||
|
void _lcd_write_byte(uint8_t bb); |
||||||
|
|
||||||
|
uint8_t _lcd_read_byte(); |
||||||
|
|
||||||
|
void lcd_command(uint8_t bb); |
||||||
|
|
||||||
|
|
||||||
|
// Write utilities
|
||||||
|
#define _lcd_write_low(bb) _lcd_write_nibble((bb) & 0x0F) |
||||||
|
#define _lcd_write_high(bb) _lcd_write_nibble(((bb) & 0xF0) >> 4) |
||||||
|
|
||||||
|
#define _lcd_write_nibble(nib) \ |
||||||
|
gpio_put_masked((1 << PIN_LCD_D7) | (1 << PIN_LCD_D6) | (1 << PIN_LCD_D5) | (1 << PIN_LCD_D4), (nib) << PIN_LCD_D4) |
||||||
|
|
||||||
|
//#define _lcd_write_nibble(nib) do { \
|
||||||
|
// set_pin(LCD_D7, get_bit((nib), 3)); \
|
||||||
|
// set_pin(LCD_D6, get_bit((nib), 2)); \
|
||||||
|
// set_pin(LCD_D5, get_bit((nib), 1)); \
|
||||||
|
// set_pin(LCD_D4, get_bit((nib), 0)); \
|
||||||
|
//} while(0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// --- Commands ---
|
||||||
|
|
||||||
|
// Clear screen (reset)
|
||||||
|
#define LCD_CLEAR 0b00000001 |
||||||
|
// Move cursor to (0,0), unshift...
|
||||||
|
#define LCD_HOME 0b00000010 |
||||||
|
|
||||||
|
// Set mode: Increment + NoShift
|
||||||
|
#define LCD_MODE_INC 0b00000110 |
||||||
|
// Set mode: Increment + Shift
|
||||||
|
#define LCD_MODE_INC_SHIFT 0b00000111 |
||||||
|
|
||||||
|
// Set mode: Decrement + NoShift
|
||||||
|
#define LCD_MODE_DEC 0b00000100 |
||||||
|
// Set mode: Decrement + Shift
|
||||||
|
#define LCD_MODE_DEC_SHIFT 0b00000101 |
||||||
|
|
||||||
|
// Disable display (data remains untouched)
|
||||||
|
#define LCD_DISABLE 0b00001000 |
||||||
|
|
||||||
|
// Disable cursor
|
||||||
|
#define LCD_CURSOR_NONE 0b00001100 |
||||||
|
// Set cursor to still underscore
|
||||||
|
#define LCD_CURSOR_BAR 0b00001110 |
||||||
|
// Set cursor to blinking block
|
||||||
|
#define LCD_CURSOR_BLINK 0b00001101 |
||||||
|
// Set cursor to both of the above at once
|
||||||
|
#define LCD_CURSOR_BOTH (LCD_CURSOR_BAR | LCD_CURSOR_BLINK) |
||||||
|
|
||||||
|
// Move cursor
|
||||||
|
#define LCD_MOVE_LEFT 0b00010000 |
||||||
|
#define LCD_MOVE_RIGHT 0b00010100 |
||||||
|
|
||||||
|
// Shift display
|
||||||
|
#define LCD_SHIFT_LEFT 0b00011000 |
||||||
|
#define LCD_SHIFT_RIGHT 0b00011100 |
||||||
|
|
||||||
|
// Set iface to 5x7 font, 1-line
|
||||||
|
#define LCD_IFACE_4BIT_1LINE 0b00100000 |
||||||
|
#define LCD_IFACE_8BIT_1LINE 0b00110000 |
||||||
|
// Set iface to 5x7 font, 2-line
|
||||||
|
#define LCD_IFACE_4BIT_2LINE 0b00101000 |
||||||
|
#define LCD_IFACE_8BIT_2LINE 0b00111000 |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 0 W, 1 R
|
||||||
|
bool _lcd_mode; |
||||||
|
|
||||||
|
struct { |
||||||
|
uint8_t x; |
||||||
|
uint8_t y; |
||||||
|
} _pos; |
||||||
|
|
||||||
|
enum { |
||||||
|
TEXT = 0, |
||||||
|
CG = 1 |
||||||
|
} _addrtype; |
||||||
|
|
||||||
|
|
||||||
|
/** Initialize the display */ |
||||||
|
void lcd_init() |
||||||
|
{ |
||||||
|
// configure pins as output
|
||||||
|
as_output(LCD_E); |
||||||
|
as_output(LCD_RW); |
||||||
|
as_output(LCD_RS); |
||||||
|
_lcd_mode = 1; // force data pins to output
|
||||||
|
_lcd_mode_w(); |
||||||
|
|
||||||
|
// Magic sequence to invoke Cthulhu (or enter 4-bit mode)
|
||||||
|
_delay_ms(16); |
||||||
|
_lcd_write_nibble(0b0011); |
||||||
|
_lcd_clk(); |
||||||
|
_delay_ms(5); |
||||||
|
_lcd_clk(); |
||||||
|
_delay_ms(5); |
||||||
|
_lcd_clk(); |
||||||
|
_delay_ms(5); |
||||||
|
_lcd_write_nibble(0b0010); |
||||||
|
_lcd_clk(); |
||||||
|
_delay_us(100); |
||||||
|
|
||||||
|
// Configure the display
|
||||||
|
lcd_command(LCD_IFACE_4BIT_2LINE); |
||||||
|
lcd_command(LCD_DISABLE); |
||||||
|
lcd_command(LCD_CLEAR); |
||||||
|
lcd_command(LCD_MODE_INC); |
||||||
|
|
||||||
|
// mark as enabled
|
||||||
|
lcd_enable(); |
||||||
|
|
||||||
|
_pos.x = 0; |
||||||
|
_pos.y = 0; |
||||||
|
_addrtype = TEXT; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Send a pulse on the ENABLE line */ |
||||||
|
void _lcd_clk() |
||||||
|
{ |
||||||
|
pin_high(LCD_E); |
||||||
|
_delay_ns(450); |
||||||
|
pin_low(LCD_E); |
||||||
|
_delay_ns(450); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Enter READ mode */ |
||||||
|
void _lcd_mode_r() |
||||||
|
{ |
||||||
|
if (_lcd_mode == 1) { return; } // already in R mode
|
||||||
|
|
||||||
|
pin_high(LCD_RW); |
||||||
|
|
||||||
|
as_input_pu(LCD_D7); |
||||||
|
as_input_pu(LCD_D6); |
||||||
|
as_input_pu(LCD_D5); |
||||||
|
as_input_pu(LCD_D4); |
||||||
|
|
||||||
|
_lcd_mode = 1; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Enter WRITE mode */ |
||||||
|
void _lcd_mode_w() |
||||||
|
{ |
||||||
|
if (_lcd_mode == 0) { return; } // already in W mode
|
||||||
|
|
||||||
|
pin_low(LCD_RW); |
||||||
|
|
||||||
|
as_output(LCD_D7); |
||||||
|
as_output(LCD_D6); |
||||||
|
as_output(LCD_D5); |
||||||
|
as_output(LCD_D4); |
||||||
|
|
||||||
|
_lcd_mode = 0; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Read a byte */ |
||||||
|
uint8_t _lcd_read_byte() |
||||||
|
{ |
||||||
|
_lcd_mode_r(); |
||||||
|
|
||||||
|
uint8_t res = 0; |
||||||
|
|
||||||
|
_lcd_clk(); |
||||||
|
res = (get_pin(LCD_D7) << 7) | (get_pin(LCD_D6) << 6) | (get_pin(LCD_D5) << 5) | (get_pin(LCD_D4) << 4); |
||||||
|
|
||||||
|
_lcd_clk(); |
||||||
|
res |= (get_pin(LCD_D7) << 3) | (get_pin(LCD_D6) << 2) | (get_pin(LCD_D5) << 1) | (get_pin(LCD_D4) << 0); |
||||||
|
|
||||||
|
return res; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Write an instruction byte */ |
||||||
|
void lcd_command(uint8_t bb) |
||||||
|
{ |
||||||
|
_lcd_wait_bf(); |
||||||
|
pin_low(LCD_RS); // select instruction register
|
||||||
|
_lcd_write_byte(bb); // send instruction byte
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Write a data byte */ |
||||||
|
void lcd_write(uint8_t bb) |
||||||
|
{ |
||||||
|
if (_addrtype == TEXT) { |
||||||
|
if (bb == '\r') { |
||||||
|
// CR
|
||||||
|
_pos.x = 0; |
||||||
|
lcd_xy(_pos.x, _pos.y); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (bb == '\n') { |
||||||
|
// LF
|
||||||
|
_pos.y++; |
||||||
|
lcd_xy(_pos.x, _pos.y); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
_pos.x++; |
||||||
|
} |
||||||
|
|
||||||
|
_lcd_wait_bf(); |
||||||
|
pin_high(LCD_RS); // select data register
|
||||||
|
_lcd_write_byte(bb); // send data byte
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Read BF & Address */ |
||||||
|
uint8_t lcd_read_bf_addr() |
||||||
|
{ |
||||||
|
pin_low(LCD_RS); |
||||||
|
return _lcd_read_byte(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Read CGRAM or DDRAM */ |
||||||
|
uint8_t lcd_read() |
||||||
|
{ |
||||||
|
if (_addrtype == TEXT) { _pos.x++; } |
||||||
|
|
||||||
|
pin_high(LCD_RS); |
||||||
|
return _lcd_read_byte(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Write a byte using the 4-bit interface */ |
||||||
|
void _lcd_write_byte(uint8_t bb) |
||||||
|
{ |
||||||
|
_lcd_mode_w(); // enter W mode
|
||||||
|
|
||||||
|
_lcd_write_high(bb); |
||||||
|
_lcd_clk(); |
||||||
|
|
||||||
|
_lcd_write_low(bb); |
||||||
|
_lcd_clk(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Wait until the device is ready */ |
||||||
|
void _lcd_wait_bf() |
||||||
|
{ |
||||||
|
uint8_t d = 0; |
||||||
|
while (d++ < 200 && lcd_read_bf_addr() & (1 << 7)) |
||||||
|
_delay_us(1); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Send a string to LCD */ |
||||||
|
void lcd_puts(char *str_p) |
||||||
|
{ |
||||||
|
char c; |
||||||
|
while ((c = *str_p++)) { |
||||||
|
lcd_putc(c); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** Sedn a char to LCD */ |
||||||
|
void lcd_putc(const char c) |
||||||
|
{ |
||||||
|
lcd_write(c); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Set cursor position */ |
||||||
|
void lcd_xy(const uint8_t x, const uint8_t y) |
||||||
|
{ |
||||||
|
_pos.x = x; |
||||||
|
_pos.y = y; |
||||||
|
lcd_addr(LCD_ROW_ADDR[y] + (x)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
uint8_t _lcd_old_cursor = CURSOR_NONE; |
||||||
|
bool _lcd_enabled = false; |
||||||
|
|
||||||
|
/** Set LCD cursor. If not enabled, only remember it. */ |
||||||
|
void lcd_cursor(uint8_t type) |
||||||
|
{ |
||||||
|
_lcd_old_cursor = (type & CURSOR_BOTH); |
||||||
|
|
||||||
|
if (_lcd_enabled) { lcd_command(LCD_CURSOR_NONE | _lcd_old_cursor); } |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Display display (preserving cursor) */ |
||||||
|
void lcd_disable() |
||||||
|
{ |
||||||
|
lcd_command(LCD_DISABLE); |
||||||
|
_lcd_enabled = false; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Enable display (restoring cursor) */ |
||||||
|
void lcd_enable() |
||||||
|
{ |
||||||
|
_lcd_enabled = true; |
||||||
|
lcd_cursor(_lcd_old_cursor); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Go home */ |
||||||
|
void lcd_home() |
||||||
|
{ |
||||||
|
lcd_command(LCD_HOME); |
||||||
|
_pos.x = 0; |
||||||
|
_pos.y = 0; |
||||||
|
_addrtype = TEXT; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Clear the screen */ |
||||||
|
void lcd_clear() |
||||||
|
{ |
||||||
|
lcd_command(LCD_CLEAR); |
||||||
|
_pos.x = 0; |
||||||
|
_pos.y = 0; |
||||||
|
_addrtype = TEXT; |
||||||
|
_delay_ms(1); // it tends to lose the first character otherwise!
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Define a glyph */ |
||||||
|
void lcd_glyph(const uint8_t index, const uint8_t *array) |
||||||
|
{ |
||||||
|
lcd_addr_cg(index * 8); |
||||||
|
for (uint8_t i = 0; i < 8; ++i) { |
||||||
|
lcd_write(array[i]); |
||||||
|
} |
||||||
|
|
||||||
|
// restore previous position
|
||||||
|
lcd_xy(_pos.x, _pos.y); |
||||||
|
_addrtype = TEXT; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Set address in CGRAM */ |
||||||
|
void lcd_addr_cg(const uint8_t acg) |
||||||
|
{ |
||||||
|
_addrtype = CG; |
||||||
|
lcd_command(0b01000000 | ((acg) & 0b00111111)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Set address in DDRAM */ |
||||||
|
void lcd_addr(const uint8_t add) |
||||||
|
{ |
||||||
|
_addrtype = TEXT; |
||||||
|
lcd_command(0b10000000 | ((add) & 0b01111111)); |
||||||
|
} |
@ -0,0 +1,294 @@ |
|||||||
|
#include <stdbool.h> |
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
#include <pico/stdlib.h> |
||||||
|
|
||||||
|
#include "pinout.h" |
||||||
|
#include "lcd.h" |
||||||
|
|
||||||
|
// ------------------ PORTING ----------------------
|
||||||
|
|
||||||
|
#define lcd_mode_instr(bb) gpio_put(PIN_LCD_DC, 0) |
||||||
|
#define lcd_mode_data(bb) gpio_put(PIN_LCD_DC, 1) |
||||||
|
|
||||||
|
#define lcd_mode_write(bb) gpio_put(PIN_LCD_RW, 0) |
||||||
|
#define lcd_mode_read(bb) gpio_put(PIN_LCD_RW, 1) |
||||||
|
|
||||||
|
//// Write utilities
|
||||||
|
//#define lcd_write_nibble(nib) \
|
||||||
|
// gpio_put_masked((1 << PIN_LCD_D7) | (1 << PIN_LCD_D6) | (1 << PIN_LCD_D5) | (1 << PIN_LCD_D4), (nib) << PIN_LCD_D4)
|
||||||
|
|
||||||
|
|
||||||
|
// Write utilities
|
||||||
|
#define lcd_write_nibble(nib) do { \ |
||||||
|
gpio_put(PIN_LCD_D7, nib & 0b1000); \
|
||||||
|
gpio_put(PIN_LCD_D6, nib & 0b0100); \
|
||||||
|
gpio_put(PIN_LCD_D5, nib & 0b0010); \
|
||||||
|
gpio_put(PIN_LCD_D4, nib & 0b0001); \
|
||||||
|
} while (0) |
||||||
|
|
||||||
|
/** Wait until the device is ready */ |
||||||
|
static void lcd_wait_ready() |
||||||
|
{ |
||||||
|
sleep_us(160); |
||||||
|
} |
||||||
|
|
||||||
|
/** Send a pulse on the ENABLE line */ |
||||||
|
static inline void lcd_clk() |
||||||
|
{ |
||||||
|
gpio_put(PIN_LCD_CLK, 1); |
||||||
|
sleep_us(1); |
||||||
|
gpio_put(PIN_LCD_CLK, 0); |
||||||
|
sleep_us(1); |
||||||
|
} |
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// --- Commands ---
|
||||||
|
|
||||||
|
// Clear screen (reset)
|
||||||
|
#define LCD_CLEAR 0b00000001 |
||||||
|
// Move cursor to (0,0), unshift...
|
||||||
|
#define LCD_HOME 0b00000010 |
||||||
|
|
||||||
|
// Set mode: Increment + NoShift
|
||||||
|
#define LCD_MODE_INC 0b00000110 |
||||||
|
// Set mode: Increment + Shift
|
||||||
|
#define LCD_MODE_INC_SHIFT 0b00000111 |
||||||
|
|
||||||
|
// Set mode: Decrement + NoShift
|
||||||
|
#define LCD_MODE_DEC 0b00000100 |
||||||
|
// Set mode: Decrement + Shift
|
||||||
|
#define LCD_MODE_DEC_SHIFT 0b00000101 |
||||||
|
|
||||||
|
// Disable display (data remains untouched)
|
||||||
|
#define LCD_DISABLE 0b00001000 |
||||||
|
|
||||||
|
// Disable cursor
|
||||||
|
#define LCD_CURSOR_NONE 0b00001100 |
||||||
|
// Set cursor to still underscore
|
||||||
|
#define LCD_CURSOR_BAR 0b00001110 |
||||||
|
// Set cursor to blinking block
|
||||||
|
#define LCD_CURSOR_BLINK 0b00001101 |
||||||
|
// Set cursor to both of the above at once
|
||||||
|
#define LCD_CURSOR_BOTH (LCD_CURSOR_BAR | LCD_CURSOR_BLINK) |
||||||
|
|
||||||
|
// Move cursor
|
||||||
|
#define LCD_MOVE_LEFT 0b00010000 |
||||||
|
#define LCD_MOVE_RIGHT 0b00010100 |
||||||
|
|
||||||
|
// Shift display
|
||||||
|
#define LCD_SHIFT_LEFT 0b00011000 |
||||||
|
#define LCD_SHIFT_RIGHT 0b00011100 |
||||||
|
|
||||||
|
// Set iface to 5x7 font, 1-line
|
||||||
|
#define LCD_IFACE_4BIT_1LINE 0b00100000 |
||||||
|
#define LCD_IFACE_8BIT_1LINE 0b00110000 |
||||||
|
// Set iface to 5x7 font, 2-line
|
||||||
|
#define LCD_IFACE_4BIT_2LINE 0b00101000 |
||||||
|
#define LCD_IFACE_8BIT_2LINE 0b00111000 |
||||||
|
|
||||||
|
/** Write an instruction byte */ |
||||||
|
static void lcd_command(uint8_t bb); |
||||||
|
|
||||||
|
/** Write a data byte, waiting for ready and handling CRLF if in text mode */ |
||||||
|
static void lcd_write(uint8_t bb); |
||||||
|
|
||||||
|
/** Write a byte (handles just the data pins and clk) */ |
||||||
|
static void lcd_write_byte(uint8_t bb); |
||||||
|
|
||||||
|
#define lcd_write_low(bb) lcd_write_nibble((bb) & 0x0F) |
||||||
|
#define lcd_write_high(bb) lcd_write_nibble(((bb) & 0xF0) >> 4) |
||||||
|
|
||||||
|
static struct { |
||||||
|
uint8_t x; |
||||||
|
uint8_t y; |
||||||
|
} lcd_pos; |
||||||
|
|
||||||
|
static enum { |
||||||
|
LCD_ADDRTYPE_TEXT = 0, |
||||||
|
LCD_ADDRTYPE_CG = 1 |
||||||
|
} lcd_addrtype; |
||||||
|
|
||||||
|
static uint8_t lcd_old_cursor = CURSOR_NONE; |
||||||
|
static bool lcd_enabled = false; |
||||||
|
|
||||||
|
// Start address of rows
|
||||||
|
const uint8_t LCD_ROW_ADDR[] = {0x00, 0x40, 0x14, 0x54}; |
||||||
|
|
||||||
|
/** Initialize the display */ |
||||||
|
void lcd_init() |
||||||
|
{ |
||||||
|
// Magic sequence to invoke Cthulhu (or enter 4-bit mode)
|
||||||
|
sleep_ms(100); |
||||||
|
lcd_write_nibble(0b0011); |
||||||
|
lcd_clk(); |
||||||
|
sleep_ms(5); |
||||||
|
lcd_clk(); |
||||||
|
sleep_ms(1); |
||||||
|
lcd_clk(); |
||||||
|
sleep_ms(1); |
||||||
|
lcd_write_nibble(0b0010); |
||||||
|
lcd_clk(); |
||||||
|
sleep_us(100); |
||||||
|
|
||||||
|
// Configure the display
|
||||||
|
lcd_command(LCD_IFACE_4BIT_2LINE); |
||||||
|
lcd_command(LCD_DISABLE); |
||||||
|
lcd_command(LCD_CLEAR); |
||||||
|
lcd_command(LCD_MODE_INC); |
||||||
|
|
||||||
|
// mark as enabled
|
||||||
|
lcd_enable(); |
||||||
|
|
||||||
|
lcd_pos.x = 0; |
||||||
|
lcd_pos.y = 0; |
||||||
|
lcd_addrtype = LCD_ADDRTYPE_TEXT; |
||||||
|
} |
||||||
|
|
||||||
|
/** Write an instruction byte */ |
||||||
|
void lcd_command(uint8_t bb) |
||||||
|
{ |
||||||
|
lcd_wait_ready(); |
||||||
|
lcd_mode_instr(); |
||||||
|
lcd_write_byte(bb); // send instruction byte
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Write a data byte */ |
||||||
|
void lcd_write(uint8_t bb) |
||||||
|
{ |
||||||
|
if (lcd_addrtype == LCD_ADDRTYPE_TEXT) { |
||||||
|
if (bb == '\r') { |
||||||
|
// CR
|
||||||
|
lcd_pos.x = 0; |
||||||
|
lcd_xy(lcd_pos.x, lcd_pos.y); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (bb == '\n') { |
||||||
|
// LF
|
||||||
|
lcd_pos.y++; |
||||||
|
lcd_xy(lcd_pos.x, lcd_pos.y); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
lcd_pos.x++; |
||||||
|
} |
||||||
|
|
||||||
|
lcd_wait_ready(); |
||||||
|
lcd_mode_data(); |
||||||
|
lcd_write_byte(bb); // send data byte
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Write a byte using the 4-bit interface */ |
||||||
|
static void lcd_write_byte(uint8_t bb) |
||||||
|
{ |
||||||
|
lcd_write_high(bb); |
||||||
|
lcd_clk(); |
||||||
|
|
||||||
|
lcd_write_low(bb); |
||||||
|
lcd_clk(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Send a string to LCD */ |
||||||
|
void lcd_puts(char *str) |
||||||
|
{ |
||||||
|
char c; |
||||||
|
while ((c = *str++)) { |
||||||
|
lcd_putc(c); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** Sedn a char to LCD */ |
||||||
|
void lcd_putc(const char c) |
||||||
|
{ |
||||||
|
lcd_write(c); |
||||||
|
} |
||||||
|
|
||||||
|
/** Set cursor position */ |
||||||
|
void lcd_xy(const uint8_t x, const uint8_t y) |
||||||
|
{ |
||||||
|
lcd_pos.x = x; |
||||||
|
lcd_pos.y = y; |
||||||
|
lcd_addr(LCD_ROW_ADDR[y] + (x)); |
||||||
|
} |
||||||
|
|
||||||
|
/** Set LCD cursor. If not enabled, only remember it. */ |
||||||
|
void lcd_set_cursor(uint8_t type) |
||||||
|
{ |
||||||
|
lcd_old_cursor = (type & CURSOR_BAR_BLINK); |
||||||
|
|
||||||
|
if (lcd_enabled) { lcd_command(LCD_CURSOR_NONE | lcd_old_cursor); } |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Disable display (preserving cursor) */ |
||||||
|
void lcd_disable() |
||||||
|
{ |
||||||
|
lcd_command(LCD_DISABLE); |
||||||
|
lcd_enabled = false; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Enable display (restoring cursor) */ |
||||||
|
void lcd_enable() |
||||||
|
{ |
||||||
|
lcd_enabled = true; |
||||||
|
lcd_set_cursor(lcd_old_cursor); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Go home */ |
||||||
|
void lcd_home() |
||||||
|
{ |
||||||
|
lcd_command(LCD_HOME); |
||||||
|
lcd_pos.x = 0; |
||||||
|
lcd_pos.y = 0; |
||||||
|
lcd_addrtype = LCD_ADDRTYPE_TEXT; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Clear the screen */ |
||||||
|
void lcd_clear() |
||||||
|
{ |
||||||
|
lcd_command(LCD_CLEAR); |
||||||
|
lcd_pos.x = 0; |
||||||
|
lcd_pos.y = 0; |
||||||
|
lcd_addrtype = LCD_ADDRTYPE_TEXT; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Define a glyph */ |
||||||
|
void lcd_glyph(const uint8_t index, const uint8_t *array) |
||||||
|
{ |
||||||
|
lcd_addr_cg(index * 8); |
||||||
|
for (uint8_t i = 0; i < 8; ++i) { |
||||||
|
lcd_write(array[i]); |
||||||
|
} |
||||||
|
|
||||||
|
// restore previous position
|
||||||
|
lcd_xy(lcd_pos.x, lcd_pos.y); |
||||||
|
lcd_addrtype = LCD_ADDRTYPE_TEXT; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Set address in CGRAM */ |
||||||
|
void lcd_addr_cg(const uint8_t acg) |
||||||
|
{ |
||||||
|
lcd_addrtype = LCD_ADDRTYPE_CG; |
||||||
|
lcd_command(0b01000000 | ((acg) & 0b00111111)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Set address in DDRAM */ |
||||||
|
void lcd_addr(const uint8_t add) |
||||||
|
{ |
||||||
|
lcd_addrtype = LCD_ADDRTYPE_TEXT; |
||||||
|
lcd_command(0b10000000 | ((add) & 0b01111111)); |
||||||
|
} |
@ -0,0 +1,62 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
// HD44780 LCD display driver - 4-bit mode
|
||||||
|
//
|
||||||
|
// LCD pins are configured using a file lcd_config.h, which you
|
||||||
|
// have to add next to your main.c file.
|
||||||
|
//
|
||||||
|
// Content can be something like this:
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
#include <stdbool.h> |
||||||
|
|
||||||
|
/** Initialize the display */ |
||||||
|
void lcd_init(); |
||||||
|
|
||||||
|
/** Send a string to LCD */ |
||||||
|
void lcd_puts(char* str_p); |
||||||
|
|
||||||
|
/** Sedn a char to LCD */ |
||||||
|
void lcd_putc(char c); |
||||||
|
|
||||||
|
/** Show string at X, Y */ |
||||||
|
#define lcd_puts_xy(x, y, str_p) do { lcd_xy((x), (y)); lcd_puts((str_p)); } while(0) |
||||||
|
|
||||||
|
/** Show char at X, Y */ |
||||||
|
#define lcd_putc_xy(x, y, c) do { lcd_xy((x), (y)); lcd_putc((c)); } while(0) |
||||||
|
|
||||||
|
/** Set cursor position */ |
||||||
|
void lcd_xy(uint8_t x, uint8_t y); |
||||||
|
|
||||||
|
/** Set LCD cursor. If not enabled, only remember it. */ |
||||||
|
#define CURSOR_NONE 0b00 |
||||||
|
#define CURSOR_BAR 0b10 |
||||||
|
#define CURSOR_BLINK 0b01 |
||||||
|
#define CURSOR_BOTH 0b11 |
||||||
|
void lcd_set_cursor(uint8_t type); |
||||||
|
|
||||||
|
/** Display display (preserving cursor) */ |
||||||
|
void lcd_disable(); |
||||||
|
|
||||||
|
/** Enable display (restoring cursor) */ |
||||||
|
void lcd_enable(); |
||||||
|
|
||||||
|
/** Go home */ |
||||||
|
void lcd_home(); |
||||||
|
|
||||||
|
/** Clear the screen */ |
||||||
|
void lcd_clear(); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Define a glyph - 8 bytes, right 5 bits are used. |
||||||
|
* There are total 8 custom glyphs that can be defined. |
||||||
|
*/ |
||||||
|
void lcd_glyph(uint8_t index, const uint8_t* array); |
||||||
|
|
||||||
|
/** Set address in CGRAM */ |
||||||
|
void lcd_addr_cg(uint8_t acg); |
||||||
|
|
||||||
|
/** Set address in DDRAM */ |
||||||
|
void lcd_addr(uint8_t add); |
@ -0,0 +1,161 @@ |
|||||||
|
#include <stdio.h> |
||||||
|
#include <pico/binary_info/code.h> |
||||||
|
#include <pico/stdlib.h> |
||||||
|
#include <hardware/i2c.h> |
||||||
|
#include <hardware/adc.h> |
||||||
|
#include <hardware/irq.h> |
||||||
|
#include "pinout.h" |
||||||
|
#include "lcd.h" |
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
PINOUT |
||||||
|
|
||||||
|
Keypad - UART RX - receives symbols from STM8 |
||||||
|
|
||||||
|
LCD - HD44780 |
||||||
|
14 - RS (H-data, L-command) |
||||||
|
15 - EN (CLK) |
||||||
|
21,20,19,18 - D7,D6,D5,D4 |
||||||
|
RW tied low (always write) |
||||||
|
TODO backlight switching |
||||||
|
|
||||||
|
I2C |
||||||
|
16 - SDA0 |
||||||
|
17 - SCL0 |
||||||
|
|
||||||
|
EEPROM 24C32 - addr 1010_000 |
||||||
|
|
||||||
|
RTC DS3231 - addr 1101_000 |
||||||
|
|
||||||
|
Relay |
||||||
|
5, 4, 22, 26 - active high |
||||||
|
|
||||||
|
Moisture |
||||||
|
28 - ADC2 0-3V |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*/ |
||||||
|
|
||||||
|
void setup_output(uint num) |
||||||
|
{ |
||||||
|
gpio_set_dir(num, GPIO_OUT); |
||||||
|
gpio_put(num, 0); |
||||||
|
gpio_set_function(num, GPIO_FUNC_SIO); |
||||||
|
} |
||||||
|
|
||||||
|
// RX interrupt handler
|
||||||
|
void irq_uart() { |
||||||
|
while (uart_is_readable(uart0)) { |
||||||
|
uint8_t ch = uart_getc(uart0); |
||||||
|
|
||||||
|
// TODO do something useful
|
||||||
|
if (uart_is_writable(uart0)) { |
||||||
|
uart_putc(uart0, ch); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void set_relays(bool one, bool two, bool three, bool four) { |
||||||
|
gpio_put(PIN_RE1, one); |
||||||
|
gpio_put(PIN_RE2, two); |
||||||
|
gpio_put(PIN_RE3, three); |
||||||
|
gpio_put(PIN_RE1, four); |
||||||
|
} |
||||||
|
|
||||||
|
void open_valve(uint num) { |
||||||
|
gpio_put(PIN_RE1, num == 1); |
||||||
|
gpio_put(PIN_RE2, num == 2); |
||||||
|
gpio_put(PIN_RE3, num == 3); |
||||||
|
gpio_put(PIN_RE4, num == 4); |
||||||
|
} |
||||||
|
|
||||||
|
uint16_t moisture_read() { |
||||||
|
adc_select_input(ADC_NUM_MOISTURE); |
||||||
|
return adc_read(); |
||||||
|
} |
||||||
|
|
||||||
|
int main() |
||||||
|
{ |
||||||
|
// picotool binary info
|
||||||
|
bi_decl(bi_1pin_with_name(PIN_LED, "LED")); |
||||||
|
bi_decl(bi_1pin_with_name(PIN_RE1, "RE1")); |
||||||
|
bi_decl(bi_1pin_with_name(PIN_RE2, "RE2")); |
||||||
|
bi_decl(bi_1pin_with_name(PIN_RE3, "RE3")); |
||||||
|
bi_decl(bi_1pin_with_name(PIN_RE4, "RE4")); |
||||||
|
bi_decl(bi_1pin_with_name(PIN_LCD_RS, "LCD RS")); |
||||||
|
bi_decl(bi_1pin_with_name(PIN_LCD_E, "LCD CLK")); |
||||||
|
bi_decl(bi_1pin_with_name(PIN_LCD_D7, "LCD D7")); |
||||||
|
bi_decl(bi_1pin_with_name(PIN_LCD_D6, "LCD D6")); |
||||||
|
bi_decl(bi_1pin_with_name(PIN_LCD_D5, "LCD D5")); |
||||||
|
bi_decl(bi_1pin_with_name(PIN_LCD_D4, "LCD D4")); |
||||||
|
bi_decl(bi_2pins_with_func(PIN_I2C_SDA, PIN_I2C_SCL, GPIO_FUNC_I2C)); |
||||||
|
bi_decl(bi_1pin_with_name(PIN_MOISTURE, "ADC (moisture)")); |
||||||
|
bi_decl(bi_program_description("Zavlaha Kuchynka")); |
||||||
|
|
||||||
|
setup_default_uart(); |
||||||
|
irq_set_exclusive_handler(UART0_IRQ, irq_uart); |
||||||
|
irq_set_enabled(UART0_IRQ, true); |
||||||
|
uart_set_irq_enables(uart0, 1, 0); |
||||||
|
|
||||||
|
/* On-board LED */ |
||||||
|
setup_output(PIN_LED); |
||||||
|
|
||||||
|
/* Valve relays */ |
||||||
|
setup_output(PIN_RE1); |
||||||
|
setup_output(PIN_RE2); |
||||||
|
setup_output(PIN_RE3); |
||||||
|
setup_output(PIN_RE4); |
||||||
|
|
||||||
|
/* LCD */ |
||||||
|
setup_output(PIN_LCD_RS); |
||||||
|
setup_output(PIN_LCD_RW); |
||||||
|
setup_output(PIN_LCD_E); |
||||||
|
setup_output(PIN_LCD_D7); |
||||||
|
setup_output(PIN_LCD_D6); |
||||||
|
setup_output(PIN_LCD_D5); |
||||||
|
setup_output(PIN_LCD_D4); |
||||||
|
|
||||||
|
/* I2C */ |
||||||
|
i2c_init(i2c0, 100 * 1000); // 100 kbps - play it safe
|
||||||
|
gpio_set_function(PIN_I2C_SDA, GPIO_FUNC_I2C); |
||||||
|
gpio_set_function(PIN_I2C_SCL, GPIO_FUNC_I2C); |
||||||
|
gpio_pull_up(PIN_I2C_SDA); |
||||||
|
gpio_pull_up(PIN_I2C_SCL); |
||||||
|
|
||||||
|
/* ADC for moisture */ |
||||||
|
adc_init(); |
||||||
|
adc_gpio_init(PIN_MOISTURE); |
||||||
|
|
||||||
|
lcd_init(); |
||||||
|
lcd_puts("HELLO WORLD!"); |
||||||
|
|
||||||
|
uint cnt = 0; |
||||||
|
char buf[16]; |
||||||
|
while (1) { |
||||||
|
lcd_clear(); |
||||||
|
lcd_puts("HELLO WORLD!"); |
||||||
|
|
||||||
|
gpio_put(PIN_LED, 1); // LED on
|
||||||
|
|
||||||
|
uint16_t moisture = moisture_read(); |
||||||
|
sprintf(buf, "ADC = %lu", moisture); |
||||||
|
lcd_xy(0, 1); |
||||||
|
lcd_puts(buf); |
||||||
|
lcd_xy(15, 3); |
||||||
|
lcd_putc('0' + cnt); |
||||||
|
|
||||||
|
sleep_ms(100); |
||||||
|
gpio_put(PIN_LED, 0); // LED off
|
||||||
|
sleep_ms(100); |
||||||
|
|
||||||
|
// demo that valve control works
|
||||||
|
cnt += 1; |
||||||
|
if (cnt == 5) { |
||||||
|
cnt = 0; |
||||||
|
} |
||||||
|
open_valve(cnt); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
/**
|
||||||
|
* TODO file description |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef ZAVLAHA_PINOUT_H |
||||||
|
#define ZAVLAHA_PINOUT_H |
||||||
|
|
||||||
|
#define PIN_LED PICO_DEFAULT_LED_PIN // 25
|
||||||
|
#define PIN_RE1 5 |
||||||
|
#define PIN_RE2 4 |
||||||
|
#define PIN_RE3 22 |
||||||
|
#define PIN_RE4 26 |
||||||
|
#define PIN_MOISTURE 28 |
||||||
|
#define ADC_NUM_MOISTURE 2 // ADC2
|
||||||
|
#define PIN_I2C_SDA 16 |
||||||
|
#define PIN_I2C_SCL 17 |
||||||
|
#define PIN_LCD_RS 14 |
||||||
|
#define PIN_LCD_RW 6 |
||||||
|
#define PIN_LCD_E 15 |
||||||
|
#define PIN_LCD_D7 21 |
||||||
|
#define PIN_LCD_D6 20 |
||||||
|
#define PIN_LCD_D5 19 |
||||||
|
#define PIN_LCD_D4 18 |
||||||
|
|
||||||
|
// must be shifted left before adding the RW bit!
|
||||||
|
#define I2C_ADDR_EEPROM 0b1010000 |
||||||
|
#define I2C_ADDR_RTC 0b1101000 |
||||||
|
|
||||||
|
#endif //ZAVLAHA_PINOUT_H
|
Loading…
Reference in new issue