Frequency counter using GPS 1PPS signal and temperature controlled 50MHz Base clock. Ported from F411 Frequency Counter.

Dependencies:   QEI DRV8830 PID ADT7410 TextLCD Frq_cuntr_Nucleo-F746ZG RingBuffer

Fork of Frequency_Counter_w_GPS_1PPS by Kenji Arai

Please refer following.
/users/kenjiArai/notebook/frequency-counters/

User_IF/uif.cpp

Committer:
kenjiArai
Date:
2019-12-17
Revision:
14:ba6ea409ab05
Parent:
13:1041596c416c
Child:
15:ae0413277bc6

File content as of revision 14:ba6ea409ab05:

/*
 * mbed Application program / User Interface subroutines
 *
 * Copyright (c) 2016,'19 Kenji Arai / JH1PJL
 *  http://www.page.sannet.ne.jp/kenjia/index.html
 *  http://mbed.org/users/kenjiArai/
 *      Created:    September 28th, 2016
 *      Revised:    December  12th, 2019
 */

#define     USE_COM         // use Communication with PC(UART)

//  Include --------------------------------------------------------------------
#include    "mbed.h"
#include    "rtos.h"
#include    "frq_cuntr_f746.h"
#include    "TextLCD.h"
#include    "QEI.h"
#include    "uif.h"

//  Definition -----------------------------------------------------------------
#define ONLY_VALUE          1       // Uart (output only value)

#ifdef  USE_COM
#define BAUD(x)         pc.baud(x)
#define GETC(x)         pc.getc(x)
#define PUTC(x)         pc.putc(x)
#define PRINTF(...)     pc.printf(__VA_ARGS__)
#define READABLE(x)     pc.readable(x)
#else
#define BAUD(x)         {;}
#define GETC(x)         {;}
#define PUTC(x)         {;}
#define PRINTF(...)     {;}
#define READABLE(x)     {;}
#endif

//  Object ---------------------------------------------------------------------
extern Serial       pc;
extern Ticker       enter_irq;
extern DigitalOut   in_frq_slct;
extern DigitalInOut prescaler10or20;

QEI         rotary(PE_9, PF_13, NC, 24, QEI::X4_ENCODING); //Rotary chB,chA
TextLCD     lcd(PD_3, PC_3, PD_4, PD_5, PD_6, PD_7, TextLCD::LCD20x4);
DigitalOut  led_R_gps1pps(PE_7);
DigitalOut  led_G_temp_ok(PE_8);
DigitalOut  led_B_recipro(PG_9);
DigitalOut  led_W_prescaler(PG_14);
DigitalOut  led_R_rotary(PF_15);
DigitalOut  led_G_rotary(PE_13);
DigitalOut  led_B_rotary(PF_14);
DigitalIn   rotary_sw(PE_11);

//  RAM ------------------------------------------------------------------------
int8_t      function_num;
// working area
char        buf[40];
// write mode control
uint8_t     mode_change_flg = 0;
// Prescaler selct
uint8_t     prescaler_on = 0;
uint8_t     prescaler_div20 = 0;
// Rotary switch
uint32_t    enter = 0;
uint8_t     enter_first_flg = 0;
// Time
time_t      seconds;
time_t      seconds_jst;
// Reciprocal data
extern
uint8_t     recipro_new_data_ready;

//  Function prototypes --------------------------------------------------------
static int8_t rotary_sw_update(void);
static void change_setting(void);
static void uart_output(dispDef *dt);
static void led_update(dispDef *dt);
static void dsp_freq(dispDef *dt);
static void dsp_1pps(dispDef *dt);
static void dsp_detail(dispDef *dt);
static void dsp_simple(dispDef *dt);
static void dsp_recipro(dispDef *dt);
static void dsp_gps_status(dispDef *dt);
static void dsp_current_setting(dispDef *dt);

//  ROM / Constant data --------------------------------------------------------
                            //  12345678901234567890
