0.6.1 Improved display code
authorGuido Socher <guidosocher@fastmail.fm>
Sat, 5 Jun 2010 22:00:00 +0000 (00:00 +0200)
committerDobrica Pavlinusic <dpavlin@rot13.org>
Sun, 23 Feb 2014 21:33:02 +0000 (22:33 +0100)
Makefile
README.htm
main.c
run-picocom.sh [new file with mode: 0755]
uart.c [new file with mode: 0644]
uart.h [new file with mode: 0644]

index 744b22a..0c37a99 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -58,9 +58,9 @@ main.hex: main.elf
        @echo " "
        @echo "Expl.: data=initialized data, bss=uninitialized data, text=code"
        @echo " "
-main.elf: main.o dac.o lcd.o analog.o kbd.o
-       $(CC) $(CFLAGS) -o main.elf -Wl,-Map,main.map main.o dac.o lcd.o analog.o kbd.o
-main.o: main.c dac.h kbd.h lcd.h lcd_hw.h analog.h hardware_settings.h
+main.elf: main.o dac.o lcd.o analog.o kbd.o uart.o
+       $(CC) $(CFLAGS) -o main.elf -Wl,-Map,main.map main.o dac.o lcd.o analog.o kbd.o uart.o
+main.o: main.c dac.h kbd.h lcd.h lcd_hw.h analog.h hardware_settings.h uart.h
        $(CC) $(CFLAGS) -Os -c main.c 
 #-------------------
 test_lcd.hex: test_lcd.elf 
@@ -89,6 +89,9 @@ dac.o : dac.c dac.h
 kbd.o : kbd.c kbd.h 
        $(CC) $(CFLAGS) -Os -c kbd.c
 #-------------------
+uart.o : uart.c uart.h 
+       $(CC) $(CFLAGS) -Os -c uart.c
+#-------------------
 load: main.hex
        $(LOADCMD) $(LOADARG)main.hex
 #
index d0b5187..40a985b 100644 (file)
@@ -130,7 +130,12 @@ Homepage: http://www.tuxgraphics.org/electronics/
 Change history:
 digitaldcpower-0.6.0 -- 2010-05-22 first version of the new power V3.
                         This version is made for a new type of hardware
-                       and will not run on any previous hardware version.
+                        and will not run on any previous hardware version.
 
+digitaldcpower-0.6.1 -- 2010-06-06 Number conversion to display string
+                        improved.
+                     -- Basic uart interface prompt, no remote control yet
+
+                        
 -------------------------------------------------------------------
 </pre>
diff --git a/main.c b/main.c
index 24cb433..1f05d91 100644 (file)
--- a/main.c
+++ b/main.c
 #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
@@ -160,7 +161,7 @@ static void store_permanent(void){
                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);
@@ -169,11 +170,43 @@ static void store_permanent(void){
                        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;
@@ -198,9 +231,9 @@ int main(void)
        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();
@@ -211,6 +244,7 @@ int main(void)
                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) {
@@ -239,14 +273,14 @@ int main(void)
 #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(']');
@@ -262,14 +296,14 @@ int main(void)
 #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(']');
@@ -284,23 +318,23 @@ int main(void)
                // 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);
                        }
                }
        }
diff --git a/run-picocom.sh b/run-picocom.sh
new file mode 100755 (executable)
index 0000000..5128c48
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/sh -x
+echo "End picocom with C-A C-X"
+ftdidev=`grep FTDI /proc/bus/usb/devices | wc -l`
+if [ "$ftdidev" = "2" ]; then
+       picocom -l -b 9600 /dev/ttyUSB1
+else
+       picocom -l -b 9600 /dev/ttyUSB0
+fi
diff --git a/uart.c b/uart.c
new file mode 100644 (file)
index 0000000..72cc33f
--- /dev/null
+++ b/uart.c
@@ -0,0 +1,111 @@
+// 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
+}
+
diff --git a/uart.h b/uart.h
new file mode 100644 (file)
index 0000000..bd69475
--- /dev/null
+++ b/uart.h
@@ -0,0 +1,26 @@
+/* vim: set sw=8 ts=8 si et: */
+/*************************************************************************
+ Title:   C include file for uart
+ Target:    atmega8
+***************************************************************************/
+#ifndef UART_H
+#define UART_H
+#include <avr/pgmspace.h>
+
+extern void uart_init(void);
+extern void uart_sendchar(char c);
+extern void uart_sendstr(char *s);
+extern void uart_sendstr_p(const prog_char *progmem_s);
+extern char uart_getchar(void);
+extern unsigned char uart_getchar_noblock(char *returnval);
+extern void uart_flushRXbuf(void);
+
+/*
+** macros for automatically storing string constant in program memory
+*/
+#ifndef P
+#define P(s) ({static const char c[] __attribute__ ((progmem)) = s;c;})
+#endif
+#define uart_sendstr_P(__s)         uart_sendstr_p(P(__s))
+
+#endif /* UART_H */