0.6.1 Improved display code
[digitaldcpower] / main.c
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);
                        }
                }
        }