static const char *const msg_clear = "                    ";
static const char *const msg_msg0  = "Frequency Counter   ";
static const char *const msg_msg1  = " mbed Nucleo F746ZG ";
static const char *const msg_msg2  = "   by JH1PJL K.Arai ";
static const char *const msg_msg3  = "     " __DATE__" UTC";
static const char *const msg_msg4  = "Getting GPS,pls wait";

// function table
void (*functptr[])(dispDef*) = {
         dsp_freq,
         dsp_1pps,
         dsp_detail,
         dsp_simple,
         dsp_recipro,
         dsp_gps_status,
         dsp_current_setting
};

//------------------------------------------------------------------------------
//  Control Program
//------------------------------------------------------------------------------
void dispay_LCD_and_UART(dispDef *dt)
{
    uint8_t  size;

    uart_output(dt);
    display_clear_all();
    led_update(dt);
    if (mode_change_flg == 0){
        led_B_rotary = !led_B_rotary;
        led_R_rotary = 0;
        function_num += rotary_sw_update();
        //size = sizeof(*functptr); // doesn't work
        size = 7;
        if (function_num >= size){
            function_num = 0;
        } else if (function_num < 0){
            function_num = size - 1;
        }
        (*functptr[function_num])(dt);   // pick one function from a table
    } else {
        led_B_rotary = 0;
        led_R_rotary = !led_R_rotary;
        change_setting();
    }
}

void change_setting()
{
    static int8_t  n;
    static int8_t  old_mode_change_flg;
    uint8_t  p;

    lcd.locate(0, 0);
            //  12345678901234567890
    lcd.printf("            1/1  BNC");
    lcd.locate(0, 1);
            //  12345678901234567890
    lcd.printf("            1/10 SMA");
    lcd.locate(0, 2);
            //  12345678901234567890
    lcd.printf("            1/20 SMA");
    lcd.locate(0, 3);
            //  12345678901234567890
    lcd.printf("Select then push SW!");
    n += rotary_sw_update();
    if (n < 0){
        p = n * -1;
    } else {
        p = n;
    }
    p %= 3;
    lcd.locate(0, p);
            //  12345678901234567890
    lcd.printf("--->>>");
    if (old_mode_change_flg != mode_change_flg){
        if (mode_change_flg == 1){
            old_mode_change_flg = mode_change_flg;
        } else {
            select_input_div_1or10or20(p);
            mode_change_flg = 0;
            old_mode_change_flg = 0;
        }
    }
}

// Display LED's
static void led_update(dispDef *dt)
{
    if (dt->ready_1pps == 3) {
        led_R_gps1pps = 1;
    } else {
        led_R_gps1pps = 0;
    }
    if (prescaler_on){
        if (prescaler_div20){
            led_W_prescaler = !led_W_prescaler;
        } else {
            led_W_prescaler = 1;
        }
    } else {
        led_W_prescaler = 0;
    }
    if (dt->recipro_of == 0){
        led_B_recipro = 1;
    } else {
        led_B_recipro = 0;
    }
    if (dt->temp_is_okay == 1){
        led_G_temp_ok = 1;
    } else {
        led_G_temp_ok = 0;
    }
}

// Data output via VCOM line
static void uart_output(dispDef *dt)
{
    static uint32_t n = 0;

    PRINTF("%9.0f,", dt->m_frq);
    PRINTF("%10d,", dt->b_1pps_new);
    // compensated
    PRINTF("%12.3f,", dt->m_frq_comp);
    PRINTF("%13.3f,", dt->b_1pps_lng);
    // 10sec data
    PRINTF("%10.1f,", dt->m_frq_10);
    // 100sec data
    PRINTF("%11.2f,", dt->m_frq_100);
    // 1000sec data
    PRINTF("%12.3f,", dt->m_frq_1000);
    if (recipro_new_data_ready){
        recipro_new_data_ready = 0;
        if (dt->recipro_of){
            PRINTF("over5KHz   ,");
        } else {
            PRINTF("%12.6f,", dt->m_frq_recipro);
        }
    } else {
        PRINTF("measuring   ,");
    }
    if (prescaler_on){
        if (prescaler_div20){
            PRINTF("Div20,");
        } else {
            PRINTF("Div10,");
        }
    } else {
        PRINTF("Div1 ,");
    }           
    PRINTF("%+6.3f,", dt->box_tmp);
    seconds = time(NULL);
    seconds_jst = seconds + 32400;   // +9 hours ->JST
    //                 13:12:11
    strftime(buf, 40, "%H:%M:%S", localtime(&seconds_jst));
    PRINTF("%s,", buf);
    // Number
    PRINTF("%08d\r\n", n++);
}

