#include "lcd.h"
#include "dac.h"
#include "kbd.h"
+#include "uart.h"
#include "analog.h"
#include "hardware_settings.h"
-#define SWVERSION "ver: ddcp-0.6.0"
+// change this when you compile:
+#define SWVERSION "ver: ddcp-0.6.1"
//#define DEBUGDISP 1
//debug LED:
#define LEDISOFF PORTD&(1<<PORTD0)
//
// the units are display units and work as follows: 100mA=10 5V=50
-// The function int_to_ascii is used to convert the intenal values
+// The function int_to_dispstr is used to convert the intenal values
// into strings for the display
static int16_t measured_val[2]={0,0};
static int16_t set_val[2];
// the set values but converted to ADC steps
static int16_t set_val_adcUnits[2];
static uint8_t bpress=0;
+#define UARTSTRLEN 8
+static char uartstr[UARTSTRLEN+1];
+static uint8_t uartstrpos=0;
+static uint8_t uart_has_one_line=0;
-void delay_ms(uint8_t ms)
+void delay_ms_uartcheck(uint8_t ms)
// delay for a minimum of <ms>
{
while(ms){
- _delay_ms(0.96);
+ _delay_ms(0.85);
+ if(uart_has_one_line==0 && uart_getchar_noblock(&uartstr[uartstrpos])){
+ uart_sendchar(uartstr[uartstrpos]); // echo back
+ if (uartstr[uartstrpos]=='\n'||uartstr[uartstrpos]=='\r'){
+ uartstr[uartstrpos]='\0';
+ uart_has_one_line=1;
+ uart_sendchar('\n'); // the echo back puts a \r
+ }
+ uartstrpos++;
+ if (uartstrpos>UARTSTRLEN){
+ uart_sendstr_P("\r\nERROR\r\n");
+ uartstrpos=0; // empty buffer
+ uartstr[uartstrpos]='\0'; // just print prompt
+ uart_has_one_line=1;
+ }
+ }
ms--;
}
}
// Convert an integer which is representing a float into a string.
-// decimalpoint_pos sets the decimal point after 2 pos from the right: e.g 74 becomes "0.74"
-// The integer may not be larger than 999.
+// Our display is always 4 digits long (including one
+// decimal point position). decimalpoint_pos defines
+// after how many positions from the right we set the decimal point.
+// The resulting string is fixed width and padded with leading space.
+//
+// decimalpoint_pos=2 sets the decimal point after 2 pos from the right:
+// e.g 74 becomes "0.74"
+// The integer should not be larger than 999.
// The integer must be a positive number.
-// spacepadd can be used to add a leading speace if number is less than 10
-//static void int_to_ascii(uint16_t inum,char *outbuf,int8_t decimalpoint_pos){
-// char chbuf[8];
-// itoa(inum,chbuf,10); // convert integer to string
-static void int_to_ascii(int16_t inum,char *outbuf,int8_t decimalpoint_pos,uint8_t spacepadd){
+// decimalpoint_pos can be 0, 1 or 2
+static void int_to_dispstr(uint16_t inum,char *outbuf,int8_t decimalpoint_pos){
int8_t i,j;
char chbuf[8];
- j=0;
- while(inum>9 && j<7){
- // zero is ascii 48:
- chbuf[j]=(char)48+ inum-((inum/10)*10);
- inum=inum/10;
- j++;
- if(decimalpoint_pos==j){
- chbuf[j]='.';
- j++;
- }
- }
- chbuf[j]=(char)48+inum; // most significant digit
- decimalpoint_pos--;
- while(j<decimalpoint_pos){
- j++;
- chbuf[j]='0';
- }
- if (spacepadd && j > (decimalpoint_pos+2)){
- // no leading space padding needed
- spacepadd=0;
- }
- if(decimalpoint_pos==j){
- j++;
- chbuf[j]='.';
- j++;
- chbuf[j]='0'; // leading zero
- }
- if (spacepadd){
- j++;
- chbuf[j]=' '; // leading space padding: "9.50" becomes " 9.50"
- }
- // now reverse the order
- i=0;
- while(j>=0){
- outbuf[i]=chbuf[j];
+ itoa(inum,chbuf,10); // convert integer to string
+ i=strlen(chbuf);
+ if (i>3) i=3; //overflow protection
+ strcpy(outbuf," 0"); //decimalpoint_pos==0
+ if (decimalpoint_pos==1) strcpy(outbuf," 0.0");
+ if (decimalpoint_pos==2) strcpy(outbuf,"0.00");
+ j=4;
+ while(i){
+ outbuf[j-1]=chbuf[i-1];
+ i--;
j--;
- i++;
+ if (j==4-decimalpoint_pos){
+ // jump over the pre-set dot
+ j--;
+ }
}
- outbuf[i]='\0';
}
// convert voltage values to adc values, disp=10 is 1.0V
eeprom_write_word((uint16_t *)0x02,set_val[0]);
eeprom_write_word((uint16_t *)0x04,set_val[1]);
}else{
- if (bpress> 3){
+ if (bpress> 2){
// display software version after long press
lcd_puts_P(SWVERSION);
lcd_gotoxy(0,1);
lcd_puts_P("already stored");
}
}
- delay_ms(200);
+ delay_ms_uartcheck(200);
}
// check the keyboard
static uint8_t check_buttons(void){
+ char buf[21];
+ if (uart_has_one_line){
+ // if (strncmp("?",uartstr,1)==0){
+ int_to_dispstr(measured_val[1],buf,1);
+ uart_sendstr(buf);
+ uart_sendchar('V');
+ uart_sendchar(' ');
+ uart_sendchar('[');
+ int_to_dispstr(set_val[1],buf,1);
+ uart_sendstr(buf);
+ uart_sendchar(']');
+ uart_sendchar(',');
+ uart_sendchar(' ');
+ int_to_dispstr(measured_val[0],buf,2);
+ uart_sendstr(buf);
+ uart_sendchar('A');
+ uart_sendchar(' ');
+ uart_sendchar('[');
+ int_to_dispstr(set_val[0],buf,2);
+ uart_sendstr(buf);
+ uart_sendchar(']');
+ uart_sendchar(' ');
+ if (is_current_limit()){
+ uart_sendchar('I');
+ }else{
+ uart_sendchar('U');
+ }
+ uart_sendchar('>');
+ // }
+ uart_has_one_line=0;
+ uartstrpos=0;
+ }
if (check_u_button(&(set_val[1]))){
if(set_val[1]>U_MAX){
set_val[1]=U_MAX;
char out_buf[21];
uint8_t i=0;
uint8_t ilimit=0;
- // debug led
- DDRD|= (1<<DDD0); // LED, enable PD0, LED as output
- LEDOFF;
+ // debug led, you can not have an LED if you use the uart
+ //DDRD|= (1<<DDD0); // LED, enable PD0, LED as output
+ //LEDOFF;
init_dac();
lcd_init();
set_val[1]=eeprom_read_word((uint16_t *)0x04);
set_val[0]=eeprom_read_word((uint16_t *)0x02);
}
+ uart_init();
sei();
init_analog();
while (1) {
#ifdef DEBUGDISP
itoa(getanalogresult(1),out_buf,10);
#else
- int_to_ascii(measured_val[1],out_buf,1,1);
+ int_to_dispstr(measured_val[1],out_buf,1);
#endif
lcd_puts(out_buf);
lcd_puts("V [");
#ifdef DEBUGDISP
itoa(set_val_adcUnits[1],out_buf,10);
#else
- int_to_ascii(set_val[1],out_buf,1,1);
+ int_to_dispstr(set_val[1],out_buf,1);
#endif
lcd_puts(out_buf);
lcd_putc(']');
#ifdef DEBUGDISP
itoa(getanalogresult(0),out_buf,10);
#else
- int_to_ascii(measured_val[0],out_buf,2,0);
+ int_to_dispstr(measured_val[0],out_buf,2);
#endif
lcd_puts(out_buf);
lcd_puts("A [");
#ifdef DEBUGDISP
itoa(set_val_adcUnits[0],out_buf,10);
#else
- int_to_ascii(set_val[0],out_buf,2,0);
+ int_to_dispstr(set_val[0],out_buf,2);
#endif
lcd_puts(out_buf);
lcd_putc(']');
// scroll too fast if pressed permanently
if (check_buttons()==0){
// no buttons pressed
- delay_ms(20);
+ delay_ms_uartcheck(20);
bpress=0;
if (check_buttons()==0){
// no buttons pressed
- delay_ms(20);
+ delay_ms_uartcheck(20);
}else{
bpress++;
- delay_ms(180);
+ delay_ms_uartcheck(180);
}
}else{
// button press
if (bpress > 10){
// somebody pressed permanetly the button=>scroll fast
- delay_ms(30);
+ delay_ms_uartcheck(30);
}else{
bpress++;
- delay_ms(180);
+ delay_ms_uartcheck(180);
}
}
}
--- /dev/null
+// vim: set sw=8 ts=8 si et:
+/********************************************
+* UART interface without interrupt
+* Author: Guido Socher
+* Copyright: GPL
+**********************************************/
+#include <avr/interrupt.h>
+#include <string.h>
+#include <avr/io.h>
+#include "uart.h"
+#define F_CPU 8000000UL // 8 MHz
+
+void uart_init(void)
+{
+ unsigned int baud=51; // 9600 baud at 8MHz
+#ifdef VAR_88CHIP
+ UBRR0H=(unsigned char) (baud >>8);
+ UBRR0L=(unsigned char) (baud & 0xFF);
+ // enable tx/rx and no interrupt on tx/rx
+ UCSR0B = (1<<RXEN0) | (1<<TXEN0);
+ // format: asynchronous, 8data, no parity, 1stop bit
+ UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
+#else
+ UBRRH=(unsigned char) (baud >>8);
+ UBRRL=(unsigned char) (baud & 0xFF);
+ // enable tx/rx and no interrupt on tx/rx
+ UCSRB = (1<<RXEN) | (1<<TXEN);
+ // format: asynchronous, 8data, no parity, 1stop bit
+ UCSRC = (1<<URSEL)|(3<<UCSZ0);
+#endif
+}
+
+// send one character to the rs232
+void uart_sendchar(char c)
+{
+#ifdef VAR_88CHIP
+ // wait for empty transmit buffer
+ while (!(UCSR0A & (1<<UDRE0)));
+ UDR0=c;
+#else
+ // wait for empty transmit buffer
+ while (!(UCSRA & (1<<UDRE)));
+ UDR=c;
+#endif
+}
+// send string to the rs232
+void uart_sendstr(char *s)
+{
+ while (*s){
+ uart_sendchar(*s);
+ s++;
+ }
+}
+
+void uart_sendstr_p(const prog_char *progmem_s)
+// print string from program memory on rs232
+{
+ char c;
+ while ((c = pgm_read_byte(progmem_s++))) {
+ uart_sendchar(c);
+ }
+
+}
+
+// get a byte from rs232
+// this function does a blocking read
+char uart_getchar(void)
+{
+#ifdef VAR_88CHIP
+ while(!(UCSR0A & (1<<RXC0)));
+ return(UDR0);
+#else
+ while(!(UCSRA & (1<<RXC)));
+ return(UDR);
+#endif
+}
+
+// get a byte from rs232
+// this function does a non blocking read
+// returns 1 if a character was read
+unsigned char uart_getchar_noblock(char *returnval)
+{
+#ifdef VAR_88CHIP
+ if(UCSR0A & (1<<RXC0)){
+ *returnval=UDR0;
+ return(1);
+ }
+#else
+ if(UCSRA & (1<<RXC)){
+ *returnval=UDR;
+ return(1);
+ }
+#endif
+ return(0);
+}
+
+// read and discard any data in the receive buffer
+void uart_flushRXbuf(void)
+{
+ unsigned char tmp;
+#ifdef VAR_88CHIP
+ while(UCSR0A & (1<<RXC0)){
+ tmp=UDR0;
+ }
+#else
+ while(UCSRA & (1<<RXC)){
+ tmp=UDR;
+ }
+#endif
+}
+