Frequency Counter. User interface are used DISCO-F746NG GUI with touch panel.

Dependencies:   BSP_DISCO_F746NG F746_GUI LCD_DISCO_F746NG RingBuffer TS_DISCO_F746NG fc_GPS1PPS_f746_f4xx mbed

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

main.cpp

Committer:
kenjiArai
Date:
2016-11-19
Revision:
0:52c5dc2b2b68

File content as of revision 0:52c5dc2b2b68:

/*
 * mbed Application program / Frequency Counter using GPS 1PPS gate puls
 *      Only for ST DISCO-F746NG
 *      Worked on a dedicated Grafic LCD Module
 *
 * Copyright (c) 2014,'15,'16 Kenji Arai / JH1PJL
 *  http://www.page.sannet.ne.jp/kenjia/index.html
 *  http://mbed.org/users/kenjiArai/
 *      Created:    October   18th, 2014
 *      Revised:    January    2nd, 2015
 *      Re-started: June      25th, 2016    ported from F411 to F746
 *      Re-started: Nobember  13th, 2016    Only for DISCO-F746NG LCD
 *      Revised:    Nobember  19th, 2016
 *
 * Base program: FreqCntr_GPS1PPS_F746F4xx_w_recipro
 * https://developer.mbed.org/users/kenjiArai
 *                           /code/FreqCntr_GPS1PPS_F746F4xx_w_recipro/
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*
    REFRENCE: see the source code in this file bottom area
    2016/11/12, Copyright (c) 2016 MIKAMI, Naoki    
    https://developer.mbed.org/users/MikamiUitOpen/code/F746_GUI_Demo/
    Thanks Mikammi-san!
 */

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

//  Include --------------------------------------------------------------------
#include    "mbed.h"
#include    "F746_GUI.hpp"
#include    "GPSrcvr.h"
#include    "fc_GPS1PPS.h"

//  Definition -----------------------------------------------------------------
#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

enum input_select {
         BNC_NORMAL = 1,
         RECIPRO_AC,
         RECIPRO_DC,
         SMA_10,
         SMA_20
};

using namespace Frequency_counter;

//  Object ---------------------------------------------------------------------
DigitalOut  input_frq_select(PF_9);
DigitalInOut  prescaler10or20(PB_15);
DigitalOut  recipro_select(PA_8);
DigitalOut  led1(LED1);
Serial      pc(USBTX, USBRX);
Timer       tmr;

//**** Req. Counter
FRQ_CUNTR   fc;
//**** GUI
LCD_DISCO_F746NG lcd_;

//  RAM ------------------------------------------------------------------------
// Freq.
double      new_frequency;
double      f_10sec;
double      f_100sec;
double      f_1000sec;
double      freq_recipro;
// Operation mode
uint8_t     input_mode;

//  ROM / Constant data --------------------------------------------------------
//                               12345678901234567890
static char *const msg_msg0   = "Frequency Counter by JH1PJL K.Arai";
static char *const msg_msg1   = "on DISCO-F746NG System";
static char *const msg_msg2   = "    "__DATE__" ";
static char *const msg_mode1  = "  BNC none-prescaler              ";
static char *const msg_mode2  = "  BNC recipro(BNC none-prescaler) ";
static char *const msg_mode3  = "  BNC recipro(dedicated BNC input)";
static char *const msg_mode4  = "  SMA prescaler 1/10              ";
static char *const msg_mode5  = "  SMA prescaler 1/20              ";

char *const open_msg[] = {
    "(1) BNC(AC) div = 1/1      10Hz to 100MHz",
    "(2) BNC(AC)(same as above) Reciprocal mode less than 5KHz",   
    "(3) BNC(DC) (another BNC)  Reciprocal mode less than 5KHz",
    "(4) SMA div = 1/10         up to 1GHz",
    "(5) SMA(same as above) div = 1/20      up to 1.5GHz"
};

char *const select_msg[] = {
    "(1) BNC(AC) div = 1/1 ",
    "(2) BNC(AC) Reciprocal",   
    "(3) BNC(DC) Reciprocal",
    "(4) SMA     div = 1/10",
    "(5) SMA     div = 1/20"
};

//  Function prototypes --------------------------------------------------------
void gps_data_rcv(void);
void freq_measurement(uint8_t mode);
void recipro(uint8_t mode);
void opening(void);
void show_time(void);
uint8_t mode_slect(void);