void select_input_div_1or10or20(uint8_t mode)
{
    if (mode == 2){             // 1/20
        prescaler_on = 1;
        prescaler_div20 = 1;
        in_frq_slct = 0;    // Select SMA input with pre-scaler
        prescaler10or20.input();
    } else if (mode == 1){      // 1/10
        prescaler_on = 1;
        prescaler_div20 = 0;
        in_frq_slct = 0;    // Select SMA input with pre-scaler
        prescaler10or20.output();
        prescaler10or20 = 0;
    } else {
        prescaler_on = 0;
        prescaler_div20 = 0;
        in_frq_slct = 1;    // Select BNC
        //prescaler10or20 = 1;
        prescaler10or20.output();
        prescaler10or20 = 0;
    }
}

// Interrupt handler for Rotary SW Push bottom
void enter_action() {
    if (rotary_sw == 1){
        enter_first_flg = 1;
    } else {
        if (enter_first_flg){
            if (enter++ > 2){
                enter = 0;
                mode_change_flg++;    // action trigger for SW on
                enter_first_flg = 0;
            }
        }
    }
}

// Detect rotary switch rotation
static int8_t rotary_sw_update()
{
    static int8_t position_old;
    int8_t pos, dt;

    pos = rotary.getPulses()/4;
    if (pos != position_old){
        if (pos > position_old){
            if (pos < 0){
                dt = -1;
            } else {
                dt =  1;
            }
        } else {
            if (pos < 0){
                dt =  1;
            } else {
                dt = -1;
            }
        }
    } else {
        dt = 0;
    }
    position_old = pos;
    return dt;      
}

//******************************************************************************
static void dsp_freq(dispDef *dt)
{
    lcd.locate(0, 0);
    if (prescaler_on == 0){
        lcd.printf("Freq = %8.0f Hz", dt->m_frq);
    } else if (prescaler_div20){
        lcd.printf("Freq = %7.4fMHz", dt->m_frq * 20.0f);    // 1/20
    } else {
        lcd.printf("Freq = %8.5fMHz", dt->m_frq * 10.0f);    // 1/10
    }
    lcd.locate(0, 1);
    if (dt->m_frq_10 == 0.0f){
        lcd.printf("10s  =    not yet");
    } else {
        if (prescaler_on == 0){
            lcd.printf("10s  = %9.1f", dt->m_frq_10);
        } else if (prescaler_div20){
            lcd.printf("10s  =  %8.5f", dt->m_frq_10 * 20.0f);    // 1/20
        } else {
            lcd.printf("10s  =  %9.6f", dt->m_frq_10 * 10.0f);    // 1/10
        }
    }
    lcd.locate(0, 2);
    if (dt->m_frq_100 == 0.0f){
        lcd.printf("100s =    not yet");
    } else {
        if (prescaler_on == 0){
            lcd.printf("100s = %10.2f",  dt->m_frq_100);
        } else if (prescaler_div20){
            lcd.printf("100s =  %9.6f",  dt->m_frq_100 * 20.0f);    // 1/20
        } else {
            lcd.printf("100s =  %10.7f", dt->m_frq_100 * 10.0f);    // 1/10
        }
    }
    lcd.locate(0, 3);
    if (dt->m_frq_1000 == 0.0f){
        strftime(buf,40, "%I:%M:%S%p (%m/%d)", localtime(&seconds_jst));
        lcd.printf("%s %d", buf, function_num);
    } else {
        if (prescaler_on == 0){
            lcd.printf("1000s= %11.3f", dt->m_frq_1000);
        } else if (prescaler_div20){
            lcd.printf("1000s=  %10.7f", dt->m_frq_1000 * 20.0f);    // 1/20
        } else {
            lcd.printf("1000s=  %11.8f", dt->m_frq_1000 * 10.0f);    // 1/10
        }
    } 
}

