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.
 
 
 
zavlaha-kzk/src/main.c

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
}