//------------------------------------------------------------------------------
//  Control Program
//------------------------------------------------------------------------------
void freq_measurement(uint8_t mode)
{
    uint16_t    n = 0;
    char        buf[48];
    double      scale;

    Button button(400, 3, 70, 40, "MODE", Font16);
    Label obj20(180, 5, "Frequency Counter",
            Label::CENTER, Font24, LCD_COLOR_GREEN, LCD_COLOR_BLACK);
    if (mode == SMA_20){
        Label obj21(200, 30, "Input=SMA, Division=1/20",
                Label::CENTER, Font16, LCD_COLOR_WHITE, LCD_COLOR_BLACK);
        scale = 20.0f;
    } else if(mode == SMA_10){
        Label obj21(200, 30, "Input=SMA, Division=1/10",
                Label::CENTER, Font16, LCD_COLOR_WHITE, LCD_COLOR_BLACK);
        scale = 10.0f;
    } else {
        Label obj21(200, 30, "Input=BNC(AC), Division=1/1",
                Label::CENTER, Font16, LCD_COLOR_WHITE, LCD_COLOR_BLACK);
        scale = 1.0f;
    }
    while(true){
        tmr.reset();
        tmr.start();
        if (fc.status_freq_update() != 0) {
            new_frequency = fc.read_freq_data() * scale;
            f_10sec   = fc.read_freq_w_gate_time(10) * scale;
            f_100sec  = fc.read_freq_w_gate_time(100) * scale;
            f_1000sec = fc.read_freq_w_gate_time(1000) * scale;
            PRINTF("%8d, Freq: %9.0f,", ++n, new_frequency);
            PRINTF(" F10s: %10.1f, F100s: %11.2f,", f_10sec, f_100sec);
            PRINTF(" F1000s: %12.3f,", f_1000sec);
            sprintf(buf, "Freq: %11.0f    [Hz]", new_frequency);
            Label obj22(40, 60, buf, Label::LEFT, Font24,
                        LCD_COLOR_GREEN, LCD_COLOR_BLACK);
            sprintf(buf, "F10S:  %12.1f  [Hz]", f_10sec);
            Label obj23(40, 90, buf, Label::LEFT, Font24,
                        LCD_COLOR_WHITE, LCD_COLOR_BLACK);
            sprintf(buf, "F100:  %13.2f [Hz]", f_100sec);
            Label obj24(40, 120, buf, Label::LEFT, Font24,
                        LCD_COLOR_WHITE, LCD_COLOR_BLACK);
        } else {
            PRINTF("%8d, No data,,,,", ++n);
            Label obj25(40, 60, "Data is NOT available!", Label::LEFT, Font24,
                        LCD_COLOR_GREEN, LCD_COLOR_BLACK);
            sprintf(buf, "                          ");
            Label obj26(40, 80, buf, Label::LEFT, Font24,
                        LCD_COLOR_WHITE, LCD_COLOR_BLACK);
            Label obj27(40, 100, buf, Label::LEFT, Font24,
                        LCD_COLOR_MAGENTA, LCD_COLOR_BLACK);
        }
        if (mode == SMA_20){
            PRINTF(" Div: 1/20,");
        } else if(mode == SMA_10){
            PRINTF(" Div: 1/10,");
        } else {
            PRINTF(" Div: 1/1 ,");
        }             
        show_time();
        while (1000 > tmr.read_ms()){   // 1 second interval
            if (button.Touched()){  // if user touched "MODE" panel then return
                return;
            }
            wait_ms(1);
        }
    }
}

