NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Support Forum » Serial ISR Not Working?

September 13, 2012
by Jer
Jer's Avatar
// ZSenSim.c is based on tempsensor.c
// for NerdKits with ATmega328
// mrobbins@mit.edu
// VER: 1.2012.0521
// PATH = c:\WinAVR-20090313\avr\ZSenSim
#define F_CPU 14745600

#include <stdio.h>
#include <math.h>
#include <string.h>
//#include "c:\WinAVR-20090313\avr\include\math.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
#include "../libnerdkits/uart.h"
#include "../libnerdkits/io_328p.h"

char RxBuf[20];
uint8_t FlagSerComndRdy = 0;

//=============================================================================================
//=============================================================================================
ISR(USART_RX_vect)
{

    static uint8_t CharIndex = 0;

    char InpChar;

    // Store local copy of new char from the UART-Rx.
    //InpChar = ReceivedByte;

    InpChar = uart_read();

    //Check if tc == EOL char.
    if((InpChar == 10) || (InpChar == 13))
    {
        CharIndex = 0;

        printf_P(PSTR("%s D\r\n"), RxBuf);

        FlagSerComndRdy = 1;

        //main_state = 4;

    }
    else
    {
        // Build ser-command string.
        RxBuf[CharIndex] = InpChar;

        // INC Char index.
        if(CharIndex < 18)
        {
            ++CharIndex;
            RxBuf[CharIndex] = '\0';

        }
        else
        {
            // RST CharIndex.
            CharIndex = 0 ;

        }
    }

}

//---------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------- 
void set_SPI_mode(uint8_t ModeIndex)
{

    // Initiate the SPI module in master mode, data rate clk/128
    // Bit 7 – SPIE: SPI Interrupt Enable = TRUE
    // Bit 4 – MSTR: Master = TRUE /Slave Select = FALSE
    // Bit[1,0] - SPR1,SPR0
    //               0,0 = clk/4
    //               0,1 = clk/16
    //               1,0 = clk/24
    //           ==> 1,1 = clk/128

    switch(ModeIndex)
    {
        case 0:
            //   SPI MODE: 0, CPOL=0, CPHA=0, Sample (Rising) Setup (Falling).
            SPCR |= (1<<SPE) | (1<<MSTR) | (1<<SPR1) | (1<<SPR0);

            break;

        case 1:
            //   SPI MODE: 1, CPOL=0, CPHA=1, Setup (Rising) Sample (Falling).
            SPCR |= (1<<SPE) | (1<<MSTR) | (1<<CPOL) | (1<<SPR1) | (1<<SPR0);// <= For keypad (74HC165).

            break;

        case 2:
            //   SPI MODE: 2, CPOL=1, CPHA=0, Sample (Falling) Setup (Rising).
            SPCR |= (1<<SPE) | (1<<MSTR) | (1<<CPHA) | (1<<SPR1) | (1<<SPR0);

            break;

        case 3:
            //   SPI MODE: 3, CPOL=1, CPHA=1, Setup (Falling) Sample (Rising).
            SPCR |= (1<<SPE) | (1<<MSTR) | (1<<CPOL) | (1<<CPHA) | (1<<SPR1) | (1<<SPR0);

            break;

        default:
            //   SPI MODE: 1, CPOL=0, CPHA=1, Setup (Rising) Sample (Falling).
            SPCR |= (1<<SPE) | (1<<MSTR) | (1<<CPOL) | (1<<SPR1) | (1<<SPR0);// <= For keypad (74HC165).

            break;
    }

}

//---------------------------------------------------------------------------------------------
void master_SPI_init()
{

    // Set MOSI,SCK,SS as outputs.
    // Pins  17,         19,         16
    DDRB |= (1<<PB3) | (1<<PB5) | (1<<PB2);

    set_SPI_mode(1);

    // Set the SS pins we are using as outputs
    // PINS=>    23,        24,         25,         26,        27,         28         
    DDRC = (1<<PC1) | (1<<PC2) | (1<<PC3) | (1<<PC4) | (1<<PC5);

    DDRB |= (1<<PB1);

    // set the SS pins logic high (slave not active)
    // PINS=>     23,        24,         25,         26,        27,         28  
    PORTC = (1<<PC1) | (1<<PC2) | (1<<PC3) | (1<<PC4) | (1<<PC5);

    PORTB |= (1<<PB1);

    //set up timer, when this fires all the slave panels are updated
    //timer set to clk/1024 - aprox 56Hz 
//  TCCR0B |= (1<<CS02) | (1<<CS00);
//  TIMSK0 |= (1<<TOIE0);
    DDRD |=  0x7E;// Set dir for pin used for the RS-232
    PORTD = 0x3F;// Set dir for pin used for the RS-232

}

//---------------------------------------------------------------------------------------------
uint16_t SPI_MasterReceive() 
{
    // Initz Return value.
    uint16_t data = 0;

    // Pull SS line Low to initiate data transmission. 
    PORTB &= ~(1<<PB2);

    // Delay to alow SS to go low.
    delay_us(50);

    // Dummy write a byte of data to SPDR to startup SCLK. 
    SPDR = 0xFF;

    // Wait for reception to complete, MSB 
    while (!(SPSR & (1<<SPIF)))  
    {
        // do nothing.
    }

    // Record byte, shifted 8 bits to left. 
    data = (SPDR<<8);

    // Dummy write a byte of data to SPDR to startup SCLK. 
    SPDR = 0xFF;

    // Wait for reception to complete, LSB   
    while ( !(SPSR & (1<<SPIF)))   
    {
        // do nothing.
    }

    // Record byte add it to current data value.
    data = data + SPDR;

    // Pull SS high to synchronise Slave 
    PORTB |= (1<<PB2);

    // Delay after making SS High for some time to garranty setup before next SPI I/O.
    delay_us(50);

    // Return Data Register 
    return data;

}

//---------------------------------------------------------------------------------------------
void SPI_Outp16(uint16_t OutWord,uint8_t byte_count)
{

    // Pull SS line Low to initiate data transmission. 
    PORTB &= ~(1<<PB2);

    // Delay to alow SS to go low.
    delay_us(50);

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    if (byte_count == 2 ) 
    {   
        // write the High byte 1st to SPDR to SPI-output.
        SPDR = (OutWord>>8);

        // Wait for reception to complete, MSB 
        while (!(SPSR & (1<<SPIF)))  
        {

        }
    }

    // write the LOW byte 2nd to SPDR to SPI-output.
    SPDR = (OutWord & 255);

    // Wait for reception to complete, LSB   
    while ( !(SPSR & (1<<SPIF)))   
    {

    }

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    // Pull SS high to synchronise Slave 
    PORTB |= (1<<PB2);

    // Delay after making SS High for some time to garranty setup before next SPI I/O.
    delay_us(50);

}

//---------------------------------------------------------------------------------------------
void SET_VDAC(uint8_t Chnl, float Vout, float Vref)
{
    uint16_t DAC_Word = 0;

    if((Chnl>=0) && (Chnl<4))
    {

        // Vref = 0 then set Vref to a default value.
        if(Vref==0)
        {
            Vref = 2.5;// Volts.
        }

        if(Vout<0)
        {
            Vout = 0;
        }
        else
        {

            if(Vout>2.5)
            {
                Vout = 2.5;
            }

        }

        // Chnl = 0 to 3.
        DAC_Word = (Chnl<<14);

        // Calculate the 16bits for the DAC = (ADDRESS + COUNT).
        DAC_Word |= (uint16_t)((Vout/Vref) * 4095);

        // Set SIP mode for the DAC.
        set_SPI_mode(3);

        // 1) Select DAC's SPI-ADDRESS = 2.
        PORTC = (2<<3);

        // Delay after selecting the DAC's SPI address and delay to allow it to settle.
        delay_us(20);

        // SPI-Outp DAC_Word.
        SPI_Outp16(DAC_Word,2);

        delay_us(20);

        // 6) Select DAC's Load Reg ADDRESS = 3.
        PORTC = (3<<3);

        // Delay after deselection of the SPI-ADDRESS.
        delay_us(10);

        // Pull MSTR_SS line Low to initiate data transmission. 
        PORTB &= ~(1<<PB2);

        // Delay after deselection of the SPI-ADDRESS.
        delay_us(10);

        // 1) LATCH DAC's new value. Make DAC_Load HIGH.
        // Pull SS high to synchronise Slave 
        PORTB |= (1<<PB2); 
    }

}

