From eb5ed0c518f93036b2ea26776ce1719229e48d11 Mon Sep 17 00:00:00 2001 From: Jan Michel Date: Tue, 4 Aug 2015 18:57:10 +0200 Subject: [PATCH] framework for pt100 reader --- pt100/Makefile | 11 +-- pt100/eeprom.c | 10 +++ pt100/keys.c | 22 +++++ pt100/lcdlib/lcd-color-graphic.c | 141 ++++++++++++++++++++--------- pt100/lcdlib/lcd-color-graphic.h | 31 ++++--- pt100/main.c | 109 ++++++++++++++++++++--- pt100/main.h | 47 ++++++++-- pt100/tempmeas.c | 34 +++++++ pt100/uart.c | 146 +++++++++++++++++++++++++++++++ 9 files changed, 478 insertions(+), 73 deletions(-) create mode 100644 pt100/eeprom.c create mode 100644 pt100/keys.c create mode 100644 pt100/tempmeas.c create mode 100644 pt100/uart.c diff --git a/pt100/Makefile b/pt100/Makefile index 61201f8..73d8224 100644 --- a/pt100/Makefile +++ b/pt100/Makefile @@ -5,12 +5,13 @@ # (GNU make, BSD make, SysV make) -MCU = atmega1284p +MCU = atmega324p FORMAT = ihex TARGET = main SRC = $(TARGET).c lcdlib/lcd-color-graphic.c lcdlib/font.c \ lcdlib/Fonts/digits_24px.c lcdlib/Fonts/digits_32px.c lcdlib/Fonts/font_proportional_16px.c \ - lcdlib/Fonts/font_proportional_8px.c lcdlib/Fonts/symbols_16px.c + lcdlib/Fonts/font_proportional_8px.c lcdlib/Fonts/symbols_16px.c \ + uart.c eeprom.c tempmeas.c keys.c ASRC = OPT = 2 @@ -114,7 +115,7 @@ AVRDUDE_FLAGS = $(AVRDUDE_BASIC) $(AVRDUDE_NO_VERIFY) $(AVRDUDE_VERBOSE) $(AVRDU CC = avr-gcc OBJCOPY = avr-objcopy OBJDUMP = avr-objdump -SIZE = avr-size +SIZE = ~/bin/avr-size NM = avr-nm AVRDUDE = avrdude REMOVE = rm -f @@ -135,7 +136,7 @@ ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) # Default target. all: build -build: elf hex eep lss +build: elf hex eep lss size elf: $(TARGET).elf hex: $(TARGET).hex @@ -150,7 +151,7 @@ program: $(TARGET).hex $(TARGET).eep size: - $(SIZE) $(TARGET).elf + $(SIZE) -C --mcu=$(MCU) $(TARGET).elf #-C --mcu=$(MCU) # Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. COFFCONVERT=$(OBJCOPY) --debugging \ diff --git a/pt100/eeprom.c b/pt100/eeprom.c new file mode 100644 index 0000000..9ae56e5 --- /dev/null +++ b/pt100/eeprom.c @@ -0,0 +1,10 @@ +#include + + +void eeprom_write(uint8_t addr, uint16_t value) { + eeprom_update_word((uint16_t*)(uint16_t)(addr*2),value); + } + +uint16_t eeprom_read(uint8_t addr) { + return eeprom_read_word((uint16_t*)(uint16_t)(addr*2)); + } diff --git a/pt100/keys.c b/pt100/keys.c new file mode 100644 index 0000000..3d49b5b --- /dev/null +++ b/pt100/keys.c @@ -0,0 +1,22 @@ +#include "main.h" + + +void scan_keys(void){ + static uint8_t key_state_m0, key_state_m1; + uint8_t key_state = ~(KEYPIN) & ACTIVE_KEYS_MASK; + // -------has state changed?---- --- is key pressed now? --- + keys_pressed |= (key_state_m0 ^ key_state_m1) & key_state; + + key_state_m1 = key_state_m0; + key_state_m0 = key_state; +} + + + +uint8_t key_was_pressed(uint8_t key_mask){ + // was one of the keys defined by key mask pressed? + uint8_t result = keys_pressed & key_mask; + keys_pressed &= ~(key_mask); + return result; +} + \ No newline at end of file diff --git a/pt100/lcdlib/lcd-color-graphic.c b/pt100/lcdlib/lcd-color-graphic.c index 8403f96..a3b1c52 100644 --- a/pt100/lcdlib/lcd-color-graphic.c +++ b/pt100/lcdlib/lcd-color-graphic.c @@ -14,8 +14,8 @@ * Background is used as background, e.g. when writing fonts. */ -color_t foreground = {.red=0x1F, .green=0x3F, .blue=0x1F}; -color_t background = {.red=0, .green=0, .blue=0}; +color_t foreground; +color_t background; /****************************************************************************** @@ -25,6 +25,7 @@ void lcd_init() { LCD_SET_PIN_DIRECTIONS(); //set outputs _delay_ms(1); LCD_INIT_SPI(); //Initialize SPI Interface + LCD_UNSELECT(); _delay_ms(50); LCD_RESET_ON(); //Apply Reset to the Display Controller _delay_ms(100); @@ -33,6 +34,7 @@ void lcd_init() { LCD_SELECT(); //Switches chip select on lcd_command(LCD_SLEEP_OUT); //Wake up LCD _delay_ms(70); + lcd_command_1(LCD_COLOR_MODE,LCD_16BIT); return; } @@ -40,11 +42,22 @@ void lcd_init() { /****************************************************************************** * Sends a command to the display */ -inline void lcd_command(uint8_t c) { - spi_wait_for_idle(); - LCD_CMD(); - spi_write(c); - } +// inline void lcd_command(uint8_t c) { +// spi_wait_for_idle(); +// LCD_CMD(); +// spi_write(c); +// } + + +/****************************************************************************** + * Sends a data word to the display + */ +// inline void lcd_data(uint8_t c) { +// spi_wait_for_idle(); +// LCD_DATA(); +// spi_write(c); +// } + /****************************************************************************** * Sends a command with one argument @@ -53,25 +66,18 @@ inline void lcd_command_1(uint8_t c, uint8_t data) { lcd_command(c); lcd_data(data); } - -/****************************************************************************** - * Sends a data word to the display - */ -inline void lcd_data(uint8_t c) { - spi_wait_for_idle(); - LCD_DATA(); - spi_write(c); -} - - /****************************************************************************** * Stores the main drawing color for later use */ inline void lcd_set_foreground(uint8_t r, uint8_t g, uint8_t b) { - foreground.red = r; - foreground.green = g; - foreground.blue = b; + uint16_t t = r<<11 | g<<5 | b; + foreground.c1 = t>>8; + foreground.c2 = t; + } +inline void lcd_use_foreground(color_t color) { + foreground.c1 = color.c1; + foreground.c2 = color.c2; } @@ -79,11 +85,24 @@ inline void lcd_set_foreground(uint8_t r, uint8_t g, uint8_t b) { * Stores the background color for later use */ inline void lcd_set_background(uint8_t r, uint8_t g, uint8_t b) { - background.red = r; - background.green = g; - background.blue = b; + uint16_t t = r<<11 | g<<5 | b; + background.c1 = t>>8; + background.c2 = t; } - +inline void lcd_use_background(color_t color) { + background.c1 = color.c1; + background.c2 = color.c2; + } + +/****************************************************************************** + * Stores the background color for later use + */ +inline void lcd_set_color(color_t* color, uint8_t r, uint8_t g, uint8_t b) { + uint16_t t = r<<11 | g<<5 | b; + color->c1 = t>>8; + color->c2 = t; + } + /****************************************************************************** * Sets the column range used for the next write operation @@ -91,28 +110,38 @@ inline void lcd_set_background(uint8_t r, uint8_t g, uint8_t b) { inline void lcd_set_column(uint16_t start, uint16_t end) { lcd_command(LCD_SET_COLUMN); lcd_data(start >> 8); - lcd_data(start); - lcd_data(end >> 8); - lcd_data(end); + lcd_data_cont(start); + lcd_data_cont(end >> 8); + lcd_data_cont(end); } - +inline void lcd_set_column_short(uint16_t start) { + lcd_command(LCD_SET_COLUMN); + lcd_data(start >> 8); + lcd_data_cont(start); + } + /****************************************************************************** * Sets the page range used for the next write operation */ inline void lcd_set_page(uint16_t start, uint16_t end) { lcd_command(LCD_SET_PAGE); lcd_data(start >> 8); - lcd_data(start); - lcd_data(end >> 8); - lcd_data(end); + lcd_data_cont(start); + lcd_data_cont(end >> 8); + lcd_data_cont(end); + } +inline void lcd_set_page_short(uint16_t start) { + lcd_command(LCD_SET_PAGE); + lcd_data(start >> 8); + lcd_data_cont(start); } /****************************************************************************** * Writes a pixel to the display using 16 Bit color mode */ inline void lcd_send_pixel(color_t c) { - lcd_data((c.red<<3) | (c.green>>3)); - lcd_data((c.green<<5) | c.blue); + lcd_data(c.c1); + lcd_data_cont(c.c2); } /****************************************************************************** @@ -125,7 +154,16 @@ inline void lcd_set_pixel_xy(uint16_t column, uint16_t page) { lcd_send_pixel(foreground); } - +/****************************************************************************** + * Sets a pixel at a given position + */ +inline void lcd_set_pixel_col_xy(uint16_t column, uint16_t page, color_t col) { + lcd_set_page_short(page); + lcd_set_column_short(column); + lcd_command(LCD_WRITE_MEM); + lcd_send_pixel(col); + } + /****************************************************************************** * This function sets an area of the screen to a given color * col0 - left edge of the area @@ -162,7 +200,7 @@ uint16_t lcd_current_column = 0; uint16_t lcd_inc_page(int16_t s) { uint16_t p = lcd_current_page; p += s; - if (p > LCD_HEIGHT/8) + if (p > LCD_HEIGHT) p = 0; lcd_current_page = p; @@ -197,18 +235,22 @@ void lcd_moveto_xy(uint16_t page, uint16_t column) { * Moves the cursor relative to the current position * pages - number of pages to move * columns - number of columns to move + * for use with the font library only */ void lcd_move_xy(int16_t pages, int16_t columns) { - lcd_moveto_xy(lcd_inc_page(pages),lcd_inc_column(columns)); + lcd_moveto_xy(lcd_inc_page(pages*8),lcd_inc_column(columns)); } /****************************************************************************** * Takes a vertical byte from the font generator and prints it on the display * b - Bit pattern to display + * c - continue writing in same page */ -void lcd_write_font_byte(uint8_t b) { - lcd_set_page(8*lcd_current_page,8*lcd_current_page+8); +void lcd_write_font_byte(uint8_t b, uint8_t c) { + if(!c) { + lcd_set_page(lcd_current_page,lcd_current_page+8); + } lcd_set_column(lcd_current_column,lcd_current_column); lcd_command(LCD_WRITE_MEM); for(uint8_t i=0;i<8;i++) { @@ -220,4 +262,25 @@ void lcd_write_font_byte(uint8_t b) { } lcd_inc_column(1); } + + +/****************************************************************************** + * Draws a line according to Bresenham (from wikipedia) + */ +void lcd_draw_line(uint16_t x0, uint16_t x1, uint16_t y0, uint16_t y1) { + int16_t dx = abs(x1-x0); + int16_t sx = x0 dy) { err += dy; x0 += sx; } /* e_xy+e_x > 0 */ + if (e2 < dx) { err += dx; y0 += sy; } /* e_xy+e_y < 0 */ + } + } + \ No newline at end of file diff --git a/pt100/lcdlib/lcd-color-graphic.h b/pt100/lcdlib/lcd-color-graphic.h index ee21b7f..b60093c 100644 --- a/pt100/lcdlib/lcd-color-graphic.h +++ b/pt100/lcdlib/lcd-color-graphic.h @@ -6,13 +6,13 @@ #include #include #include - +#include /***************************************************************************** * BEGIN CONFIG BLOCK *****************************************************************************/ -#define LCD_WIDTH 240 -#define LCD_HEIGHT 320 +#define LCD_WIDTH 320 +#define LCD_HEIGHT 240 //Should chip select (CS) be used? #define LCD_USE_CHIPSELECT 1 @@ -61,12 +61,18 @@ extern void init_spi_lcd(void); //Color struct - no bit fields are used for better performance (i.e. bit shifts //can be done while waiting for SPI, not while preparing to write the pixel) typedef struct { - uint8_t red; - uint8_t green; - uint8_t blue; + uint8_t c1; + uint8_t c2; } color_t; +#define lcd_data(c) spi_wait_for_idle();LCD_DATA();spi_write(c) +#define lcd_data_cont(c) spi_wait_for_idle();spi_write(c) +#define lcd_command(c) spi_wait_for_idle();LCD_CMD();spi_write(c) + + color_t foreground; + color_t background; + /***************************************************************************** * Public Functions *****************************************************************************/ @@ -74,13 +80,16 @@ typedef struct { void lcd_init(void); //write data word or command to the LCD - void lcd_data (uint8_t data); - void lcd_command (uint8_t cmd); +// void lcd_data (uint8_t data) ; +// void lcd_command (uint8_t cmd); void lcd_command_1 (uint8_t cmd, uint8_t data); //Set the drawing and background colors void lcd_set_foreground(uint8_t r, uint8_t g, uint8_t b); void lcd_set_background(uint8_t r, uint8_t g, uint8_t b); + void lcd_set_color(color_t* color, uint8_t r, uint8_t g, uint8_t b); + void lcd_use_foreground(color_t color); + void lcd_use_background(color_t color); //set display area for next write accesses void lcd_set_page(uint16_t start, uint16_t end); @@ -91,10 +100,12 @@ typedef struct { //Set a pixel at a given location to the foreground color void lcd_set_pixel_xy(uint16_t column, uint16_t page); + void lcd_set_pixel_col_xy(uint16_t column, uint16_t page, color_t col); //Set an area to the background color void lcd_set_area_xy(uint16_t col0, uint16_t col1, uint16_t page0, uint16_t page1); - +//Draw a straight line + void lcd_draw_line(uint16_t x1, uint16_t x2, uint16_t y1, uint16_t y2); //Text functions are included in font.c / font.h @@ -108,7 +119,7 @@ typedef struct { extern uint16_t lcd_current_column; static inline uint16_t lcd_get_position_page(void) {return lcd_current_page;} static inline uint16_t lcd_get_position_column(void) {return lcd_current_column;} - void lcd_write_font_byte(uint8_t b); + void lcd_write_font_byte(uint8_t b, uint8_t c); /***************************************************************************** diff --git a/pt100/main.c b/pt100/main.c index 9255381..fb42679 100644 --- a/pt100/main.c +++ b/pt100/main.c @@ -1,17 +1,19 @@ - - -#include -#include -#include -#include -#include - #include "main.h" #include "lcdlib/lcd-color-graphic.h" #include "lcdlib/font.h" +volatile uint16_t control_reg; +volatile uint16_t time; +volatile uint8_t keys_pressed = 0b00000000; +volatile uint8_t next_step = 0; + +volatile uint8_t measurement_active = 0; +color_t col_background; +color_t col_font; +color_t col_title; +struct calib_t calib_settings; /****************** * Init USART for LCD @@ -20,14 +22,45 @@ void init_spi_lcd(void) { UCSR1B = (1 << TXEN1); UCSR1C = (1 << UMSEL10) | (0 << UDORD1) | (0 << UCPHA1) | (0 << UCPOL1); UBRR1L = 0; - UBRR1H = 0; + UBRR1H = 0; //full speed } +/****************** + * Read calibration from eeprom + *****************/ +void read_calib() { + for(uint8_t i=0; i< 8; i++) { + calib_settings.offset_res[i] = eeprom_read(i); + } + calib_settings.gain_res = eeprom_read(8); + } +/****************** + * Some stuff on the LCD + *****************/ +void lcd_design(void) { + lcd_set_color(&col_background,0x03,0x04,0x05); + lcd_set_color(&col_title, 0x1f,0x3f,0x08); + lcd_set_color(&col_font, 0x1f,0x3f,0x08); + + lcd_use_background(col_background); + lcd_use_foreground(col_title); + lcd_set_area_xy(0, 0x13F, 0, 0xEF); + + lcd_set_font(FONT_PROP_16,DOUBLE_SIZE|SPACING); + lcd_putstr_xy_P(PSTR("PT100 Reader"),0,0); + + } + +void lcd_update(void) { + } + + /****************** * Init all functions *****************/ void init(void) { +//CPU Regs //Init ADC SPI SPCR = (0 << SPIE) | (1 << SPE ) | (0 << DORD) | (1 << MSTR) | (0 << CPOL) | (0 << CPHA) | (0 << SPR0); @@ -40,7 +73,8 @@ void init(void) { DIDR0 = 0x08; //PA3 is analog only //Init UART - + UCSR0B = (1 << RXCIE0) | (0 << TXCIE0) | (0 << UDRIE0) | (1 << RXEN0) | ( 1 << TXEN0); //udrie enabled on request + UBRR0 = 12; //38400baud //GPIO PORTD |= (0xc0); //pull-up for switches @@ -50,15 +84,66 @@ void init(void) { DDRA |= (0x70); //select outputs DDRC |= (0xc0); //outputs for Inhibit signals +//Timer0: 2ms interrupts + TCCR0A = (2 << WGM00); //CTC + TCCR0B = (3 << CS00); //fcpu/64 + OCR0A = 249; + TIMSK0 = (1 << OCF0A); //Interrupt on compare match + +//Timer1: 1s ticks to start measurement + TCCR1A = 0; + TCCR1B = (1 << WGM12) | ( 4 << CS10); //CTC, fcpu/256 + TIMSK1 = (1 << OCIE1A); + OCR1A = 31250; + + lcd_init(); + lcd_command_1(LCD_MIRROR, LCD_BGR | LCD_FLIP_XY); + lcd_command(LCD_ON); + + read_calib(); + lcd_design(); + sei(); +} + + +/********************** + * ADC finished conversion + *********************/ +ISR(ADC_vect) { } +/********************** + * 500 Hz ticks + *********************/ +ISR(TIMER0_COMPA_vect) { + time++; + next_step = 1; + } + + +/********************** + * Second ticks + *********************/ +ISR(TIMER1_COMPA_vect) { + send_information(); + measurement_active = 1; +} + + int main(void) { init(); - lcd_init(); - while(1); + while(1) { + while(next_step==0); + next_step = 0; + if (measurement_active) {do_measurement_step();} + if (time == 40) {lcd_update();} + if(key_was_pressed(1< +#include +#include +#include +#include - -#define FIRMWARE_VERSION 0x01 +#define FIRMWARE_VERSION 0x0001 #define UDORD1 2 #define UCPHA1 1 @@ -8,17 +12,46 @@ #define ADC_SELECT() PORTB &= ~(1<< PB4) #define ADC_UNSELECT() PORTB |= (1<< PB4) -#define LED1_ON() PORTB |= (1<< PB1) +#define LED1_ON() PORTB |= (1<< PB1) //while measurement ongoing #define LED1_OFF() PORTB &= ~(1<< PB1) -#define LED2_ON() PORTB |= (1<< PB0) +#define LED2_ON() PORTB |= (1<< PB0) //while transmitting data #define LED2_OFF() PORTB &= ~(1<< PB0) -#define SWITCH1() ((PIND>>PD6)&1) -#define SWITCH2() ((PIND>>PD7)&1) + +#define KEYPORT PORTD +#define KEYDDR DDRD +#define KEYPIN PIND +#define KEY_1 PD6 +#define KEY_2 PD7 +#define ACTIVE_KEYS_MASK (1<> (nib*4)) & 0xF; + if (t <= 9) {return t + 0x30;} + return t - 10 + 0x61; + } + +uint8_t hex_to_int(uint8_t h) { //assumes valid number + if (h < 0x40) return h-0x30; + if (h < 0x50) return h-0x41+10; + return h-0x61+10; + } + +uint8_t hex_to_byte(uint8_t* h) { + return hex_to_int(*h)*16 + hex_to_int(*(h+1)); + } + + +void forward_msg(uint8_t i) { + if(rxbuf[0] == 'A') rxbuf[1]++; + else rxbuf[1]--; + memcpy ((uint8_t*)txbuf,(uint8_t*)rxbuf,i); + STARTTX(i); + } + + +uint8_t is_my_address(uint8_t s) { + if (ISMYADDR() && rxbuf[0] != 'A') { + return 1; + } + else { + forward_msg(s); + return 0; + } + } + +void send_answer_hex(uint8_t type, uint8_t chan, uint32_t v) { + sei(); + while(TX_BUSY()); + txbuf[0]='A'; + txbuf[1]=type; + txbuf[2]='0'; + txbuf[3]=chan; + txbuf[4]=nib_to_hex(v,5); + txbuf[5]=nib_to_hex(v,4); + txbuf[6]=nib_to_hex(v,3); + txbuf[7]=nib_to_hex(v,2); + txbuf[8]=nib_to_hex(v,1); + txbuf[9]=nib_to_hex(v,0); + txbuf[10]='\n'; + STARTTX(11); + } + + +void send_information(void) { + sei(); + while(TX_BUSY()); + txbuf[0]='A'; + txbuf[1]='I'; + txbuf[2]='0'; + txbuf[3]='0'; + txbuf[4]=nib_to_hex(FIRMWARE_VERSION,3); + txbuf[5]=nib_to_hex(FIRMWARE_VERSION,2); + txbuf[6]=nib_to_hex(FIRMWARE_VERSION,1); + txbuf[7]=nib_to_hex(FIRMWARE_VERSION,0); + txbuf[8]=nib_to_hex(connected_sensors,1); + txbuf[9]=nib_to_hex(connected_sensors,0); + txbuf[10]='\n'; + STARTTX(11); + } + +/********************** + * UART received a byte + *********************/ +ISR(USART0_RX_vect) { + uint8_t buf = UDR1; + if (rxcnt != 0 || (buf == 'W' || buf == 'A')) { + rxbuf[rxcnt++] = buf; + } + if (buf == '\n' || buf == '\r') { + if(rxcnt == 11) { + if(rxbuf[0] == 'A') {forward_msg(rxcnt);} + else if(rxbuf[0] == 'W') { + if(rxbuf[1] == 'E') { + uint8_t addr = hex_to_byte(rxbuf+4); + eeprom_write(addr, (hex_to_byte(rxbuf+6)<<8) | hex_to_byte(rxbuf+8)); + } + else if(rxbuf[1] == 'C') { + control_reg = (hex_to_byte(rxbuf+6)<<8) | hex_to_byte(rxbuf+8); + } + else if(rxbuf[1] == 'R') { + read_calib(); + } + } + } + else { + rxcnt = 0; + } + } + if (rxcnt >= 12 || buf == '\n' || buf == '\r') { + rxcnt = 0; + } + } + +/********************** + * UART able to send a byte + *********************/ +ISR(USART0_UDRE_vect) { + LED2_ON(); + UDR0 = txbuf[txpoint++]; + if(--txcnt == 0 || txpoint > 12) { + txpoint = 0; + txcnt = 0; + UCSR0B &= ~(1<< UDRIE0); + LED2_OFF(); + } + } \ No newline at end of file -- 2.43.0