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/

main.cpp

Committer:
kenjiArai
Date:
2014-10-22
Revision:
7:0c09d29c4cf3
Parent:
6:44c2bcbdd77b
Child:
8:7b033903c8fb

File content as of revision 7:0c09d29c4cf3:

/*
 * mbed Application program / Frequency Counter
 *
 * Copyright (c) 2014 Kenji Arai / JH1PJL
 *  http://www.page.sannet.ne.jp/kenjia/index.html
 *  http://mbed.org/users/kenjiArai/
 *      Created: October   18th, 2014
 *      Revised: October   22nd, 2014
 *
 * 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.
 */

#define USE_COM         // use Communication with PC(UART)
#define USE_TEXT_LCD    // use Text LCD/I2C Interface
#define USE_GRAP_LCD    // use Grafic LCD/SPI interface

//  Include ---------------------------------------------------------------------------------------
#include "mbed.h"
#include "freq_counter.h"
#if defined(USE_TEXT_LCD)
#include "TextLCD.h"            // Std. lib./ LCD control
#endif
#if defined(USE_GRAP_LCD)
#include "ST7565_SPI_LCD.h"
#endif

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

#if defined(TARGET_LPC1768)
// LPC1768 Frequency example
// Outout mbed's "PWM6" pin to 96MHZ/19 = 5.052MHz (Approx)
#define CLK_REFRENCE()  PWM6_SETCLK(19)
// Outout mbed's "PWM6" pin to 96MHZ/96 = 1.000MHz (Approx)
//#define CLK_REFRENCE()    PWM6_SETCLK(96)
#elif defined(TARGET_LPC1114)
#define led_not_zero    temp_ram
#define led_01          temp_ram
#define led_10          temp_ram
#define CLK_REFRENCE()  clock_out()
#warning "Don't forget LPC1114 runs with internal clock. Measurement data is not accurate!!"
#elif defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)
#define led_not_zero    temp_ram
#define led_01          temp_ram
#define led_10          temp_ram
#define CLK_REFRENCE()  port_mco1_mco2_set()
#else
#error "No support for this CPU"
#endif

//  Object ----------------------------------------------------------------------------------------
#if defined(TARGET_LPC1768)

DigitalOut led_gate(LED1);
DigitalOut led_not_zero(LED2);
DigitalOut led_01(LED3);
DigitalOut led_10(LED4);
DigitalIn  sw_01(p19);
DigitalIn  sw_10(p20);
Serial pc(USBTX, USBRX);
I2C i2cBus(p9, p10);   // SDA, SCL
#if defined(USE_TEXT_LCD)
TextLCD_I2C_N lcd(&i2cBus, 0x7c, TextLCD::LCD8x2);  // LCD(Akizuki AQM0802A)
#endif
#if defined(USE_GRAP_LCD)
ST7565 glcd(p5, p7, p19, p8, p20, ST7565::AD12864SPI); // mosi, sck, reset, a0, ncs
#endif
PwmOut fmclck(p21);                 // for RESERVE pin21 as PWM1[6]
F_COUNTER fc(p30);

#elif defined(TARGET_LPC1114)

DigitalOut led_gate(LED2);
DigitalIn  sw_01(dp25);
DigitalIn  sw_10(dp26);
Serial pc(dp16,dp15);       // Communication with Host
I2C i2cBus(dp5,dp27);       // SDA, SCL
#if defined(USE_TEXT_LCD)
TextLCD_I2C_N lcd(&i2cBus, 0x7c, TextLCD::LCD8x2);  // LCD(Akizuki AQM0802A)
#endif
#if defined(USE_GRAP_LCD)
ST7565 glcd(dp2, dp6, dp10, dp4, dp9, ST7565::AQM1248A); // mosi, sck, reset, a0, ncs
#endif
F_COUNTER fc(dp14);
// dp24 uses for CLOCKOUT -> Clock output for checking

#elif defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)

