# (GNU make, BSD make, SysV make)
-MCU = atmega324p
+MCU = atmega324pa
FORMAT = ihex
TARGET = main
SRC = $(TARGET).c lcdlib/lcd-color-graphic.c lcdlib/font.c \
// MODE "device operating mode"
#define ADS_MODE_S (1 << 8)
// DR "Data rate"
-#define ADS_1600SPS (0b100 << 5)
-#define ADS_128SPS (0b000 << 5)
+#define ADS_860SPS (0b111 << 5)
+#define ADS_128SPS (0b100 << 5)
// PULL_UP_EN "Pull-up enable"
#define ADS_PULLUP_DRDY (1 << 3)
// NOP "No operation"
}
//write character
+ uint8_t cont = 0;
do {
for(i=(row>>hc); i<char_width*font_height; i+=font_height) {
tmp = pgm_read_byte(tableposition+i);
- if(row == char_final_height-1)
+ if(ul && row == char_final_height-1)
tmp |= ul;
if(hc)
tmp = double_bits((row&1),tmp);
if(inv)
tmp = ~tmp;
- LCD_WRITE(tmp);
+ LCD_WRITE(tmp,cont);
+ cont = 1;
if(wc)
- LCD_WRITE(tmp);
+ LCD_WRITE(tmp,cont);
}
if (free_space) {
uint8_t c = inv;
c ^= ul>>1;
}
for(uint8_t x = free_space<<wc; x>0;x--) {
- LCD_WRITE(c);
+ LCD_WRITE(c,cont);
}
}
LCD_MOVE(1,-char_final_width);
+ cont = 0;
} while (++row < char_final_height);
//move cursor to upper right corner of character
* the string from program memory. The position of the string on the display
* is selected by page / col.
*/
-uint16_t lcd_put_string_xy_P(FONT_P font, uint8_t style, PGM_P str,uint8_t page, uint8_t col) {
+uint16_t lcd_put_string_xy_P(FONT_P font, uint8_t style, PGM_P str,uint16_t page, uint16_t col) {
LCD_MOVE_TO(page,col);
return lcd_put_string_P(font,style,str);
}
* the string from main memory. The position of the string on the display
* is selected by page / col.
*/
-uint8_t lcd_put_char_xy(FONT_P font, uint8_t style, char character, uint8_t page, uint8_t col) {
+uint8_t lcd_put_char_xy(FONT_P font, uint8_t style, char character, uint16_t page, uint16_t col) {
LCD_MOVE_TO(page,col);
return lcd_put_char(font,style,character);
}
/******************************************************************************
* Outputs a character on the display, using the global font and style
*/
-uint8_t lcd_putc_xy(char c, uint8_t page, uint8_t col) {
+uint8_t lcd_putc_xy(char c, uint16_t page, uint16_t col) {
return lcd_put_char_xy(global_font_select, global_font_style, c, page, col);
}
* Outputs a string on the display, using the global font and style at the
* given position
*/
-uint16_t lcd_putstr_xy_P(PGM_P str, uint8_t page, uint8_t col) {
+uint16_t lcd_putstr_xy_P(PGM_P str, uint16_t page, uint16_t col) {
return lcd_put_string_xy_P(global_font_select, global_font_style, str, page, col);
}
#define LCD_MOVE(x,y) lcd_move_xy((x),(y)) //relative cursor movement
#define LCD_MOVE_TO(x,y) lcd_moveto_xy((x),(y)) //absolute cursor movement
-#define LCD_WRITE(x) lcd_data((x)) //write data to display
+#define LCD_WRITE(x,c) lcd_write_font_byte(x,c) //write data to display
//Functions to read the current position as provided by the LCD library
#define LCD_CURRENT_COL() lcd_get_position_column()
uint16_t lcd_put_string_length(FONT_P font, uint8_t style, char* str, uint8_t length);
uint16_t lcd_put_string_P (FONT_P font, uint8_t style, PGM_P str);
uint8_t lcd_put_char (FONT_P font, uint8_t style, char c);
-uint16_t lcd_put_string_xy_P (FONT_P font, uint8_t style, PGM_P str, uint8_t page, uint8_t col);
-uint8_t lcd_put_char_xy (FONT_P font, uint8_t style, char character, uint8_t page, uint8_t col);
+uint16_t lcd_put_string_xy_P (FONT_P font, uint8_t style, PGM_P str, uint16_t page, uint16_t col);
+uint8_t lcd_put_char_xy (FONT_P font, uint8_t style, char character, uint16_t page, uint16_t col);
void lcd_set_font (FONT_P font, uint8_t style);
uint8_t lcd_putc (char c);
-uint8_t lcd_putc_xy (char c, uint8_t page, uint8_t col);
+uint8_t lcd_putc_xy (char c, uint16_t page, uint16_t col);
uint16_t lcd_putstr (char* str);
uint16_t lcd_putstr_P (PGM_P str);
-uint16_t lcd_putstr_xy_P (PGM_P str, uint8_t page, uint8_t col);
+uint16_t lcd_putstr_xy_P (PGM_P str, uint16_t page, uint16_t col);
#if INCLUDE_INTEGER_OUTPUT == 1
uint16_t lcd_put_long (int32_t integer);
#include <avr/pgmspace.h>
#include <stdlib.h>
+
/*****************************************************************************
* BEGIN CONFIG BLOCK
*****************************************************************************/
#define LCD_INIT_SPI() init_spi_lcd()
//Define a function that waits until SPI interface is idle
-#define spi_wait_for_idle() while(! (UCSR1A & _BV(UDRE1)));
+#define spi_wait_for_idle() while(!(UCSR1A & _BV(TXC1)));UCSR1A |= _BV(TXC1)
//Define how to write to SPI data register
#define spi_write(i) UDR1 = i
//Control A0 input of LCD
#define LCD_DATA() PORT_DC |= _BV(PIN_DC)
-#define LCD_CMD() PORT_DC &= ~_BV(PIN_DC)
+#define LCD_CMD() PORT_DC &= ~_BV(PIN_DC);
#define LCD_SET_OUTPUT_DC() DDR_DC |= _BV(PIN_DC)
//Control reset input of LCD
#if LCD_USE_CHIPSELECT == 1
#define LCD_SET_OUTPUT_CS() DDR_CS |= _BV(PIN_CS)
#define LCD_SELECT() PORT_CS &= ~_BV(PIN_CS)
- #define LCD_UNSELECT() spi_wait_for_idle(); PORT_CS |= _BV(PIN_CS)
+ #define LCD_UNSELECT() spi_wait_for_idle(); PORT_CS |= _BV(PIN_CS); spi_write(LCD_NOP)
#else
#define LCD_SET_OUTPUT_CS()
- #define LCD_SELECT() spi_wait_for_idle();
+ #define LCD_SELECT() spi_wait_for_idle(); spi_write(LCD_NOP)
#define LCD_UNSELECT()
#endif
volatile uint16_t time;
volatile uint8_t keys_pressed = 0b00000000;
volatile uint8_t next_step = 0;
+volatile uint8_t next_second = 0;
volatile uint8_t measurement_active = 0;
+uint32_t temperature[9];
+
color_t col_background;
color_t col_font;
color_t col_title;
+color_t col_neg;
struct calib_t calib_settings;
* Init USART for LCD
*****************/
void init_spi_lcd(void) {
- UCSR1B = (1 << TXEN1);
- UCSR1C = (1 << UMSEL10) | (0 << UDORD1) | (0 << UCPHA1) | (0 << UCPOL1);
+ UCSR1B = (1 << TXEN1);
+ UCSR1C = (3 << UMSEL10) | (0 << UDORD1) | (0 << UCPHA1) | (0 << UCPOL1);
UBRR1L = 0;
UBRR1H = 0; //full speed
+ UDR1 = LCD_NOP;
}
/******************
}
calib_settings.nominal_offset = eeprom_read(8);
calib_settings.gain_current = eeprom_read(9);
+ calib_settings.period = eeprom_read(10);
}
/******************
* 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_set_color(&col_font,0x1f,0x3f,0x1f);
+ lcd_set_color(&col_title, 0x1f,0x1f,0x05);
+ lcd_set_color(&col_background, 0x00,0x00,0x00);
+ lcd_set_color(&col_neg, 0x1f,0x00,0x00);
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);
+ lcd_set_font(FONT_PROP_16,DOUBLE_SIZE);
+ lcd_putstr_xy_P(PSTR("PT100 Reader"),0,10);
}
* All my measurements...
*****************/
void lcd_update(void) {
+ LED2_ON();
+ lcd_set_font(FONT_DIGITS_24,SPACING);
+ lcd_use_background(col_background);
+ lcd_use_foreground(col_font);
+
+// send_answer_hex('I','I',DDRB);
+
+ for(uint8_t i = 0; i<8; i++){
+ int32_t x = temperature[i];
+ if (x < 0) {lcd_use_foreground(col_neg); x = -x;}
+ else {lcd_use_foreground(col_font);}
+
+ uint16_t posx = (i&1)?170:10;
+ uint16_t posy = i/2*40+60;
+ lcd_moveto_xy(posy,posx);
+
+ uint8_t deg = x / 1000;
+ uint8_t mil = (x % 1000) / 10;
+ if(deg<10) {
+ lcd_set_area_xy(posx,posx+16,posy,posy+32);
+ lcd_move_xy(0,16);
+ }
+ lcd_put_short(deg);
+ lcd_putc('.');
+ if(mil<10) lcd_putc('0');
+ lcd_put_short(mil);
+ }
+ LED2_OFF();
+
}
*****************/
void init(void) {
//CPU Regs
+// CLKPR = 0x80;CLKPR = 0x01; //clkosc/2
+
+//GPIO
+ PORTD = (0xc8); //pull-up for switches
+ PORTA = (0x77); //spare I/O have pull-up
+
+ DDRA = (0x70); //select outputs
+ DDRB = (0xbb); //LED are output
+ DDRC = (0xc0); //outputs for Inhibit signals
+ DDRD = (0x3c); //LCD data lines
+
+ MUX_C_ON();
+ MUX_T_ON();
//Init ADC SPI
- SPCR = (0 << SPIE) | (1 << SPE ) | (0 << DORD) | (1 << MSTR) | (0 << CPOL) | (1 << CPHA) | (0 << SPR0);
- SPSR = (1 << SPI2X); //fcpu/2
- DDRB |= (1 << PB7) | (1 << PB5) | (1 << PB4); //ADC has three control lines
+// DDRB |= (1 << PB7) | (1 << PB5) | (1 << PB4); //ADC has three control lines
+ SPCR0 = (0 << SPIE0) | (1 << SPE0 ) | (0 << DORD0) | (1 << MSTR0) | (0 << CPOL0) | (1 << CPHA0) | (0 << SPR00);
+ SPSR0 = (0 << SPI2X0); //fcpu/2
+
//Init ADC for presence measurement
ADMUX = (3 << REFS0) | (1 << ADLAR) | (3 << MUX0); // internal2.56V ADC3
//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
- PORTA |= (0x07); //spare I/O have pull-up
-
- DDRB |= (0x03); //LED are output
- DDRA |= (0x70); //select outputs
- DDRC |= (0xc0); //outputs for Inhibit signals
+
//Timer0: 2ms interrupts
TCCR0A = (2 << WGM00); //CTC
OCR0A = 249;
TIMSK0 = (1 << OCF0A); //Interrupt on compare match
-//Timer1: 1s ticks to start measurement
+//Timer1: 1s ticks to make LCD output
TCCR1A = 0;
TCCR1B = (1 << WGM12) | ( 4 << CS10); //CTC, fcpu/256
TIMSK1 = (1 << OCIE1A);
OCR1A = 31250;
+
+ LED1_ON();
lcd_init();
+ LED1_OFF();
+ LED2_ON();
lcd_command_1(LCD_MIRROR, LCD_BGR | LCD_FLIP_XY);
lcd_command(LCD_ON);
-
+
+ LED2_OFF();
read_calib();
- lcd_design();
sei();
-}
+ }
* 500 Hz ticks
*********************/
ISR(TIMER0_COMPA_vect) {
- if(++time == 500) {
+ if(++time == calib_settings.period) {
time = 0;
send_information();
- measurement_active = 1;
+ measurement_active = 1;
}
next_step = 1;
}
* Second ticks
*********************/
ISR(TIMER1_COMPA_vect) {
-
+ next_second = 1;
}
int main(void) {
-
- init();
-
- 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<<KEY_1)) {}
- if(key_was_pressed(1<<KEY_2)) {}
-
- };
- return 0;
-}
\ No newline at end of file
+ _delay_ms(100);
+ init();
+ lcd_design();
+ while(1) {
+ while(next_step==0);
+ next_step = 0;
+ if (measurement_active) {do_measurement_step();}
+ if (next_second && !measurement_active) {
+ lcd_update();
+ next_second = 0;
+ }
+ if(key_was_pressed(1<<KEY_1)) {}
+ if(key_was_pressed(1<<KEY_2)) {}
+
+ };
+ return 0;
+ }
#define LED1_ON() PORTB |= (1<< PB1) //while measurement ongoing
#define LED1_OFF() PORTB &= ~(1<< PB1)
+#define LED1_TOGGLE() PINB |= (1<< PB1)
#define LED2_ON() PORTB |= (1<< PB0) //while transmitting data
#define LED2_OFF() PORTB &= ~(1<< PB0)
+#define LED2_TOGGLE() PINB |= (1<< PB0)
#define KEYPORT PORTD
#define MUX_T_OFF() PORTC |= (1<<PC6)
-void eeprom_write(uint8_t addr, uint8_t value);
+void eeprom_write(uint8_t addr, uint16_t value);
uint16_t eeprom_read(uint8_t addr);
void send_answer_hex(uint8_t type, uint8_t chan, uint32_t v);
extern volatile uint16_t time;
extern volatile uint8_t measurement_active;
extern struct calib_t calib_settings;
+extern uint32_t temperature[9];
struct calib_t {
uint16_t offset_res[8]; //precise offset in Milliohm minus nominal value
uint16_t nominal_offset; //approximate offset resistor, in Ohm, 100 as default
uint16_t gain_current; //2^29 / (gain * current[uA]) (about 53700)
+ uint16_t period; //measurement period in timer ticks (2ms)
};
#define CONNECTED_SENSORS 8
-uint8_t measurement_step;
+uint8_t measurement_step = 0;
uint8_t current_channel = 0;
uint8_t num_connected_sensors = 8;
+const uint16_t connect_threshold = 0xd000;
//factors: gain_current has 2^29, ADC has 2^7 steps per mV
//hence shift by 36 necessary, 6 as part of multiplication by 1E6
}
void set_inhibit_signals(int on_off) {
- PORTC = (PORTC & 0x3F) | (on_off << 6);
+// PORTC = (PORTC & 0x3F) | (on_off << 6);
+ if(on_off == 0) {
+ MUX_C_ON();
+ MUX_T_ON();
+ }
+ else {
+ MUX_C_OFF();
+ MUX_T_OFF();
+ }
}
void select_channel(void) {
-char SPI_transceive(unsigned char cData){
- SPDR = cData;
- while (!(SPSR & (1<<SPIF)))
- ;
- return SPDR;
+uint8_t SPI_transceive(uint8_t cData){
+ SPDR0 = cData;
+ LED1_ON();
+ while(! (SPSR0 & _BV(SPIF0)));
+ LED1_OFF();
+ return SPDR0;
}
uint16_t SPI_transceive_16bit(uint16_t data){
- char high, low;
+ uint8_t high, low;
+ ADC_SELECT();
+ _delay_us(1);
high = SPI_transceive(data>>8);
low = SPI_transceive(data&0xFF);
+ ADC_UNSELECT();
return (high << 8) | low;
}
//34 read ADC temperature as 9th channel
//35 send ADC temperature
+ // should be
+ // (5 - 2.2E3 * 410E-6) / 2 = 2.049 V if on
+ // (5 - 2.2E3 * 10E-6) / 2 = 2.489 V if off
+ // -> compare to 2.27 V or (2.27/2.56)*2^16 = 58112
+
void do_measurement_step(void) {
- if(measurement_step < (CONNECTED_SENSORS*4) && (measurement_step & 0x3) == 0x0) {
- LED1_ON();
+ static uint16_t con;
+ static int32_t adc_result = 0;
+ uint16_t conf_register;
+ if( (measurement_step < (CONNECTED_SENSORS*4)) && ((measurement_step & 0x3) == 0x0) ) {
select_channel();
+ adc_result = 0;
}
else if(measurement_step < (CONNECTED_SENSORS*4) && (measurement_step & 0x3) == 0x1) {
+
ADCSRA |= (1<<ADSC); //start ADC conversion
- uint16_t conf_register = (ADS_MODE_S | ADS_GAIN_025V |
- ADS_SConv | ADS_WRITE_CONFIG | ADS_PULLUP_DRDY | ADS_1600SPS);
+ conf_register = (ADS_MODE_S | ADS_GAIN_025V |
+ ADS_SConv | ADS_WRITE_CONFIG | ADS_PULLUP_DRDY | ADS_860SPS);
conf_register |= ADS_MUX_AIN0_AIN3;
+
+
SPI_transceive_16bit(conf_register);
}
else if(measurement_step < (CONNECTED_SENSORS*4) && (measurement_step & 0x3) == 0x2) {
- set_inhibit_signals(1);
- uint16_t x;
// read on / off
- x = ADCL;
- x += (ADCH<<8);
- // should be
- // (5 - 2.2E3 * 410E-6) / 2 = 2.049 V if on
- // (5 - 2.2E3 * 10E-6) / 2 = 2.489 V if off
- // -> compare to 2.27 V or (2.27/2.56)*2^16 = 58112
- if (x < 58112) {
+ con = ADCL;
+ con += (ADCH<<8);
+
+ if (con < connect_threshold) {
+ adc_result = SPI_transceive_16bit(conf_register);
+ }
+ }
+ else if(measurement_step < (CONNECTED_SENSORS*4) && (measurement_step & 0x3) == 0x3) {
+ set_inhibit_signals(1);
+ if (con < connect_threshold) {
// read value
- x = SPI_transceive_16bit(0x0000);
- x = res_to_temp(adc_to_res(x, current_channel));
- send_answer_hex(0, 0, x);
+ adc_result += SPI_transceive_16bit(0x0000);
+ adc_result /= 2;
+// send_answer_hex('C', current_channel+'0', adc_result & 0xffff);
+ int32_t y = res_to_temp(adc_to_res((uint16_t)adc_result, current_channel));
+ temperature[current_channel] = y;
+ send_answer_hex('T', current_channel+'0', y & 0xfffff);
}
else {
num_connected_sensors = 8;
uint32_t nc_msg = 0x100000;
- send_answer_hex(0, 0, nc_msg);
+ temperature[current_channel] = 0;
+ send_answer_hex('T', current_channel+'0', nc_msg);
}
- }
- else if(measurement_step < (CONNECTED_SENSORS*4) && (measurement_step & 0x3) == 0x3) {
current_channel += 1;
}
measurement_step += 1;
- if(measurement_step == 36)
+ if(measurement_step == 36) {
measurement_step = 0;
current_channel = 0;
- LED1_OFF();
measurement_active = 0;
+ }
}
#define TX_BUSY() (txcnt != 0)
#define STARTTX(i) txcnt = (i);UCSR0B |= (1<< UDRIE0)
-#define ISMYADDR() (rxbuf[1] == '0')
+#define ISMYADDR() (rxbuf[2] == '0')
uint8_t rxcnt = 0, txpoint = 0;
volatile uint8_t txcnt = 0;
void forward_msg(uint8_t i) {
- if(rxbuf[0] == 'A') rxbuf[1]++;
- else rxbuf[1]--;
+ if(rxbuf[0] == 'A') rxbuf[2]++;
+ else rxbuf[2]--;
memcpy ((uint8_t*)txbuf,(uint8_t*)rxbuf,i);
STARTTX(i);
}
* UART received a byte
*********************/
ISR(USART0_RX_vect) {
- uint8_t buf = UDR1;
+ uint8_t buf = UDR0;
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);}
+ if(rxbuf[0] == 'A' || rxbuf[2] != '0') {
+ 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));
+ eeprom_write(addr, (((uint16_t)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);
read_calib();
}
}
+ rxcnt = 0;
}
else {
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