void recipro(uint8_t mode)
{
    uint16_t    n = 0;
    char        buf[48];
    double      freq_recipro;
    uint32_t    interval_recipro;
    uint32_t    base_clk;
    int32_t     run2stop;

    Button button(400, 3, 70, 40, "MODE", Font16);
    Label obj30(180, 5, "Frequency Counter",
            Label::CENTER, Font24, LCD_COLOR_GREEN, LCD_COLOR_BLACK);
    if (mode == RECIPRO_AC){
        Label obj31(200, 30, "Input=BNC(AC) Reciprocal Mode",
                Label::CENTER, Font16, LCD_COLOR_WHITE, LCD_COLOR_BLACK);
    } else if (mode == RECIPRO_DC){
        Label obj31(200, 30, "Input=BNC(DC) Reciprocal Mode",
                Label::CENTER, Font16, LCD_COLOR_WHITE, LCD_COLOR_BLACK);
    }
    while(true){
        tmr.reset();
        tmr.start();
        fc.recipro_start_measure();
        PRINTF("Start measurement\r");
        while (fc.recipro_check_trigger() == 0){
            run2stop = tmr.read_ms();
            if (run2stop >= 100000){    // 100sec 0.001Hz
                break;
            }
            if (button.Touched()){  // if user touched "MODE" panel then return
                return;
            }
        }
        if (button.Touched()){  // if user touched "MODE" panel then return
            return;
        }
        if (run2stop >= 1000000){   // 100sec 0.001Hz
            //freq_recipro = 0;
        } else {
            interval_recipro = fc.recipro_read_data();
            base_clk = fc.recipro_base_clk_data(1);
            if (interval_recipro >= 9000){// Measure less than 10KHz frequency
                freq_recipro = (double)base_clk / (double)interval_recipro;
            } else {
                //freq_recipro = 0;
            }
        }
        PRINTF("%8d, Freq: %11.5f [Hz] , ", n++, freq_recipro);
        PRINTF("Raw:  %11u [cnt] , ", interval_recipro);
        PRINTF("Base: %11u [Hz], ", base_clk);
        sprintf(buf, "Freq:%11.5f [Hz]", freq_recipro);
        Label obj32(40, 60, buf, Label::LEFT, Font24,
                    LCD_COLOR_GREEN, LCD_COLOR_BLACK);
        sprintf(buf, "Raw: %11u [Counts]", interval_recipro);
        Label obj33(40, 90, buf, Label::LEFT, Font24,
                    LCD_COLOR_WHITE, LCD_COLOR_BLACK);
        sprintf(buf, "Base:%11u (Sys Clk)", base_clk);
        Label obj34(40, 120, buf, Label::LEFT, Font24,
                    LCD_COLOR_MAGENTA, LCD_COLOR_BLACK);
        show_time();
        run2stop = tmr.read_ms();
        if (run2stop < 1000){ 
            while (tmr.read_ms() < 1000){   // 1 second interval
                if (button.Touched()){
                    return;
                }
                wait_ms(1);
            }
        }
    }
}

void show_time(void)
{
    char        buf[48];
    time_t      seconds;

    seconds = time(NULL) + 32400;   // Adjust UTC to JST
    strftime(buf, 40,
                " %I:%M:%S %p JST %y/%m/%d", localtime(&seconds));
    PRINTF("%s\r\n", buf);
    Label obj0(40, 240, buf, Label::LEFT, Font24,
                LCD_COLOR_ORANGE, LCD_COLOR_BLACK);
}

int main()
{
    // Initial input mode
    input_mode = BNC_NORMAL;
    input_frq_select = 1;
    prescaler10or20.output();
    prescaler10or20 = 0;
    recipro_select = 0;
    while(true){
        lcd_.Clear(LCD_COLOR_BLACK);
        // openning message
        opening();
        PRINTF("\r\n%s%s\r\n", msg_msg0, msg_msg2);
        PRINTF("%s\r\n", msg_msg1);
        PRINTF("Wait GPS 1PPS signal\r\n");
        // GPS (not return until 3D condition)
        gps_data_rcv();
        lcd_.Clear(LCD_COLOR_BLACK);
        input_mode = mode_slect();
        lcd_.Clear(LCD_COLOR_BLACK);
        PRINTF("\r\nInput mode # is %u\r\n", input_mode);
        PRINTF("If you want to change the input signal,");
        PRINTF(" please restart the system (Enter Alt+B from your PC)\r\n");
        PRINTF("\r\nStart measuring\r\nMeasureing mode = ");
        switch(input_mode){
            case RECIPRO_AC:
                PRINTF("%s\r\n", msg_mode2);
                input_frq_select = 1;
                prescaler10or20.output();
                prescaler10or20 = 0;
                recipro_select = 0;
                recipro(input_mode);
                break;
            case RECIPRO_DC:
                PRINTF("%s\r\n", msg_mode3);
                input_frq_select = 1;
                prescaler10or20.output();
                prescaler10or20 = 0;
                recipro_select = 1;
                recipro(input_mode);
                break;
            case SMA_10:
                PRINTF("%s\r\n", msg_mode4);
                input_frq_select = 0;
                prescaler10or20.output();
                prescaler10or20 = 0;
                recipro_select = 0;
                freq_measurement(input_mode);
                break;
            case SMA_20:
                PRINTF("%s\r\n", msg_mode5);
                input_frq_select = 0;
                prescaler10or20.input();
                recipro_select = 0;
                freq_measurement(input_mode);
                break;
            case BNC_NORMAL:
            default:
                input_mode = BNC_NORMAL;
                PRINTF("%s\r\n", msg_mode1);
                input_frq_select = 1;
                prescaler10or20.output();
                prescaler10or20 = 0;
                recipro_select = 0;
                freq_measurement(input_mode);
                break;
        }
    }
}