DigitalOut led_gate(LED1);
DigitalIn  sw_01(PC_0);
DigitalIn  sw_10(PC_1);
Serial pc(USBTX, USBRX);
I2C i2cBus(PB_9,PB_8);  // SDA, SCL
#if defined(USE_TEXT_LCD)
TextLCD_I2C_N lcd(&i2cBus, 0x7c, TextLCD::LCD8x2);  // LCD(Akizuki AQM0802A)
#endif
#if defined(USE_GRAP_LCD)
ST7565 glcd(PB_5, PB_3, PA_10, PB_10, PA_9, ST7565::AD12864SPI); // mosi, sck, reset, a0, ncs
#endif
F_COUNTER fc(PA_0);
// PA8 & PC9 uses for MCO_1 % MCO_2 -> Clock output for checking

#else
#error "No support for this CPU"
#endif

//  RAM -------------------------------------------------------------------------------------------
float freqency;
double t_gate;
uint8_t sw;

uint32_t temp_ram;  // dummy ram (please keep it!)

//  ROM / Constant data ---------------------------------------------------------------------------

//  Function prototypes ---------------------------------------------------------------------------

//  Function prototypes ---------------------------------------------------------------------------

//-------------------------------------------------------------------------------------------------
//  Control Program
//-------------------------------------------------------------------------------------------------
#if defined(TARGET_LPC1768)

// Clock Output From pin21(PWM6)
// Set Clock Freq with div.
// if mbed is running at 96MHz, div is set 96 to Get 1MHz.
void PWM6_SETCLK(int div)
{
    LPC_PWM1->TCR = (1 << 1);           // 1)Reset counter, disable PWM
    LPC_SC->PCLKSEL0 &= ~(0x3 << 12);
    LPC_SC->PCLKSEL0 |= (1 << 12);      // 2)Set peripheral clock divider to /1, i.e. system clock
    LPC_PWM1->MR0 = div - 1;            // 3)Match Register 0 is shared period counter for all PWM1
    LPC_PWM1->MR6 = (div + 1)>> 1;      //
    LPC_PWM1->LER |= 1;                 // 4)Start updating at next period start
    LPC_PWM1->TCR = (1 << 0) || (1 << 3); // 5)Enable counter and PWM
}

#elif defined(TARGET_LPC1114)

// CLOCKOUT from pin24(dp18)
//      Freq = 48MHz/4 = 12MHz
void clock_out(void)
{
    LPC_SYSCON->CLKOUTCLKSEL = 3;       // System clock
    LPC_SYSCON->CLKOUTDIV = 4;          // div 1/4
    LPC_IOCON->PIO0_1 = 1;              // select CLKOUT to P0_1(pin24)/dp18
    LPC_SYSCON->CLKOUTUEN = 1;          // enable output
}

#elif defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)

void port_mco1_mco2_set(void)
{
    uint32_t temp = 0x00;

    // PA8 -> MCO_1
    temp = ((uint32_t)(GPIO_AF0_MCO) << (((uint32_t)8 & (uint32_t)0x07) * 4)) ;
    GPIOA->AFR[8 >> 3] &= ~((uint32_t)0xf << ((uint32_t)(8 & (uint32_t)0x07) * 4)) ;
    GPIOA->AFR[8 >> 3] |= temp;
    GPIOA->MODER &= ~(GPIO_MODER_MODER0 << (8 * 2));
    GPIOA->MODER |= (0x2 << (8 * 2));
    // PC9 -> MCO_2
    temp = ((uint32_t)(GPIO_AF0_MCO) << (((uint32_t)9 & (uint32_t)0x07) * 4)) ;
    GPIOC->AFR[9 >> 3] &= ~((uint32_t)0xf << ((uint32_t)(9 & (uint32_t)0x07) * 4)) ;
    GPIOC->AFR[9 >> 3] |= temp;
    GPIOC->MODER &= ~(GPIO_MODER_MODER0 << (9 * 2));
    GPIOC->MODER |= (0x2 << (9 * 2));
    // Select output clock source
    RCC->CFGR &= 0x009fffff;
    // MC0_1 output HSE 1/4, MCO_2 output SYSCLK 1/4
    //             MCO2          MCO2PRE       MCO1PRE       MCO1
    RCC->CFGR |= (0x0 << 30) + (0x6 << 27) + (0x6 << 24) + (0x3 << 22);
}

#else
#error "No support for this CPU"
#endif