static void dsp_1pps(dispDef *dt)
{
    lcd.locate(0, 0);
    if (dt->m_frq_10 == 0.0f){
        lcd.printf("10s  =    not yet");
    } else {
        if (prescaler_on == 0){
            lcd.printf("10s  = %9.1f", dt->m_frq_10);
        } else if (prescaler_div20){
            lcd.printf("10s  =  %8.5f", dt->m_frq_10 * 20.0f);    // 1/20
        } else {
            lcd.printf("10s  =  %9.6f", dt->m_frq_10 * 10.0f);    // 1/10
        }
    }
    lcd.locate(0, 1);
    lcd.printf("1PPS = %8d Hz", dt->b_1pps_new);
    lcd.locate(0, 2);
    lcd.printf("Oven Temp= %+5.2f%cC", dt->box_tmp, 0xdf);
    lcd.locate(0, 3);
    strftime(buf,40, "%I:%M:%S%p (%m/%d)", localtime(&seconds_jst));
    lcd.printf("%s %d", buf, function_num);
}

static void dsp_detail(dispDef *dt)
{
    lcd.locate(0, 0);
    if (dt->m_frq_100 == 0.0f){
        lcd.printf("100s =    not yet");
    } else {    
        if (prescaler_on == 0){
            lcd.printf("100s = %11.2f",  dt->m_frq_100);
        } else if (prescaler_div20){
            lcd.printf("100s =  %9.6f",  dt->m_frq_100 * 20.0f);    // 1/20
        } else {
            lcd.printf("100s =  %10.7f", dt->m_frq_100 * 10.0f);    // 1/10
        }
    }
    lcd.locate(0, 1);
    if (dt->gps_1pps_ave == 1000){
        lcd.printf("1PPS = %12.3f ", dt->b_1pps_lng);
    } else if (dt->gps_1pps_ave == 100){
        lcd.printf("1PPS = %11.2f ", dt->b_1pps_lng);
    } else if (dt->gps_1pps_ave == 10){
        lcd.printf("1PPS = %10.1f ", dt->b_1pps_lng);
    } else {
        lcd.printf("1PPS = %9.0f " , dt->b_1pps_lng);
    }
    lcd.locate(0, 2);
    lcd.printf("Oven Temp= %+6.3f%cC", dt->box_tmp, 0xdf);
    lcd.locate(0, 3);
    strftime(buf,40, "%I:%M:%S%p (%m/%d)", localtime(&seconds_jst));
    lcd.printf("%s %d", buf, function_num);
}

static void dsp_simple(dispDef *dt)
{
    lcd.locate(0, 0);
    if (prescaler_on == 0){
        lcd.printf("Freq =  %8.0f Hz", dt->m_frq);
    } else if (prescaler_div20){
        lcd.printf("Freq =  %7.4fMHz", dt->m_frq * 20.0f);    // 1/20
    } else {
        lcd.printf("Freq =  %8.5fMHz", dt->m_frq * 10.0f);    // 1/10
    }
    lcd.locate(0, 1);
    lcd.printf("1PPS =  %8d Hz", dt->b_1pps_new);
    lcd.locate(0, 2);
    lcd.printf("Oven Temp= %+3.0f%cC", dt->box_tmp, 0xdf);
    lcd.locate(0, 3);
    strftime(buf,40, "%I:%M:%S%p (%m/%d)", localtime(&seconds_jst));
    lcd.printf("%s %d", buf, function_num);
}