void opening()
{
    Label obj10(240, 2, "Frequency Counter using GPS 1PPS",
                Label::CENTER, Font16);
    Label obj11(240, 20, " created on Nov. 2016 by JH1PJL/Kenji Arai",
                Label::CENTER);
    Label obj12(240, 100, " Please wait to receive",
                Label::CENTER, Font24, LCD_COLOR_LIGHTYELLOW);
    Label obj13(240, 120, "      GPS signal!!     ",
                Label::CENTER, Font24, LCD_COLOR_LIGHTYELLOW);
}

uint8_t mode_slect()
{
    Label obj10(240, 2, "Set ""Operationg Mode""",
                Label::CENTER, Font24, LCD_COLOR_LIGHTGREEN);
    Label obj11(40, 30, open_msg[0], Label::LEFT);
    Label obj12(40, 42, open_msg[1], Label::LEFT);
    Label obj13(40, 54, open_msg[2], Label::LEFT);
    Label obj14(40, 66, open_msg[3], Label::LEFT);
    Label obj15(40, 78, open_msg[4], Label::LEFT);
    const int NUMBER_BUTTONS = 5;
    const string STR1[NUMBER_BUTTONS] =
            {"1) Nor(AC)", "2) Rec(AC)", "3) Rec(DC)", "4) 1/10","5) 1/20"};
    ButtonGroup bGroup1(18, 120, 85, 40,  NUMBER_BUTTONS, STR1, 5, 5, 5, 5,
                Font12, LCD_COLOR_WHITE, 0xFF003538, 0xFFB70068, 0xFFFF7FFF);
    NumericLabel<int> bTouch(50, 240, "",
                Label::LEFT, Font24, LCD_COLOR_ORANGE);
    Button button1(300, 170, 100, 50, "ENTER", Font16);
    while (true)
    {
        int num;
        if (bGroup1.GetTouchedNumber(num)){
            char buf[32];
            strcpy(buf, select_msg[num]);
            bTouch.Draw(buf, num);
        }
        if (button1.Touched()){
            return (uint8_t)(num + 1);
        }
        wait(0.02f);
    }
}


//------------------------------------------------------------------------------
// ORIGINAL PROGRAM FOR F746_GUI_DEMO
//  by MIKAMI, Naoki
//  2016/11/12, Copyright (c) 2016 MIKAMI, Naoki
//------------------------------------------------------------------------------
#if 0
//-----------------------------------------------------------------------
//  GuiBase とその派生クラスのデモプログラム
//  Demo program for GuiBase class and its derivertive classes
//
//      GuiBase, Button, ButtonGroup, Label, NumericLabel, BlinkLabel,
//      SeekBar, SeekbarGroup
//
//  2016/11/12, Copyright (c) 2016 MIKAMI, Naoki
//-----------------------------------------------------------------------
 
#include "F746_GUI.hpp"
 