void read_sw_and_set_gate_time(void)
{
    if (sw_10) {
        led_10 = 1;
        sw = 2;
    } else {
        led_10 = 0;
        sw = 0;
    }
    if (sw_01) {
        led_01 = 1;
        sw += 1;
    } else {
        led_01 = 0;
    }
    switch (sw) {
        case 0:
            t_gate = 0.001;
            break;
        case 1:
            t_gate = 0.01;
            break;
        case 2:
            t_gate = 0.1;
            break;
        case 3:
        default:
            t_gate = 1.0;
            break;
    }
}

int main()
{
    PRINTF("\r\nFrequency Counter by JH1PJL created on "__DATE__"\r\n");
    t_gate = 1.0;
    // Initialize LCD
#if defined(USE_TEXT_LCD)
    lcd.locate(0, 0);    // 1st line top
    //          12345678
    lcd.printf("Fre-Cntr");
    lcd.locate(0, 1);    // 2nd line top
    //        12345678
    lcd.puts(" JH1PJL ");
    lcd.setContrast(0x16);
#endif
#if defined(USE_GRAP_LCD)
    glcd.cls();
    glcd.locate(0, 0);
    glcd.printf("--- Frequency Counter --\r\n");
    glcd.printf("     Kenji Arai / JH1PJL\r\n" );
    glcd.printf("                        \r\n");
#if defined(TARGET_LPC1768)
    glcd.set_contrast(0x06);
    glcd.printf(" Input: P30 PWM out: P21\r\n" );
    glcd.printf(" LED1:Gate  LED2:signal \r\n" );
#elif defined(TARGET_LPC1114)
    glcd.set_contrast(0x01);
    glcd.printf(" LED2:Gate              " );
#elif defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE)
    glcd.set_contrast(0x06);
    glcd.printf(" Input: PA0 PWM out: PA8\r\n" );
    glcd.printf(" LED1:Gate              \r\n" );
#else
#error "No support for this CPU"
#endif
#endif  // defined(USE_GRAP_LCD)
#if defined(USE_TEXT_LCD)
    wait(5.0);
    lcd.locate(0, 1);    // 2nd line top
    //        12345678
    lcd.puts("        ");
#endif
    // Set Internalclock for reference
    CLK_REFRENCE();
    freqency = 0;
    while(true) {
        led_gate = 1;
        freqency = (float)fc.read_frequency(t_gate);
        led_gate = 0;
        wait(1.1 - t_gate);
        if (freqency == 0) {
            led_not_zero = 1;
        } else {
            led_not_zero = 0;
        }
        read_sw_and_set_gate_time();
        PRINTF("f= %9.0f [Hz], gate= %4.3f [Sec]\r\n", freqency/t_gate, t_gate);
#if defined(USE_TEXT_LCD)
        lcd.locate(0, 0);    // 1st line top
        lcd.printf("%8.0f", freqency);
        lcd.locate(0, 1);    // 2nd line top
#endif
#if defined(USE_GRAP_LCD)
        glcd.locate(0, 10);
        glcd.printf("                      \r\n");
        glcd.locate(10, 10);
        glcd.printf("%8.0f Hz", freqency);
        glcd.locate(10, 20);
#endif
        switch (sw) {
            case 0:
#if defined(USE_TEXT_LCD)
                //          12345678
                lcd.printf("x1000 Hz");
#endif
#if defined(USE_GRAP_LCD)
                glcd.printf("  x1000   ");
#endif
                break;
            case 1:
#if defined(USE_TEXT_LCD)
                //          12345678
                lcd.printf("x100  Hz");
#endif
#if defined(USE_GRAP_LCD)
                glcd.printf("  x100    ");
#endif
                break;
            case 2:
#if defined(USE_TEXT_LCD)
                //          12345678
                lcd.printf("x10   Hz");
#endif
#if defined(USE_GRAP_LCD)
                glcd.printf("x10     ");
#endif
                break;
            case 3:
            default:
#if defined(USE_TEXT_LCD)
                //          12345678
                lcd.printf("x1    Hz");
#endif
#if defined(USE_GRAP_LCD)
                glcd.printf("  x1      ");
#endif
                break;
        }
    }
}