//---------------------------------------------------------------------------------------------
int8_t Inp_Keypad() 
{

    uint16_t cKeyValue = 65535;

    //   SPI MODE: 1, CPOL=0, CPHA=1, Setup (Rising) Sample (Falling).
    set_SPI_mode(1);// <= For keypad (74HC165).

    // Parrallel Load Keypad data.
    // Make 74HC165.PL go Lo then back to High.

    // 1) Select Keypad ADDRESS = 0
    PORTC = 0;

    // 2) Make  KeyPad_LD Low to load key data into 74hc165.
    PORTB &= ~(1<<PB2);

    // 2) Delay, holding KeyPad_LD low.
    delay_us(25);

    // 3) Make  KeyPad_LD High to load key data into 74hc165.
    PORTB |= (1<<PB2);

    // 4) Let KeyPad_LD stay High before Reading SPI.
    delay_us(25);

    // 5) Select Keypad SPI address = 1.
    PORTC = (1<<3);

    // 6) Read in the 16bits of the Keypad SPI.
    cKeyValue = SPI_MasterReceive();

    // Allow SS Address to be deselected.
    delay_us(10);

    //cKeyValue !=cKeyValue;

    //return (65535 - cKeyValue);
    switch(65535 - cKeyValue)
    {
        case 0:
            // No Key.
            return -1;
            break;
        case 1:
            // [*]
            return 10;
            break;
        case 2:
            // [7]
            return 7;
            break;
        case 4:
            // [4]
            return 4;
            break;
        case 8:
            // [1]
            return 1;
            break;
        case 16:
            // [0]
            return 0;
            break;  
        case 32:
            // [8] 
            return 8;
            break;
        case 64:
            // [5] 
            return 5;
            break;
        case 128:
            // [2] 
            return 2;
            break;
        case 256:
            // [#] 
            return 11;
            break;
        case 512:
            // [9] 
            return 9;
            break;
        case 1024:
            // [6] 
            return 6;
            break;
        case 2048:
            // [3] 
            return 3;
            break;
        case 4096:
            // [C] 
            return 12;
            break;
        case 8192:
            // [D] 
            return 13;
            break;
        case 16384:
            // [E] 
            return 14;
            break;
        case 32768:
            // [F] 
            return 15;
            break;
        default:
            // Invalid Key.
            return -1;
            break;
    }

}

//---------------------------------------------------------------------------------------------
void adc_init() 
{
    // set analog to digital converter
    // for external reference (5v), single ended input ADC0
    ADMUX = 0;

    // Set analog to digital converter to 
    // be enabled, with a clock prescale of 1/128
    // so that the ADC clock runs at 115.2kHz.
    ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);

    // fire a conversion just to get the ADC warmed up
    ADCSRA |= (1<<ADSC);
}

//---------------------------------------------------------------------------------------------
uint16_t Inp_ADC() 
{
    // read from ADC, waiting for conversion to finish
    // (assumes someone else asked for a conversion.)
    // wait for it to be cleared
    while(ADCSRA & (1<<ADSC)) 
    {
        // do nothing... just hold your breath.
    }
    // bit is cleared, so we have a result.

    // read from the ADCL/ADCH registers, and combine the result
    // Note: ADCL must be read first (datasheet pp. 259)
    uint16_t result = ADCL;
    uint16_t temp = ADCH;
    result = result + (temp<<8);

    // set ADSC bit to get the *next* conversion started
    ADCSRA |= (1<<ADSC);

    return result;
}

//---------------------------------------------------------------------------------------------
float Calc_VZout(float Read_Sim, float Ik, float Vofs, float Vref_uut, float Zout)
{

    float Isim = 0;
    float Vzsim = 0;
    float temp = 1;
    float temp_read;

    temp_read = (temp - Read_Sim);

    if (temp_read > 0)
    {   
        Isim = log(temp_read) * Ik;

    }
    else
    {
        Isim = 0;
    }

    Vzsim = (Isim * Zout) + Vofs;//added offset 20120910 JBF.

    return (Vref_uut - Vzsim);

}

//---------------------------------------------------------------------------------------------
void lcd_display(uint8_t displayOn, uint8_t cursorShow, uint8_t cursorBlink)
{

    uint8_t LCD_CMD = 8;

    if(cursorBlink>0)
    {
        LCD_CMD += 1;
    }

    if(cursorShow>0)
    {
        LCD_CMD += 2;
    }

    if(displayOn>0)
    {
        LCD_CMD += 4;
    }

    lcd_write_byte(LCD_CMD);

}

//---------------------------------------------------------------------------------------------
int8_t Get_Key_Pressed()
{   
    // NOTE: variable "IsWaitingKeyPress" was a global but now is a local static.
    static int8_t IsWaitingKeyPress = 0;

    int8_t curKey;

    // Get the current key pressed.
    curKey = Inp_Keypad();

    if (IsWaitingKeyPress > 0) 
    {
        if (curKey >= 0)
        {
            // SET PRESSED STATE to = Waiting for button to be Releas.
            IsWaitingKeyPress = 0;

            return curKey;
        }
        else
        {
            return -2;

        }
    }
    else
    {
        // Check if button has been released?
        if (curKey < 0)
        {
            // YES! BUTTON HAS BEEN Released.

            // Set STATE FLAG to = Waitting for Button Press.
            IsWaitingKeyPress = 1;

            // Debounce Delay.
            delay_ms(150);

            return -4;
        }
        else
        {
            return -8;
        }
    }

}