int main()
{
    Label obj10(240, 2, "Dome: GUI parts, 2016/07/30, 19:43", Label::CENTER, Font16);
    Label obj11(240, 20, "Button, ButtonGroup, Label, NumericLabel, BlinkLabel,",
                Label::CENTER);
    Label obj12(240, 32, "SeekBar, SeekbarGroup",
                Label::CENTER);
 
    Button button1(10, 54, 50, 40, "1");
    Button button2(62, 54, 50, 40, "2");
 
    const int NUMBER_BUTTONS = 4;
    const string STR1[NUMBER_BUTTONS] = {"Button1", "Button2", "Button3", "Activate"};
    ButtonGroup bGroup1(160, 54, 66, 40,  NUMBER_BUTTONS, STR1, 5, 5, 3, 1,
                        Font12, LCD_COLOR_WHITE, 0xFF003538, 0xFFB70068, 0xFFFF7FFF);
    NumericLabel<int> bTouch(240, 112, "", Label::LEFT, Font12, LCD_COLOR_MAGENTA);
 
    // Control status of bGroup1
    ButtonGroup bGroup2(160, 150, 66, 40,  3, (string[]){"0", "1", "2"}, 5, 5, 3);
    bGroup2.InactivateAll();
    
    // Switching buttons to control barH active or inactive
    ButtonGroup bGroup3(10, 150, 66, 40,  2, (string[]){"ON", "OFF"}, 0, 0, 2);
    bGroup3.TouchedColor(0);
 
    Button doNotTouch(250, 220, 120, 40, "Don't Touch", Font12,
                      GuiBase::ENUM_TEXT, GuiBase::ENUM_BACK,
                      LCD_COLOR_DARKGREEN, LCD_COLOR_RED);
 
    // Using default value for argument (Horizontal)
    SeekBar barH(20, 250, 200, -5, 5, 0, "-5", "", "5");
    NumericLabel<float> numLabel1(80, 205, "%5.1f", barH.GetValue());
    NumericLabel<int> numLabel2(130, 205, "%3d", (int)barH.GetValue());
    NumericLabel<int> numLabel3(160, 205, "%3d");
    
    // SeekbarGroup (vertical)
    SeekbarGroup barV(410, 130, 121, 2, 45, -6, 6, 2,
                      SeekBar::Vertical, 0xFFA0FFC0);
    NumericLabel<float> **numLabel4;
    numLabel4 = new NumericLabel<float> *[2];
    for (int n=0; n<2; n++) numLabel4[n] =
        new NumericLabel<float>(410+n*45, 104, "%4.1f", barV.GetValue(n), Label::CENTER);
    NumericLabel<int> numLabel5(455, 92, "%1d", barV.GetIntValue(0), Label::CENTER);
 
    // Test of left-, cenrer-, and right-justified
    Label leftJustified(420, 54, "ABC", Label::LEFT);
    Label centerJustified(420, 64, "ABC", Label::CENTER);
    Label rightJustified1(420, 74, "ABC", Label::RIGHT);
 
    while (true)
    {
        if (button1.Touched()) button2.Draw();
        if (button2.Touched()) button1.Draw();
 
        int num;
        if (bGroup1.GetTouchedNumber(num))
            bTouch.Draw("Button%d touched", num+1);
        if (num == 3)
            bGroup2.ActivateAll();
 
        if (bGroup2.GetTouchedNumber(num))
        switch (num)
        {
            case 0: button1.Activate();
                    bGroup1.Activate(1);
                    bGroup1.DrawAll();
                    break;
            case 1: button1.Inactivate();
                    bGroup1.Inactivate(1);
                    break;
            case 2: bGroup1.EraseAll();//for (int n=0; n<4; n++) bGroup1.Erase(n);
                    for (int n=0; n<2; n++)
                    {
                        barV.Draw(n, 0);    // reset seekbar
                        numLabel4[n]->Draw("%4.1f", barV.GetValue(n));
                    }
                    break;
        }
 
        if (barH.Slide())
        {
            numLabel1.Draw("%5.1f", barH.GetValue());
            int8_t x = (int8_t)barH.GetValue();
            numLabel2.Draw("%3d", x);
 
            numLabel3.Draw(barH.GetIntValue());            
        }        
 
        int sbNum;
        if (barV.GetSlidedNumber(sbNum))
        {
            if (sbNum == 0) numLabel4[sbNum]->Draw("%4.1f", barV.GetValue(sbNum));
            else            numLabel4[sbNum]->Draw("%4.1f", barV.GetValue(sbNum));
            if (sbNum == 1) numLabel5.Draw("%1d", barV.GetIntValue(sbNum));
        }
        // If "doNotTouch" button touched, trapped into endless loop
        if (doNotTouch.Touched())
            BlinkLabel warning(250, 200, "You must reset", Label::LEFT, Font16);
            
        // SeekBar active inactive switching
        if (bGroup3.Touched(0))
        {
            barH.Activate();
            barV.ActivateAll();
        }
        if (bGroup3.Touched(1))
        {
            barH.Inactivate();
            barV.InactivateAll();
        }
 
        wait(0.02f);
    }
}

#endif