uni

University stuff
git clone git://git.margiolis.net/uni.git
Log | Files | Refs | README | LICENSE

commit a185dc6577db116f6c659426698d3a08d4e920b1
parent 044eb359382d61bcbdbbc605fd4c7194c7ab6b4f
Author: Christos Margiolis <christos@margiolis.net>
Date:   Fri, 28 Jan 2022 23:51:49 +0200

lcd working properly

Diffstat:
Mc_embedded/src/main.c | 219+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 147 insertions(+), 72 deletions(-)

diff --git a/c_embedded/src/main.c b/c_embedded/src/main.c @@ -1,36 +1,32 @@ #define NO_BIT_DEFINES #include <pic14regs.h> #include <stdint.h> -#include <string.h> +/*#include <string.h>*/ static __code uint16_t __at (_CONFIG) __configword = _FOSC_HS & _WDTE_OFF & _PWRTE_ON & _LVP_OFF & _WRT_OFF & _BOREN_ON & _CPD_OFF & _CP_OFF; +/* MCU related constants */ #define _XTAL_FREQ 16000000 /* Crystal oscillator running at 16MHz */ -#define TIMER_RISING_EDGE (0 << 6) /* Interrupt on rising edge */ -#define TIMER_INTERNAL_CLK (0 << 5) /* Use the CLK0 pin */ -#define TIMER_PRESCALAR_TMR0 (0 << 3) /* Assign prescalar to TMR0 */ +#define TMR0_CLK0 (0 << 5) /* Use the CLK0 pin */ /* - * The last 3 bits of OPTION_REG indicate the prescalar value. In this case, + * Bit 3 assigns the prescalar to TMR0. + * Bits 0-2 of OPTION_REG indicate the prescalar value. In this case, * 111 indicates a prescalar value of 256. */ -#define TIMER_PRESCALAR_256 0b111 +#define TMR0_PRESCALAR_256 0b0111 /* - * We want 1ms delay @ 16Mhz with 256 prescalar, the formula is: + * We want 1ms delay @ 16Mhz with 64 prescalar, the formula is: * * 256 - ((delay * (fosc / 1000)) / (prescalar * 4)) = * 256 - ((1 * (16000000 / 1000)) / (256 * 4)) = - * 256 - ((1 * 16000) / (256 * 4)) = - * 256 - 15.625 = ~240 + * 256 - ((1 * 16000) / (256 * 4)) = ~240 * * sdcc thinks there's an overflow here (hint: he's wrong)... */ -#define TIMER_DELAY (256 - ((1 * (_XTAL_FREQ / 1000)) / (256 * 4))) -#define TIMER_REQ_MAX 3 - -#define OUTPUT 0 -#define INPUT 1 +#define TMR0_DELAY (256 - ((1 * (_XTAL_FREQ / 1000)) / (256 * 4))) +#define TMR0_REQ_MAX 3 #define BTN_PORT PORTBbits.RB0 #define BTN_TRIS TRISBbits.TRISB0 @@ -39,18 +35,28 @@ static __code uint16_t __at (_CONFIG) __configword = #define LED_PORT PORTBbits.RB1 #define LED_TRIS TRISBbits.TRISB1 -#define LCD_RS PORTCbits.RC0 -#define LCD_RW PORTCbits.RC1 -#define LCD_EN PORTCbits.RC2 +#define LCD_RS PORTCbits.RC0 /* Instruction reg: 0, Data reg: 1 */ +#define LCD_RW PORTCbits.RC1 /* Write: 0, Read: 1 */ +#define LCD_EN PORTCbits.RC2 /* Enable read/write */ #define LCD_PORT_DATA PORTD -#define LCD_SEL_INST 0 -#define LCD_SEL_DATA 1 +#define LCD_PORT_DATA_DIR TRISD +#define LCD_PORT_CTL_DIR TRISC +#define LCD_SEL_INST 0 /* Instruction register for RS */ +#define LCD_SEL_DATA 1 /* Data register for RS */ #define LCD_CLEAR 0x01 /* Clear screen */ -#define LCD_CURS_ZERO 0x02 /* Set cursor on (0, 0) */ +#define LCD_CURS_ROW1 0x02 /* Set cursor on (0, 0) */ +#define LCD_CURS_ROW2 0xc0 /* Set cursor on (1, 0) */ #define LCD_CURS_INC 0x06 /* Auto-increment cursor */ #define LCD_CURS_OFF 0x0c /* Hide cursor */ -#define LCD_MODE 0x38 /* 16x2 setup */ -#define LCD_DISPLAY_INIT 0x32 /* Required */ +#define LCD_MODE 0x38 /* 8-bit, 16x2 */ + +#define OUTPUT 0 +#define INPUT 1 + +/* Non MCU related constants */ +#define NULL ((void *)0) +#define BUFSIZ (3 * sizeof(uint32_t)) + /* Function macros */ #define lcd_putc(c) lcd_data(c, LCD_SEL_DATA) #define lcd_cmd(cmd) lcd_data(cmd, LCD_SEL_INST) @@ -58,13 +64,14 @@ static __code uint16_t __at (_CONFIG) __configword = typedef void (*ev_handler)(void); struct timer_req { - ev_handler handler; - uint32_t rate; - uint32_t cnt; + ev_handler handler; /* ISR callback */ + uint32_t rate; /* Interval */ + uint32_t cnt; /* Current time */ }; -static void delay_ms(uint32_t); +/* Function declarations */ static void tmr0_init(void); +static void tmr0_delay_ms(uint32_t); static int tmr0_set_event(ev_handler, uint32_t); static void tmr0_isr(void) __interrupt; static void led_blink(void); @@ -72,45 +79,51 @@ static void button_debounce(void); static void lcd_init(void); static void lcd_data(uint8_t, uint8_t); static void lcd_puts(const char *); +static void ctx_main(void); +static void ctx_uptime_maxtp(void); +static char *itoa(char *, uint32_t); +static void *memset(void *, int, int); -static struct timer_req reqs[TIMER_REQ_MAX]; -static uint32_t timecnt = 0; /* Seconds passed since start */ - -static void -delay_ms(uint32_t t) -{ - while (t--) - __asm nop __endasm; -} +/* Global variables */ +static struct timer_req reqs[TMR0_REQ_MAX]; +static uint32_t timecnt = 0; /* Seconds passed since start */ +static int f_ctx = 0; /* Change context */ +static uint8_t humid = 0; /* Current humidity */ +static int8_t tp = 0; /* Current temperature */ +static int8_t maxtp = 0; /* Max temperature */ +static char buf[BUFSIZ+1] = {0}; /* Generic buffer */ +/* Function implementations */ static void tmr0_init(void) { - struct timer_req *r; - uint8_t i; - - for (i = 0; i < TIMER_REQ_MAX; i++) { - r = &reqs[i]; - r->handler = NULL; - r->rate = 0; - r->cnt = 0; - } + memset(reqs, 0, sizeof(reqs)); OPTION_REG = 0; - OPTION_REG |= TIMER_INTERNAL_CLK | TIMER_RISING_EDGE | - TIMER_PRESCALAR_TMR0 | TIMER_PRESCALAR_256; - TMR0 = TIMER_DELAY; + OPTION_REG |= TMR0_CLK0 | TMR0_PRESCALAR_256; + TMR0 = TMR0_DELAY; INTCONbits.TMR0IE = 1; /* TMR0 Interrupt Enable */ INTCONbits.GIE = 1; /* Global Interrupt Enable */ INTCONbits.PEIE = 1; /* Peripheral Interrupt Enable */ } +static void +tmr0_delay_ms(uint32_t t) +{ + while (t--) { + while (INTCONbits.TMR0IF == 0) + ; /* nothing */ + INTCONbits.TMR0IF = 0; + TMR0 = TMR0_DELAY; + } +} + static int tmr0_set_event(ev_handler handler, uint32_t rate) { struct timer_req *r; uint8_t i; - for (i = 0; i < TIMER_REQ_MAX; i++) { + for (i = 0; i < TMR0_REQ_MAX; i++) { r = &reqs[i]; if (r->handler != NULL) continue; @@ -130,7 +143,7 @@ tmr0_isr(void) __interrupt if (INTCONbits.TMR0IF != 1) return; - for (i = 0; i < TIMER_REQ_MAX; i++) { + for (i = 0; i < TMR0_REQ_MAX; i++) { r = &reqs[i]; if (r->handler == NULL) continue; @@ -139,7 +152,7 @@ tmr0_isr(void) __interrupt r->cnt = 0; } } - TMR0 = TIMER_DELAY; + TMR0 = TMR0_DELAY; INTCONbits.TMR0IF = 0; /* Clear interrupt flags */ } @@ -149,12 +162,11 @@ led_blink(void) LED_PORT ^= 1; /* * Increment here since this function is called every 1 sec. - * No need to create another one. + * No need to create another timer callback. */ timecnt++; } - static void button_debounce(void) { @@ -162,45 +174,43 @@ button_debounce(void) /* Button is pressed */ if (BTN_PORT == 0) { - if (cnt == 0) + if (cnt == 0) { + /* Actual button functionality goes here. */ + f_ctx = 1; cnt++; + } cnt = BTN_DEBOUNCE_TIME_MS; - } else if (cnt != 0) + } else if (cnt != 0) { cnt--; + f_ctx = 0; + } } -/* FIXME: fix delays */ static void lcd_init(void) { - LCD_PORT_DATA = 0; + LCD_PORT_CTL_DIR = OUTPUT; + LCD_PORT_DATA_DIR = OUTPUT; LCD_RS = 0; LCD_RW = 0; LCD_EN = 0; - TRISC = OUTPUT; - TRISD = OUTPUT; - lcd_cmd(LCD_DISPLAY_INIT); - delay_ms(150); - lcd_cmd(LCD_DISPLAY_INIT); - delay_ms(150); - lcd_cmd(LCD_MODE); + tmr0_delay_ms(15); + lcd_cmd(LCD_CURS_ROW1); + lcd_cmd(LCD_CURS_OFF); lcd_cmd(LCD_CURS_INC); - lcd_cmd(LCD_CURS_ZERO); lcd_cmd(LCD_CLEAR); - lcd_cmd(LCD_CURS_OFF); } -/* FIXME: fix delays */ static void lcd_data(uint8_t c, uint8_t rs) { LCD_RS = rs; LCD_RW = 0; - LCD_EN = 1; LCD_PORT_DATA = c; - delay_ms(500); + LCD_EN = 1; + tmr0_delay_ms(2); LCD_EN = 0; } @@ -211,20 +221,85 @@ lcd_puts(const char *str) lcd_putc(*str++); } +/* Helper to clean up the code below */ +#define LCD_PUTS_BUF(buf, v) do { \ + memset(buf, 0, sizeof(buf)); \ + lcd_puts(itoa(&buf[sizeof(buf)-1], v)); \ +} while (0) + +static void +ctx_main(void) +{ + lcd_cmd(LCD_CURS_ROW1); + lcd_puts("19390133"); + + lcd_cmd(LCD_CURS_ROW2); + LCD_PUTS_BUF(buf, tp); + lcd_puts("\337C "); + + LCD_PUTS_BUF(buf, humid); + lcd_puts("%"); +} + +static void +ctx_uptime_maxtp(void) +{ + lcd_cmd(LCD_CURS_ROW1); + lcd_puts("T: "); + LCD_PUTS_BUF(buf, timecnt); + + lcd_cmd(LCD_CURS_ROW2); + lcd_puts("Max: "); + LCD_PUTS_BUF(buf, maxtp); + lcd_puts("\337C"); +} + +#undef LCD_PUTS_BUF + +/* + * To avoid reversing the string, the caller has to provide a pointer to the + * end of the string. + */ +static char * +itoa(char *s, uint32_t n) +{ + *s = '\0'; + if (n == 0) + *--s = '0'; + for (; n; n /= 10) + *--s = n % 10 + '0'; + return (s); +} + +static void * +memset(void *dst, int v, int len) +{ + uint8_t *dst0; + + dst0 = dst; + while (len--) + *dst0++ = v; + return (dst); +} + void main(void) { tmr0_init(); - tmr0_set_event(&led_blink, 1000); /* Blink every 1 sec */ + tmr0_set_event(&led_blink, 1000); tmr0_set_event(&button_debounce, 1); lcd_init(); - lcd_cmd(LCD_CURS_ZERO); - lcd_puts("19390133"); BTN_TRIS = INPUT; - LED_PORT = 1; /* LED on */ + LED_PORT = 0; /* LED on */ LED_TRIS = OUTPUT; for (;;) { + lcd_cmd(LCD_CLEAR); + if (!f_ctx) + ctx_main(); + else + ctx_uptime_maxtp(); + tmr0_delay_ms(1000); } }