//--------------------------------------------------------------------------------------------- 
void SOutPortA(uint8_t port_val)
{

    // 1) Select SOutPortA SPI-ADDRESS = 2.
    PORTC = (4<<3);

    // 2)  SPI MODE: 1, CPOL=0, CPHA=1, Setup (Rising) Sample (Falling).
    set_SPI_mode(1);// <= For keypad (74HC165) and 74HC595.

    // 3) Write the new value of 'port_val' to the SPortA
    SPI_Outp16( port_val, 1);

}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
int main() 
{

    // Z simulator vars
    float Read_sim_inp = .2090;
    float         Vref = 2.5085;//<= Common value.
    float     Vref_uut = 1.098;
    float        VZout = 0;
    float     Range[3] = {.25,.5,.95};
    float      Zout[3] = {13600,28600,6800};
    //float        Ik[3] = {-0.0002649,0.0002649,-0.0002649};// Zsim
    //float        Ik[3] = {-0.00025543,-0.00005052,-0.000048155};// Zsim
    float        Ik[3] = {-0.00025543,-0.000050,-0.000050};// Zsim
    float        ZVofs[3] = {0,0,0};
    float      Ippm[7] = {0,0,0,0,0,0,0};

    // G simulator vars
    float VGout = 0;
    double IGmax[7];
    double VGm[7];
    double VGb[7];
    uint8_t GRelay[7];

    int8_t       KeyValue = 0;
    int8_t    Press_Count = 0;
    int8_t    Press_Limit = 4;
    int8_t         pos_dp = 0;
    int8_t       dspl_row = 0;
    int8_t       dspl_col = 0;
    int8_t     Edit_State = 0;
    int8_t    UserInpMode = 1;

    uint8_t   Sensor_Type = 0;
    uint8_t   Range_index = 0;
    uint8_t    main_state = 0;
    uint8_t       ZRelays = 0;
    uint8_t       GRelays = 0;
    uint8_t       ManCtrl = 0;

    uint16_t  temp_uint16 = 0;
    uint16_t  last_sample = 0;
    uint16_t   adc_sample = 0;

    long   Read_sim_ppm = 0;
//  double    temp_double = 0;
    long        temp_long = 0;
//  uint32_t   temp32int = 0;

    char tempStr[20];
    char KeyStr[2];

    Read_sim_ppm = (Read_sim_inp * 1000000);

    // Start up the LCD.
    lcd_init();
    FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
    lcd_home();

    // Start up the serial port.
    uart_init();
    FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
    stdin = stdout = &uart_stream;

    // Enable Interupts.
    sei();

    /*
    //=============================================================================================
    void Get_Ser_Command()
    {

        tc = '\0';

        // FlagSerComndRdy = '0' Is waiting for a complete ser-command string.
        // FlagSerComndRdy = '1' Is prossesing RQSTed ser-command string.
        if (FlagSerComndRdy==0) 
        {

            // returns 1 if a character is waiting
            // returns 0 if not
            while ( uart_char_is_waiting() )
            {
                // Read in CHAR.
                tc = uart_read();

                //Check if tc == EOL char.
                if((tc == 10) || (tc == 13))
                {
                    CharIndex = 0;

                    printf_P(PSTR("%s OK\r\n"), RxBuf);

                    FlagSerComndRdy = 1;

                    main_state = 4;

                    break;
                }
                else
                {
                    // Build ser-command string.
                    RxBuf[CharIndex] = tc;

                    // INC Char index.
                    if(CharIndex < 18)
                    {
                        ++CharIndex;
                        RxBuf[CharIndex] = '\0';

                    }
                    else
                    {
                        // RST CharIndex.
                        CharIndex = 0 ;
                        break;
                    }
                }
            }
        }

        //return FlagSerComndRdy;

    }
*/

    //=============================================================================================
    float Set_IG_DAC(long sim_ppm, double Ippm, float Vref_dac)
    {
        uint8_t r = 0;
        double Isim = 0;
        double Vsim = 0;
//      double tempDBL = 0;
        double tempVar = 0;
        uint8_t NewRelay=0;
        //sim_ppm = 7.5;

        Isim = (sim_ppm * Ippm);
        //Isim = (10 * Ippm);
        ZRelays = 0;
        r =  0;

        // float IGmax[6];
        // float VGm[6];
        // float VGb[6];

        for(r=0;r<7; ++r)
        {

            if (Isim < IGmax[r])
            {

                // Calculate Vsim.  
                // Vsim = ((Isim * VGm[r]) + VGb[r]);
                //tempDBL = (Isim * VGm[r] );

                //tempDBL = (Isim * 7.35099E+07 );
                Vsim = ((Isim * VGm[r] ) + VGb[r] );

                if ((Vsim > .001) && (Vsim <= 2.5))
                {

                    // Set relays that need to be selected. 
                    GRelays = GRelay[r];

                    NewRelay = GRelay[r];

                    // Set the Relays.
                    SOutPortA(GRelay[r]);

                    tempVar = Vsim;

                    // Set GDAC.
                    SET_VDAC(1, tempVar ,Vref_dac);

                    break;  
                }
            }

        }

        return tempVar;

    }

    //=============================================================================================

    void UpdateDSPLYRow(uint8_t DSPLY_Index)
    {

        switch (DSPLY_Index)
        {
            case 0: 
                // CLR LINE.            
                                     //00000000001111111111
                                     //01234567890123456789
                lcd_write_string(PSTR("                   "));

                break;

            case 1:
                // TITLE.
                lcd_write_string(PSTR("  Sensor Simulator  "));

                break;

            case 2:
                // Version.
                lcd_write_string(PSTR("Ver: 1.2012.0913h  "));

                break;

            case 3:
                // Author.
                lcd_write_string(PSTR("Author: Jerome Ford "));

                break;

            case 4:
                // Show Selected Sensor Type = 0 'Z'.
                lcd_write_string(PSTR(" Sensor = Z1, Z2    "));

                break;

            case 5:
                // Show Selected Sensor Type = 1 'T2'.
                lcd_write_string(PSTR(" Sensor = T1,T2     "));

                break;

            case 6:

                // DSPL Selected Z-Output Range.
                fprintf_P(&lcd_stream, PSTR("  Range = %4.2f"), (Range[Range_index] * 100));
                lcd_write_string(PSTR("% "));
                fprintf_P(&lcd_stream, PSTR("%u %u"), FlagSerComndRdy,main_state);
                break;

            case 7:
                // Display Z-Sim Reading.
                fprintf_P(&lcd_stream, PSTR(" Read = %5.2f"), Read_sim_inp * 100); 
                lcd_write_string(PSTR("%   "));
                break;

            case 8:
                // VZout.
                fprintf_P(&lcd_stream, PSTR("VZout = %4.3f"), VZout);
                lcd_write_string(PSTR("V   "));
                break;

            case 9:
                // Show 'z' AUX INFO.
                fprintf_P(&lcd_stream, PSTR("ADC=%u"), last_sample);

                fprintf_P(&lcd_stream, PSTR(" Key=%2d"), KeyValue);

                fprintf_P(&lcd_stream, PSTR(" P=%2u"), Press_Count);

                break;

            case 10:
                // Display Z-Sim Reading.
                fprintf_P(&lcd_stream, PSTR(" Read = %5.2f"), Read_sim_inp * 100); 
                lcd_write_string(PSTR("%  *"));
                break;

            case 11:
                // Show Selected Sensor Type = 0 'Manualy Control DAC.1 & GRelay's'.
                lcd_write_string(PSTR(" Sensor = Man-Ctrl. "));

                break;

            case 12:
                // VGout.
                fprintf_P(&lcd_stream, PSTR("VGout = %4.3f"), VGout);
                lcd_write_string(PSTR("V   "));
                break;

            case 13:
                // Relays.
                fprintf_P(&lcd_stream, PSTR("Relay = %03u        "), (ZRelays+GRelays) );
                break;

            case 14:
                // DSPL Selected G-Output Range.
                lcd_write_string(PSTR("  Range = PPM       "));
                break;

            case 15:
                // DSPL Selected G-Output Range.
                lcd_write_string(PSTR("  Range = %         "));
                break;

            case 16:
                // Display G-Sim Reading(ppm).
                fprintf_P(&lcd_stream, PSTR(" Read = %06lu"), (Read_sim_ppm)); 
                lcd_write_string(PSTR("ppm"));
                break;

            case 17:
                // Display G-Sim Reading(ppm).
                fprintf_P(&lcd_stream, PSTR(" Read = %5.2f"), ((float)Read_sim_ppm/10000)); 
                lcd_write_string(PSTR("%     "));
                break;

            case 18:
                // Display G-Sim Reading(ppm).
                lcd_write_string(PSTR("  AMI's             "));
                break;

            case 19:
                // Show Selected Sensor Type = 1 'T2'.
                lcd_write_string(PSTR(" Sensor = P2        "));
                break;

            case 20:
                // Show Selected Sensor Type = 1 'T2'.
                lcd_write_string(PSTR(" Sensor = P3,P4     "));
                break;

            case 21:
                // Show Selected Sensor Type = 1 'T2'.
                lcd_write_string(PSTR(" Sensor = P5        "));
                break;

            case 22:
                // Show Selected Sensor Type = 1 'T2'.
                lcd_write_string(PSTR(" Sensor = H2s-B1     "));
                break;

            case 23:
                // Show Selected Sensor Type = 1 'T2'.
                lcd_write_string(PSTR(" Sensor = H2S-BE    "));
                break;

        }

    }

    void CLR_RxBuffer()
    {
        uint8_t i = 0;

        for(i = 0; i < 19 ; i++)
        {
            RxBuf[i] = '\0';
        }

    }

    //=============================================================================================

    /////////////////////////////////////////////////////////////////////////////////////////////
    // Main Loop. ///////////////////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////////////////////
    while(1) 
    {

        if (FlagSerComndRdy != 0)
        {
            // RST Flag.
            FlagSerComndRdy = 0;

            // Process the serial command RQST.
            main_state = 4;
        }

        switch (main_state)
        {
            case 0:/* INITZ-Hardware. main_state = 0 */

                //Set next State.
                main_state = 1;

                Edit_State = 1;

                // Initz SPI hardware.
                master_SPI_init();

                // Start up the Analog to Digital Converter.
                adc_init();

                Sensor_Type = 0; // Z=0 , T2=1.
                //RE-INITZ Values
                Read_sim_inp = .2090;

                ZRelays = 2;
                GRelays = 0;

                Vref = 2.509;
                Vref_uut = 1.097;// Typical Value 20120409 JBF

                Press_Limit = 4;

                Range[0] = .25;
                Range[1] = .50;
                Range[2] = .95;

                Zout[0] = 13460;//<= Measured values 20120910 jbf
                Zout[1] = 28240;//<= Measured values 20120910 jbf
                Zout[2] =  6740;//<= Measured values 20120910 jbf

                Ik[0] = -.0002553504;
                Ik[1] = -.0000500;
                Ik[2] = -.00004780;

                ZVofs[0] = .0035;// Zero offset mV
                ZVofs[1] = .004;
                ZVofs[2] = .004;

                // Galvanic Sinsor Simulator Vars. Use DAC-B

                Read_sim_ppm = (Read_sim_inp * 1000000);

                Ippm[0] = 2.5359e-9;// T1,T2
                Ippm[1] = 2.5359e-9;// T1,T2
                Ippm[2] = 1.6746e-9;// P2
                Ippm[3] = 1.1962e-9;// P3, p4
                Ippm[4] = 143.54e-12;// P5
                Ippm[5] = 6.136569e-7;// H1 SPAN (699/450) = 1.55333 x 375e-9 = 0.0000005825
                Ippm[6] = 97.5e-9;// H2

                // Ig-Range[0]
                GRelay[0] = 0;
                VGm[0] = 7.350987E+07;
                VGb[0] = -1.843413E-02;
                IGmax[0] = 3.425981E-08;

                // Ig-Range[1]
                GRelay[1] = 4;
                VGm[1] = 7.33418E+06;
                VGb[1] = 7.78107E-03;
                IGmax[1] = 3.39809E-07;

                // Ig-Range[2]
                GRelay[2] = 68;
                VGm[2] = 7.32168E+05;
                VGb[2] = -1.76765E-2;
                IGmax[2] = 3.43866E-06;

                // Ig-Range[3]
                GRelay[3] = 100;
                VGm[3] = 7.379149E+04;
                VGb[3] = -4.075647E-2;
                IGmax[3] = 3.443157E-05;

                // Ig-Range[4]
                GRelay[4] = 108;
                VGm[4] = 7.3564143E+03;
                VGb[4] = -4.04192E-3;
                IGmax[4] = 3.40389e-04;

                // Ig-Range[5]
                GRelay[5] = 116;
                VGm[5] = 8.28444585E+02;
                VGb[5] = 0;
                IGmax[5] = 3.01770E-03;

                // Ig-Range[6]
                GRelay[6] = 124;
                VGm[6] = 7.4093097E+01;
                VGb[6] = 1.35699e-4;
                IGmax[6] = 3.37395e-02;

                //GRelay[0] = 0;
                //VGm[0] = 7.350987E+07;
                //VGb[0] = -1.843413E-02;
                //IGmax[0] = 3.425981E-08;

                //SET DAC-1
                SET_VDAC(1,0,Vref);
                SET_VDAC(2,1.3,Vref);
                SET_VDAC(3,1.5,Vref);

                lcd_display(1,0,0);

                RxBuf[0] = 0;
                RxBuf[1] = 0;
                RxBuf[2] = 0;
                RxBuf[3] = 0;
                RxBuf[4] = 0;
                RxBuf[5] = 0;
                RxBuf[6] = 0;
                RxBuf[7] = 0;
                RxBuf[8] = 0;
                RxBuf[9] = 0;

                RxBuf[10] = 0;
                RxBuf[11] = 0;
                RxBuf[12] = 0;
                RxBuf[13] = 0;
                RxBuf[14] = 0;
                RxBuf[15] = 0;
                RxBuf[16] = 0;
                RxBuf[17] = 0;
                RxBuf[18] = 0;
                RxBuf[19] = 0;

                // Set to next State.
                main_state = 3;//<= Update_DSPL

                /////////////////////////////////////////////////////

                //------------------------------------------------
                // Product Presentation.
                // Top Line
                lcd_home();
                    // Show Company Name.
                    UpdateDSPLYRow(18);

                // 2nd Line: 
                lcd_line_two();
                    // Show Blank Line.
                    UpdateDSPLYRow(0);

                // 3rd Line:  
                lcd_line_three();

                    // Show Product Title.  
                    UpdateDSPLYRow(1);

                // 4th Line: 
                lcd_line_four();
                    // Show Blank Line.
                    UpdateDSPLYRow(0);

                delay_ms(2000);

                // 2nd Line: 
                lcd_line_two(); 
                    // Show Product Title.  
                    UpdateDSPLYRow(1);

                // 3rd Line:  
                lcd_line_three();   
                    // Show Blank Line.
                    UpdateDSPLYRow(0);

                delay_ms(500);

                // 3rd Line:  
                lcd_line_three();
                    // Show Version.
                    UpdateDSPLYRow(2);

                // 4th Line: 
                lcd_line_four();
                    // Show Author.
                    UpdateDSPLYRow(3);

                delay_ms(2000);

                // 4th Line: 
                lcd_line_four();
                    // Show Blank Line.
                    UpdateDSPLYRow(0);

                //-------------------------------------------------

                lcd_display(1,1,1);
                dspl_row = 1;
                dspl_col = 11;

                // Position Cursor to show user where editting point is.
                lcd_goto_position(dspl_row,dspl_col);

                //zRange 25%, Zo = 13.6Kohms, [ K1=Off, K2=On ]
                SOutPortA(ZRelays|GRelays);

                // write message to serial port.
                printf_P(PSTR("Ready %1d \r\n"), 0);

                break;

            case 1:/*  Input User RQSTs via Keypad., main_state = 1*/

                // Get Key Pressed.
                KeyValue = Get_Key_Pressed();

                // Check if RQST for Input Mode Change. 
                if((KeyValue == 10) || (KeyValue == 11)) // key = '#'
                {

                    // UserInpMode = 0 EQLs Set-RANGE.
                    // UserInpMode = 1 EQLs Set-VzSimOut via Keypad.
                    // UserInpMode = 2 EQLs Set-VzSimOut via ADC.
                    // UserInpMode = 3 EQLs Set-SensorType or Manual Mode.

                    if (KeyValue == 10)
                    {
                        // The '*' Key is used for moveing curser up.
                        // MOVE CURSER UP ^.
                        Edit_State -= 1;

                        if(Edit_State < 0)
                        {
                            Edit_State = 3;
                        }

                    }
                    else
                    {
                        // The '#' Key is used for moveing curser down.
                        // MOVE CURSER Down v.
                        Edit_State += 1;

                        if(Edit_State > 3)
                        {
                            Edit_State = 0;
                        }

                    }

                    switch(Edit_State)//(UserInpMode)
                    {
                        case 0:

                            UserInpMode = 0;

                            // Enter new Sensor Type 1,2 or 0.
                            dspl_row = 0;
                            dspl_col = 10;

                            // Position Cursor to show user where editting point is.
                            lcd_goto_position(dspl_row,dspl_col);

                            lcd_display(1,1,1);

                            break;

                        case 1:

                            if(ManCtrl==1)
                            {
                                UserInpMode = 4;

                                // Enter new VZout.
                                dspl_row = 1;
                                dspl_col = 8;

                                // Position Cursor to show user where editting point is.
                                lcd_goto_position(dspl_row,dspl_col);

                                lcd_display(1,1,1);
                            }
                            else
                            {
                                UserInpMode = 1;

                                // Line 1
                                // Enter new range 1,2 or 3.
                                dspl_row = 1;
                                dspl_col = 10;

                                // Position Cursor to show user where editting point is.
                                lcd_goto_position(dspl_row,dspl_col);

                                lcd_display(1,1,1);

                            }

                            break;

                        case 2:

                            if(ManCtrl == 1)
                            {
                                UserInpMode = 5;

                                // Enter new VGout.
                                dspl_row = 2;
                                dspl_col = 8;

                                // Position Cursor to show user where editting point is.
                                lcd_goto_position(dspl_row,dspl_col);

                                lcd_display(1,1,1);

                            }
                            else
                            {
                                if (Sensor_Type == 0)
                                {
                                    UserInpMode = 2;// 'Z' = Sensor
                                }
                                else
                                {
                                    UserInpMode = 7;// 'T2' = Sensor
                                }

                                // Enter new Simulator Value ##.##% via Keypad.
                                dspl_row = 3;
                                dspl_col = 8;

                                // Position Cursor to show user where editting point is.
                                lcd_goto_position(dspl_row,dspl_col);

                                lcd_display(1,1,1);

                            }
                            break;

                        case 3:

                            if(ManCtrl == 1)
                            {
                                UserInpMode = 6;

                                // Enter new Relay Value.
                                dspl_row = 3;
                                dspl_col = 8;

                                // Position Cursor to show user where editting point is.
                                lcd_goto_position(dspl_row,dspl_col);

                                lcd_display(1,1,1);

                            }
                            else
                            {
                                UserInpMode = 3;

                                // Enter new Simulator Value ##.##% Via the ADC Inp-Adj.
                                dspl_row = 3;
                                dspl_col = 18;

                                // Position Cursor to show user where editting point is.
                                lcd_goto_position(dspl_row,dspl_col);

                                lcd_display(1,0,0);
                            }

                            break;
                    }

                    // Set to next State.
                    main_state = 5;//<= Update_DSPL

                }
                else
                {

                    // Preform the selecte User input.
                    switch(UserInpMode)
                    {

                        case 0:

                            // (Sensor-Type) OR (Manual Mode CTRL) ?
                            switch (KeyValue)
                            {
                                case 0:
                                    // Manual CTRL.
                                    ManCtrl = 1;

                                    // Set main_state = Update Display.
                                    main_state = 5;

                                    break;

                                case 1:

                                    ManCtrl = 0;

                                    Sensor_Type = 0;// Z = sensor

                                    // Set main_state = Calculate Vzout.
                                    main_state = 3;

                                    break;

                                case 2:

                                    ManCtrl = 0;

                                    Sensor_Type = 1;// T1,T2 = Sensor

                                    // Set main_state = Calculate VGout.
                                    main_state = 2;

                                    break;

                                case 3:

                                    ManCtrl = 0;

                                    Sensor_Type = 2;// P2 = Sensor

                                    // Set main_state = Calculate VGout.
                                    main_state = 2;

                                    break;

                                case 4:

                                    ManCtrl = 0;

                                    Sensor_Type = 3;// P3,P4 = Sensor

                                    // Set main_state = Calculate VGout.
                                    main_state = 2;

                                    break;

                                case 5:

                                    ManCtrl = 0;

                                    Sensor_Type = 4;// P5 = Sensor

                                    // Set main_state = Calculate VGout.
                                    main_state = 2;

                                    break;

                                case 6:

                                    ManCtrl = 0;

                                    Sensor_Type = 5;// H2S-B1 = Sensor

                                    // Set main_state = Calculate VGout.
                                    main_state = 2;

                                    break;

                                case 7:

                                    ManCtrl = 0;

                                    Sensor_Type = 6;// H2S-BE = Sensor

                                    // Set main_state = Calculate VGout.
                                    main_state = 2;

                                    break;      
                            }

                            // Position Cursor to show user where editting point is.
                            lcd_goto_position(dspl_row,dspl_col);

                            break;

                        case 1:

                            if (Sensor_Type == 0)
                            {
                                // SELECT NEW RANGE[0-2].
                                switch(KeyValue)
                                {
                                    case 1:

                                        // Select the 25% Output Range.
                                        Range_index = 0;

                                        // zRange 25%, Zo = 13.6Kohms, [ K1=Off, K2=On ]
                                        ZRelays = 2;

                                        // Set Z range relays.
                                        SOutPortA(ZRelays | GRelays);

                                        // Set main_state= Calculate Vzout.
                                        main_state = 3;

                                        break;

                                    case 2:

                                        // Select the 50% Output Range.
                                        Range_index = 1;

                                        //zRange 50%, Zo = 28.6Kohms, [ K1=Off, K2=Off ]
                                        ZRelays = 0;

                                        // Set Z range relays.
                                        SOutPortA(ZRelays | GRelays);

                                        // Set main_state= Calculate Vzout.
                                        main_state = 3;

                                        break;

                                    case 3:

                                        // Select the 95% Output Range.
                                        Range_index = 2;

                                        //zRange 95%, Zo = 6.8Kohms, [ K1 = Off, K2 = Off ]

                                        // 
                                        ZRelays = 1;

                                        // Set Z range relays.
                                        SOutPortA(ZRelays | GRelays);

                                        // Set main_state= Calculate Vzout.
                                        main_state = 3;

                                        break;
                                }
                            }
                            else
                            {

                                // SELECT NEW Range_Is_PPM = [0,1]

                                switch(KeyValue)
                                {
                                    case 1:

                                        // Set the Range = Trace 'ppm' .
                                        Range_index = 0;

                                        // Range_Is_PPM = 1;

                                        // Set main_state = Calculate VGout.
                                        main_state = 2;

                                        break;

                                    case 2:

                                        // Set the Range = Percent '%' .
                                        Range_index = 1;

                                        // Range_Is_PPM = 0;

                                        // Set main_state = Calculate VGout.
                                        main_state = 2;
                                        break;

                                }
                            }

                            break;

                        case 2:
                            // User Input Z-Sim Reading Out.
                            // Check if button has been PRESSED?
                            if ((KeyValue >= 0) && (KeyValue < 10))
                            {
                                Press_Limit = 4;

                                // Store the simulated reading value.
                                temp_uint16 = (uint16_t)(Read_sim_inp * 10000);

                                // store it as a string "2090" <= (.2090)
                                sprintf_P(tempStr, PSTR("%04d"), temp_uint16);

                                // Convert and store key pressed as a char['0' to '9'].
                                sprintf_P(KeyStr, PSTR("%1d"), KeyValue);

                                // Place new key char into postion.
                                tempStr[Press_Count] =  KeyStr[0];

                                // Convert and Store newly edited string value as a uint16.
                                sscanf_P(tempStr, PSTR("%04d"), &temp_uint16);

                                // Rescale the new temp value to the Read_sim_inp.
                                Read_sim_inp = ((float)temp_uint16/10000);

                                // INC edititing point. [0 to 3]
                                if (Press_Count<(Press_Limit-1))
                                {
                                    // INC Char index.
                                    Press_Count += 1;
                                }
                                else
                                {
                                    Press_Count = 0;
                                }

                                //Set Cursor Row.
                                dspl_row = 3;

                                // Set Cursor Col.
                                if(Press_Count < 2)
                                {
                                    dspl_col = (8 + Press_Count);
                                }
                                else
                                {
                                    dspl_col = (8 + Press_Count + 1);
                                }

                                // Position Cursor to show user where editting point is.
                                lcd_goto_position(dspl_row,dspl_col);

                                // Set main_state = Calculate Vzout.
                                main_state = 3;
                            }

                            break;

                        case 3:
                            /* Get User's Desired Reading from ADC input. */

                            // Get ADC Data.
                            adc_sample = Inp_ADC()-30;

                            if (last_sample != adc_sample)
                            {
                                // Set main_state = Calculate Vzout.
                                main_state = 3;

                                last_sample = adc_sample;

                                if(last_sample < 0 )
                                {
                                    last_sample = 0;
                                }
                                else if(last_sample > 1024)
                                {
                                    last_sample = 0 ;
                                }

                                // Calculate the desired Simulated Reading.
                                Read_sim_inp = Range[Range_index] * (last_sample/(float)980);

                                //Set Cursor Row.
                                dspl_row = 3;
                                dspl_col = 18;

                                // Position Cursor to show user where editting point is.
                                lcd_goto_position(dspl_row,dspl_col);
                            }

                            break;

                        case 4:
                            // Manualy Enter the VDac.0 for Z-Simulator.
                            // Check if button has been PRESSED?
                            if ((KeyValue >= 0) && (KeyValue < 10))
                            {
                                Press_Limit = 4;

                                // Store the simulated reading value.
                                temp_uint16 = (uint16_t)(VZout * 1000);

                                // store it as a string "2090" <= (.2090)
                                sprintf_P(tempStr, PSTR("%04d"), temp_uint16);

                                // Convert and store key pressed as a char['0' to '9'].
                                sprintf_P(KeyStr, PSTR("%1d"), KeyValue);

                                // Place new key char into postion.
                                tempStr[Press_Count] =  KeyStr[0];

                                // Convert and Store newly edited string value as a uint16.
                                sscanf_P(tempStr, PSTR("%04d"), &temp_uint16);

                                // Rescale the new temp value to the Read_sim_inp.
                                VZout = ((float)temp_uint16/1000);

                                //SET DAC[0] = VZout.
                                SET_VDAC(0,VZout*2,Vref);

                                // INC edititing point. [0 to 3]
                                if (Press_Count<(Press_Limit-1))
                                {
                                    // INC Char index.
                                    Press_Count += 1;
                                }
                                else
                                {
                                    Press_Count = 0;
                                }

                                //Set Cursor Row.
                                dspl_row = 1;

                                // Set Cursor Col.
                                if(Press_Count < 1)
                                {
                                    dspl_col = (8 + Press_Count);
                                }
                                else
                                {
                                    // Skip over '.'
                                    dspl_col = (8 + Press_Count + 1);
                                }

                                // Position Cursor to show user where editting point is.
                                lcd_goto_position(dspl_row,dspl_col);

                                // Set main_state = Calculate Vzout.
                                main_state = 5;

                            }

                            break;

                        case 5:
                            // Manualy Enter the VDac.1 for Galvanic Simulator.
                            // Check if button has been PRESSED?
                            if ((KeyValue >= 0) && (KeyValue < 10))
                            {
                                Press_Limit = 4;

                                // Store the simulated reading value.
                                temp_uint16 = (uint16_t)(VGout * 1000);

                                // store it as a string "2090" <= (.2090)
                                sprintf_P(tempStr, PSTR("%04d"), temp_uint16);

                                // Convert and store key pressed as a char['0' to '9'].
                                sprintf_P(KeyStr, PSTR("%1d"), KeyValue);

                                // Place new key char into postion.
                                tempStr[Press_Count] =  KeyStr[0];

                                // Convert and Store newly edited string value as a uint16.
                                sscanf_P(tempStr, PSTR("%04d"), &temp_uint16);

                                // Rescale the new temp value to the Read_sim_inp.
                                VGout = ((float)temp_uint16/(float)1000);

                                //SET DAC[0] = VZout.
                                SET_VDAC(1,VGout,Vref);

                                // INC edititing point. [0 to 3]
                                if (Press_Count<(Press_Limit-1))
                                {
                                    // INC Char index.
                                    Press_Count += 1;
                                }
                                else
                                {
                                    Press_Count = 0;
                                }

                                //Set Cursor Row.
                                dspl_row = 2;

                                // Set Cursor Col.
                                if(Press_Count < 1)
                                {
                                    dspl_col = (8 + Press_Count);
                                }
                                else
                                {
                                    // Skip over '.'
                                    dspl_col = (8 + Press_Count + 1);
                                }

                                // Position Cursor to show user where editting point is.
                                lcd_goto_position(dspl_row,dspl_col);

                                // Set main_state = Calculate Vzout.
                                main_state = 5;

                            }

                            break;

                        case 6:

                            // Manualy Enter the Relay value.
                            // Check if button has been PRESSED?

                            if ((KeyValue >= 0) && (KeyValue < 10))
                            {
                                Press_Limit = 3;

                                // Store the simulated reading value.
                                temp_uint16 = (uint16_t)(ZRelays | GRelays);

                                // store it as a string "0-255"
                                sprintf_P(tempStr, PSTR("%03d"), temp_uint16);

                                // Convert and store key pressed as a char['0' to '9'].
                                sprintf_P(KeyStr, PSTR("%1d"), KeyValue);

                                // Place new key char into postion.
                                tempStr[Press_Count] =  KeyStr[0];

                                // Convert and Store newly edited string value as a uint16.
                                sscanf_P(tempStr, PSTR("%03d"), &temp_uint16);

                                // Set the new temp value to the Relay vars.
                                ZRelays = (temp_uint16 & 3);
                                GRelays = (temp_uint16 & 252);

                                SOutPortA(ZRelays|GRelays);

                                // INC edititing point. [0 to 3]
                                if (Press_Count<(Press_Limit-1))
                                {
                                    // INC Char index.
                                    Press_Count += 1;
                                }
                                else
                                {
                                    Press_Count = 0;
                                }

                                //Set Cursor Row.
                                dspl_row = 3;

                                // Set Cursor Col.
                                if(Press_Count < 3)
                                {
                                    dspl_col = (8 + Press_Count);
                                }

                                // Position Cursor to show user where editting point is.
                                lcd_goto_position(dspl_row,dspl_col);

                                // Set main_state = Calculate Vzout.
                                main_state = 5;

                            }
                            break;

                        case 7:

                            // User Input G-Sim Reading Out.
                            // Check if button has been PRESSED?
                            if ((KeyValue >= 0) && (KeyValue < 10))
                            {

                                Press_Limit = 6;
                                pos_dp = 7;

                                // Copy the simulated reading value into the working var.
                                temp_long = Read_sim_ppm; //000012.5

                                // Convert it into a string "000007.5" 
                                                         ////209000.0

                                sprintf_P(tempStr, PSTR("%06lu"), temp_long);

                                // Convert and store key pressed as a char['0' to '9'].
                                sprintf_P(KeyStr, PSTR("%1u"), KeyValue);

                                // Place new key char into postion.
                                tempStr[Press_Count] =  KeyStr[0];

                                // Convert and Store newly edited string value as a number.
                                sscanf_P(tempStr, PSTR("%06lu"), &temp_long);

                                // Copy the new temp value to the Read_sim_ppm.
                                Read_sim_ppm = temp_long;

                                // INC edititing point. [0 to n]
                                if (Press_Count <  (Press_Limit-1))
                                {
                                    // INC Char index.
                                    Press_Count += 1;

                                    if (Press_Count == pos_dp)
                                    {
                                        // INC Char index.
                                        Press_Count += 1;

                                    }

                                }
                                else
                                {
                                    Press_Count = 0;

                                }

                                dspl_col = (8 + Press_Count);

                                //Set Cursor Row.
                                dspl_row = 3;

                                // Position Cursor to show user where editting point is.
                                lcd_goto_position(dspl_row,dspl_col);

                                // Set main_state = Calculate VGout.
                                main_state = 2;
                            }

                            break;
                    }

                }

                break;

            case 2: /* Update VgDAC, main_state = 2 */

                // Set to next State.
                main_state = 5;

                //Set_IG_DAC(long sim_ppm, float Ippm, float Vref_dac)
                VGout = Set_IG_DAC( Read_sim_ppm, Ippm[Sensor_Type], Vref);

                break;

            case 3:/* Calculate Vzout. main_state = 3 */

                // Set to next State.
                main_state = 5;

                // Recalculate the simulators VZsensor output.
                VZout = Calc_VZout( Read_sim_inp, Ik[Range_index], ZVofs[Range_index], Vref_uut, Zout[Range_index]);

                //SET DAC[0] = VZout.
                SET_VDAC(0,VZout*2,Vref);

                break;

            case 4:/* Preform Serial Command, main_state = 4 */

                if (sscanf_P(RxBuf, PSTR("SOWA0 %06lu"), &temp_long) > 0)   
                {
                    // "A0" Set new value for the Simulated Reading.

                    // Copy the new temp value to the Read_sim_ppm.
                    //Read_sim_inp = temp_long;
                    Read_sim_ppm = temp_long;

                    Read_sim_inp =((float)temp_long/1000000);

                    if (Sensor_Type == 0)
                    {
                        UpdateDSPLYRow(7);

                        // Recalculate the simulators VZsensor output.
                        VZout = Calc_VZout( Read_sim_inp, Ik[Range_index], ZVofs[Range_index], Vref_uut, Zout[Range_index]);

                        //SET DAC[0] = VZout.
                        SET_VDAC(0,VZout*2,Vref);
                    }
                    else
                    {
                        //Set_IG_DAC(long sim_ppm, float Ippm, float Vref_dac)
                        VGout = Set_IG_DAC( Read_sim_ppm, Ippm[Sensor_Type], Vref);
                    }
                }
                else
                {

                    // Else If: RANGE?
                    if (sscanf_P(RxBuf, PSTR("SOWB0 %06lu"), &temp_long) > 0) 
                    {

                        if(Sensor_Type==0)
                        {
                            // "B0" Set new Simulated Range.
                            switch(temp_long)
                            {
                                case 0:
                                    Range_index = 0;
                                    // Select the 25% Output Range.
                                    Range_index = 0;

                                    // zRange 25%, Zo = 13.6Kohms, [ K1=Off, K2=On ]
                                        ZRelays = 2;

                                    // Set Z range relays.
                                    SOutPortA(ZRelays | GRelays);

                                    break;
                                case 1:
                                    Range_index = 1;

                                    //zRange 50%, Zo = 28.6Kohms, [ K1=Off, K2=Off ]
                                    ZRelays = 0;

                                    // Set Z range relays.
                                    SOutPortA(ZRelays | GRelays);

                                    break;
                                case 2:

                                    Range_index = 2;
                                    //zRange 95%, Zo = 6.8Kohms, [ K1 = Off, K2 = Off ]
                                    ZRelays = 1;

                                    // Set Z range relays.
                                    SOutPortA(ZRelays | GRelays);
                                    break;
                            }
                        }
                        else
                        {
                            // "B0" Set new Simulated Range.
                            switch(temp_long)
                            {
                                case 0:
                                    Range_index = 0;

                                    //Set_IG_DAC(long sim_ppm, float Ippm, float Vref_dac)
                                    VGout = Set_IG_DAC( Read_sim_ppm, Ippm[Sensor_Type], Vref);

                                    break;
                                case 1:
                                    Range_index = 1;

                                    //Set_IG_DAC(long sim_ppm, float Ippm, float Vref_dac)
                                    VGout = Set_IG_DAC( Read_sim_ppm, Ippm[Sensor_Type], Vref);

                                    break;
                            }
                        }
                    }
                    else
                    {
                        // Else-If: Sensor-Type?
                        if (sscanf_P(RxBuf, PSTR("SOWJ0 %06lu"), &temp_long) > 0) 
                        {
                            // "J0" Set new value for the Sensor Type.
                            // 1 = Z1 or Z2 //
                            // 2 = T1 or T2 //
                            // 3 = P2       //
                            // 4 = P3 or P4 //
                            // 5 = P5       //
                            // 6 = H2S-B1   //
                            // 7 = H2S-Be   //

                            switch(temp_long)
                            {
                                case 1:// 1 = Z1 or Z2.
                                    Sensor_Type = 0;

                                    switch(Range_index)
                                    {
                                        case 0:
                                            // Set Z range relays.
                                            ZRelays = 2;
                                            break;
                                        case 1:
                                            // Set Z range relays.
                                            ZRelays = 0;
                                            break;

                                        case 2:
                                            // Set Z range relays.
                                            ZRelays = 1;
                                            break;

                                    }

                                    // Set Z range relays.
                                    SOutPortA(ZRelays | GRelays);

                                    break;
                                case 2:// 2 = T1 or T2.
                                    Sensor_Type = 1;
                                    //Set_IG_DAC(long sim_ppm, float Ippm, float Vref_dac)
                                    VGout = Set_IG_DAC( Read_sim_ppm, Ippm[Sensor_Type], Vref);

                                    break;
                                case 3:// 3 = P2.
                                    Sensor_Type = 2;

                                    //Set_IG_DAC(long sim_ppm, float Ippm, float Vref_dac)
                                    VGout = Set_IG_DAC( Read_sim_ppm, Ippm[Sensor_Type], Vref);

                                    break;
                                case 4:// 4 = P3 or P4.
                                    Sensor_Type = 3;

                                    //Set_IG_DAC(long sim_ppm, float Ippm, float Vref_dac)
                                    VGout = Set_IG_DAC( Read_sim_ppm, Ippm[Sensor_Type], Vref);

                                    break;
                                case 5:// 5 = P5.
                                    Sensor_Type = 4;

                                    //Set_IG_DAC(long sim_ppm, float Ippm, float Vref_dac)
                                    VGout = Set_IG_DAC( Read_sim_ppm, Ippm[Sensor_Type], Vref);

                                    break;
                                case 6:// 6 = H2S-B1.
                                    Sensor_Type = 5;

                                    //Set_IG_DAC(long sim_ppm, float Ippm, float Vref_dac)
                                    VGout = Set_IG_DAC( Read_sim_ppm, Ippm[Sensor_Type], Vref);

                                    break;
                                case 7:// 7 = H2S-Be.
                                    Sensor_Type = 6;

                                    //Set_IG_DAC(long sim_ppm, float Ippm, float Vref_dac)
                                    VGout = Set_IG_DAC( Read_sim_ppm, Ippm[Sensor_Type], Vref);

                                    break;
                            }
                        }
                    }
                }

                // Set to next State.
                main_state = 5;

                break;

            case 5:/* Update Display. */

                // Set Main STATE.
                main_state = 1;

                // Start message to LCD at the top.
                lcd_line_one();

                if (ManCtrl == 1)
                {

                    // Show User in Op-Mode is 'Manual-CTRL' is currently selected.
                    UpdateDSPLYRow(11);

                    // 2nd Line:
                    lcd_line_two();

                    // SHOW VZout.
                    UpdateDSPLYRow(8);

                    // 3rd Line:
                    lcd_line_three();

                    // SHOW VGout.
                    UpdateDSPLYRow(12);

                    // 4th Line: 
                    lcd_line_four();

                    // SHOW Relay Value.
                    UpdateDSPLYRow(13);

                }
                else
                {

                    switch(Sensor_Type)
                    {
                        case 0:
                            // Show 'Z1' sensor type currently selected.
                            UpdateDSPLYRow(4);
                            break;

                        case 1:
                            // Show 'Z2' sensor type currently selected.
                            UpdateDSPLYRow(5);
                            break;

                        case 2:
                            // Show 'Z' sensor type currently selected.
                            UpdateDSPLYRow(19);
                            break;

                        case 3:
                            // Show 'Z' sensor type currently selected.
                            UpdateDSPLYRow(20);
                            break;

                        case 4:
                            // Show 'P5' sensor type currently selected.
                            UpdateDSPLYRow(21);
                            break;

                        case 5:
                            // Show 'H2S-B1' sensor type currently selected.
                            UpdateDSPLYRow(22);
                            break;

                        case 6:
                            // Show 'H2S-BE' sensor type currently selected.
                            UpdateDSPLYRow(23);
                            break;

                    }

                    // 2nd Line:
                    lcd_line_two();

                    if (Sensor_Type == 0)
                    {
                        // DSPL Selected 'Z' Output Range.
                        UpdateDSPLYRow(6);
                    }
                    else
                    {
                        // DSPL Selected 'G' Output Range.
                        if (Range_index == 0)
                        {

                            // 'G' Output Range = 'PPM'
                            UpdateDSPLYRow(14);
                        }
                        else
                        {
                            // 'G' Output Range = '%'
                            UpdateDSPLYRow(15);

                        }

                    }

                    // 3rd Line:
                    lcd_line_three();

                    // Blank Line.
                    UpdateDSPLYRow(0);

                    // 4th Line: 
                    lcd_line_four();
                    if (Sensor_Type == 0)
                    {

                        // DSPL Selected 'Z' Output Value.
                        //if ((dspl_col == 18) && (dspl_row == 3))
                        if (UserInpMode == 3)
                        {
                            //Show Simulated Output.
                            UpdateDSPLYRow(10);

                        }
                        else
                        {
                            //Show Simulated Output.
                            UpdateDSPLYRow(7);
                        }

                    }
                    else
                    {
                        // DSPL Selected 'G' Output Value.
                        if (Range_index == 0)
                        {

                            // 'G' Output Range = 'PPM'
                            UpdateDSPLYRow(16);
                        }
                        else
                        {
                            // 'G' Output Range = '%'
                            UpdateDSPLYRow(17);
                        }
                    }

                }

                // Position Cursor to show user where editting point is.
                lcd_goto_position(dspl_row,dspl_col);

                break;

            default:

                main_state = 0;

                break;

            break;

        }// END switch main_state(main_state)

        //Get_Ser_Command();

    } // END Main Loop.

    return 0;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
September 13, 2012
by Ralphxyz
Ralphxyz's Avatar

So Jer what exactly is your problem.

It helps to know what I am looking for.

If you are having problems compiling it is because of your path:

PATH = c:\WinAVR-20090313\avr\ZSenSim

Do you have the libnerdkits folder in your avr folder?

Anyway let us know what to look for.

Ralph

September 13, 2012
by Jer
Jer's Avatar

Hi Ralphxyz

It dose compile but the ISR does not fire.

This is the location of the libnerdkits folder: c:WinAVR-20090313avrlibnerdkits

1) What should the PATH be?

