You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
275 lines
6.5 KiB
275 lines
6.5 KiB
#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 <hardware/sync.h>
|
|
#include "pinout.h"
|
|
#include "lcd.h"
|
|
#include "ds_rtc.h"
|
|
#include "ee.h"
|
|
#include "lcd/lcdbuf.h"
|
|
#include "screens/app_gui.h"
|
|
#include "app_config.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);
|
|
}
|
|
|
|
#define KEYPAD_BUFFER_LEN 10
|
|
static uint8_t keypad_buffer[KEYPAD_BUFFER_LEN];
|
|
static uint8_t keypad_buffer_wp = 0;
|
|
static uint8_t keypad_buffer_rp = 0;
|
|
|
|
// RX interrupt handler
|
|
void irq_uart() {
|
|
while (uart_is_readable(uart0)) {
|
|
uint8_t ch = uart_getc(uart0);
|
|
|
|
if (keypad_buffer[keypad_buffer_wp] == 0) {
|
|
keypad_buffer[keypad_buffer_wp] = ch;
|
|
keypad_buffer_wp++;
|
|
if (keypad_buffer_wp >= KEYPAD_BUFFER_LEN) {
|
|
keypad_buffer_wp = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int __attribute__((noreturn)) 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_RE5, "RE5"));
|
|
bi_decl(bi_1pin_with_name(PIN_RE6, "RE6"));
|
|
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);
|
|
setup_output(PIN_RE5);
|
|
setup_output(PIN_RE6);
|
|
|
|
/* 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);
|
|
|
|
appconfig_load();
|
|
|
|
lcd_init();
|
|
|
|
gui_init();
|
|
|
|
for(;;) {
|
|
// Check if any key was pushed
|
|
uint32_t interrupts = save_and_disable_interrupts();
|
|
GuiEvent event = GUI_EVENT_NONE;
|
|
if (keypad_buffer[keypad_buffer_rp] != 0) {
|
|
char ch = keypad_buffer[keypad_buffer_rp];
|
|
keypad_buffer[keypad_buffer_rp] = 0;
|
|
keypad_buffer_rp++;
|
|
if (keypad_buffer_rp >= KEYPAD_BUFFER_LEN) {
|
|
keypad_buffer_rp = 0;
|
|
}
|
|
event = ch; // there is 1:1 mapping for keypad ASCII
|
|
}
|
|
restore_interrupts(interrupts);
|
|
|
|
gui_loop_iter(event);
|
|
|
|
// TODO scheduler logic
|
|
}
|
|
|
|
//
|
|
// struct LcdBuffer lcd;
|
|
// LcdBuffer_Init(&lcd, CGROM_A00, CGRAM_CZ);
|
|
//
|
|
// LcdBuffer_Write(&lcd, 0, 0, "ěščřŽÝÁÍ pyčo!");
|
|
// LcdBuffer_Flush(&lcd);
|
|
//
|
|
// char buf[100];
|
|
// while (1) {
|
|
// struct rtc_time time;
|
|
// if (0 == rtc_get_time(&time)) {
|
|
// sprintf(buf, "čas: %02d:%02d:%02d", time.hour, time.minute, time.second);
|
|
// LcdBuffer_Write(&lcd, 2, 2, buf);
|
|
// }
|
|
// LcdBuffer_Flush(&lcd);
|
|
//
|
|
// sleep_ms(1000);
|
|
// }
|
|
|
|
#if 0
|
|
|
|
// while (1) {
|
|
// int y;
|
|
// lcd_clear();
|
|
//
|
|
// y = 0;
|
|
// for (int j = 0; j < 80; j += 20) {
|
|
// lcd_xy(0, y++);
|
|
// for (int i = j; i < j + 20; i++) {
|
|
// lcd_putc(i);
|
|
// }
|
|
// }
|
|
//
|
|
// sleep_ms(5000);
|
|
// lcd_clear();
|
|
//
|
|
// y = 0;
|
|
// for (int j = 80; j < 160; j += 20) {
|
|
// lcd_xy(0, y++);
|
|
// for (int i = j; i < j + 20; i++) {
|
|
// lcd_putc(i);
|
|
// }
|
|
// }
|
|
//
|
|
// sleep_ms(5000);
|
|
// lcd_clear();
|
|
//
|
|
// y = 0;
|
|
// for (int j = 160; j < 240; j += 20) {
|
|
// lcd_xy(0, y++);
|
|
// for (int i = j; i < j + 20; i++) {
|
|
// lcd_putc(i);
|
|
// }
|
|
// }
|
|
//
|
|
// sleep_ms(5000);
|
|
// lcd_clear();
|
|
//
|
|
// for (int i = 240; i < 256; i++) {
|
|
// lcd_putc(i);
|
|
// }
|
|
//
|
|
// sleep_ms(5000);
|
|
// }
|
|
|
|
|
|
lcd_puts("HELLO WORLD!");
|
|
|
|
uint8_t ee_data[1] = {};
|
|
int ee_rv = ee_read(0, ee_data, 1);
|
|
printf("ee rd rv = %d, val %02x", ee_rv, ee_data[0]);
|
|
|
|
ee_data[0]++;
|
|
ee_rv = ee_write(0, ee_data, 1);
|
|
printf("ee wr rv = %d", ee_rv);
|
|
|
|
int boot_count = ee_data[0];
|
|
|
|
uint cnt = 0;
|
|
char buf[20];
|
|
while (1) {
|
|
lcd_clear();
|
|
sprintf(buf, "ZAVLAHA-Boot=%d", boot_count);
|
|
lcd_puts(buf);
|
|
|
|
// Try to read RTC
|
|
struct rtc_time time;
|
|
if (0 == rtc_get_time(&time)) {
|
|
sprintf(buf, "%02d:%02d:%02d", time.hour, time.minute, time.second);
|
|
lcd_xy(0, 2);
|
|
lcd_puts(buf);
|
|
} else {
|
|
lcd_xy(0, 2);
|
|
lcd_puts("RTC err!");
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|