static void dsp_recipro(dispDef *dt)
{
    if ((prescaler_on != 0) || (dt->recipro_of == 1)){
        display_clear_all();
        lcd.locate(0, 0);
        //          12345678901234567890
        lcd.printf(" Reciprocal data is");
        lcd.locate(0, 1);
        lcd.printf("  Not avairable ");
        lcd.locate(0, 3);
        //          12345678901234567890
        lcd.printf("                   %d", function_num);
    } else {
        lcd.locate(0, 0);
        //          12345678901234567890
        lcd.printf("Reciprocal [Hz]     ");
        lcd.locate(0, 1);
        if (dt->recipro_of){
            //          12345678901234567890
            lcd.printf("    5KHz over       ");
        } else {
            lcd.printf(" %11.6f,", dt->m_frq_recipro);
        }
        lcd.locate(0, 2);
        lcd.printf("Oven Temp= %+6.3f%cC", dt->box_tmp, 0xdf);
        lcd.locate(0, 3);
        strftime(buf,40, "%I:%M:%S%p (%m/%d)", localtime(&seconds_jst));
        lcd.printf("%s %d", buf, function_num);
    }
}

static void dsp_current_setting(dispDef *dt)
{
    lcd.locate(0, 0);
            //  12345678901234567890
    lcd.printf("Current setting     ");
    lcd.locate(0, 1);
    if (prescaler_on == 1){
        if (prescaler_div20 == 1){
                    //  12345678901234567890
            lcd.printf(" Prescaler =ON  1/20");
        } else {
                    //  12345678901234567890
            lcd.printf(" Prescaler =ON  1/10");
        }
    } else {
                //  12345678901234567890
        lcd.printf(" None-Prescaler(BNC)");
    }
    lcd.locate(0, 2);
            //  12345678901234567890
    lcd.printf("Change parameter    ");
    lcd.locate(0, 3);
            //  12345678901234567890
    lcd.printf(" -> Push Switch    %d", function_num);
}

static void dsp_gps_status(dispDef *dt)
{
    lcd.locate(0, 0);
    //          12345678901234567890
    lcd.printf("GPS status          ");
    lcd.locate(0, 1);
    //          12345678901234567890
    lcd.printf("  3D or not --> %u  ", dt->ready_1pps);
    lcd.locate(0, 2);
    lcd.printf("Oven Temp= %+6.3f%cC", dt->box_tmp, 0xdf);
    lcd.locate(0, 3);
    strftime(buf,40, "%I:%M:%S%p (%m/%d)", localtime(&seconds_jst));
    lcd.printf("%s %d", buf, function_num);
}

// Clear LCD screen
void display_clear_all(void)
{
    lcd.locate(0, 0);
    lcd.printf(msg_clear);
    lcd.printf(msg_clear);
    lcd.printf(msg_clear);
    lcd.printf(msg_clear);
}

// Openning message on LCD & message via VCOM
void disp_first_msg(void)
{
//    lcd.setCursor(LCDCursol 0);   // Cursol off
    // LCD Initial screen
    lcd.locate(0, 0);
    lcd.printf(msg_msg0);
    lcd.printf(msg_msg1);
    lcd.printf(msg_msg2);
    lcd.printf(msg_msg3);
    // Clear all LED
    led_R_gps1pps = 0;
    led_W_prescaler = 0;
    led_R_rotary = 0;
    led_G_rotary = 0;
    led_B_rotary = 0;
    // VCOM message
    BAUD(9600);
    //PRINTF("\r\nFrequency Counter by JH1PJL created on \r\n");
    PRINTF("\r\nFrequency Counter by JH1PJL created on " __DATE__"\r\n");
    PRINTF("\r\nStarted!\r\n");
    PRINTF("SystemCoreClock = %d Hz\r\n", SystemCoreClock);
    // Rotary switch control
    enter_irq.attach_us(&enter_action, 5000);  // every 5mS
}

// GPS waiting message
void disp_wait_gps(void)
{
    lcd.locate(0, 3);
    lcd.printf(msg_msg4);
}