2) Is the ISR vector correct.

3) Im using the same comm settings (115K,n,8,1 ) Do I need to enable the Interupt flags other than what I currently do on line 650=> sei();

4) Can this be an isue beacuse Im using a ATmega328

5) Note that when I poll the comm port the program work just fine as long as my VB program sends one char at a 5mS interval between chars. But of cource I dont want to do it that way my firmware should be able to RECV a continuose streem so thats why I want the ISR.

Thanks for any help.

Jer Ford

September 13, 2012
by Jer
Jer's Avatar

Can you make a simple program Example using => ISR(USART_RX_vect)

NOTE: If I enable line 35=> InpChar = ReceivedByte;

THEN I GET THIS ERROR:

"make.exe" all make -C ../libnerdkits make[1]: Entering directory C:/WinAVR-20090313/avr/libnerdkits' make[1]: Nothing to be done forall'. make[1]: Leaving directory `C:/WinAVR-20090313/avr/libnerdkits' avr-gcc -g -O0 -Wall -mmcu=atmega328p -Wl,-u,vfprintf -lprintf_flt -Wl,-u,vfscanf -lscanf_flt -o zsensim.o zsensim.c ../libnerdkits/delay.o ../libnerdkits/lcd.o ../libnerdkits/uart.o -lm zsensim.c: In function '__vector_18': zsensim.c:39: error: 'ReceivedByte' undeclared (first use in this function) zsensim.c:39: error: (Each undeclared identifier is reported only once zsensim.c:39: error: for each function it appears in.) make.exe: *** [zsensim.hex] Error 1

Process Exit Code: 2 Time Taken: 00:01

September 13, 2012
by Ralphxyz
Ralphxyz's Avatar

Hi jer, as long as you can compile your path is OK!!

Describe the simple program Example using => ISR(USART_RX_vect) a little more.

Ralph

September 13, 2012
by pcbolt
pcbolt's Avatar

Jer -

You do need to enable the USART interrupt. I just happened to have a simple program example using the ISR(USART_RX_vect). To enable the RX interrupt use...

UCSR0B |= (1<<RXCIE0);
sei();

Here is a snippet of my ISR which reads the UART and stores it in a circular buffer...

ISR(USART_RX_vect){ // this is the symbol from AVR compiler docs (interrupt.h)

//  UDR0 is data register for uart - must read it during interrupt
//  See page 185 of datasheet for chip
//  Simply read uart rx reg and copy to buffer, update pointer

rx_buf[rx_in_idx] = UDR0;
rx_in_idx++;
if (rx_in_idx >= MAX_RX)
    rx_in_idx = 0;
return;
}

I do most of the processing in the main portion of the program. I have a second buffer index variable "rx_out_idx" (also global) and when rx_out_idx != rx_in_idx, I know I have a new character to process.

September 14, 2012
by Jer
Jer's Avatar

The ISR() still is not getting fired. Thanks for your help. but I think that the ISR vector just does not work for the Atmega328p.

Jer Ford

September 14, 2012
by Jer
Jer's Avatar

Ralph

Do I have the ISR in the write palce in the code?

I have also enabled the Serial's enterupt not shown in this version of the code: UCSR0B |= (1<<RXCIE0); sei(); This has not yet fixed the problem.

Do you have any other suggestions?

September 14, 2012
by esoderberg
esoderberg's Avatar

Jer,

The ISR vector does work on the 328. I have working code on a 328p that is similar to that posted by PCBolt.

I'm not sure why inside your ISR(USART_RX_vect) you call the "uart_read();" function. This function checks to see if data is available before returning a value, but because you're in the ISR you already know data is waiting. Instead you might try:

InpChar = UDR0;

Don't know if this is a fix for your problem but it's a little simpler.

Eric

September 17, 2012
by Jer
Jer's Avatar

Hi Eric

I found that problem and another:
UCSR0B = (1<<RXCIE0); This disabled both the Trans/Recv lines.

Now its working!

THANKS FOR YOU HELP => Ralph & Eric!

Jer

Post a Reply

Please log in to post a reply.

Did you know that you can aim and fire a servo-controlled water gun from your computer? Learn more...