Charles Young's development fork. Going forward I only want to push mature code to main repository.

Dependencies:   mbed

Fork of GEO_COUNTER_L432KC by Geo Electronics "Geo Counter"

main.cpp

Committer:
charlesdavidyoung
Date:
2018-09-04
Revision:
20:fb73eaaf0894
Parent:
18:ef5678ab1889
Child:
21:5640ebc362a0

File content as of revision 20:fb73eaaf0894:

//  GEO COUNTER V1 firmware
//  This FW provides a basic operation of GEO-COUNTER
//
//  Latest review: August 27, 2018 - Walter Trovo
//
//  Sep  4, 2018: Charles Young: Created RotarySwitch class to manage mode selection
//  Feb 14, 2018: initial release aimed to test the counters, the serial port
//                the PWM output and the MAX7219 operation.
//  Feb 15, 2018: Removed MAX7219 libray (replaced with custom routine). 
//                Added 74HC595 routine. Added beep. Added Gate_write
//


// this block includes key libraries
#include <string>       // strings management
#include "RotarySwitch.hpp"

// Everything associated with the rotary switch and the associated LEDs
// is hidden in this class.
RotarySwitch ModeSwitch;

// definitions of fixed parameters

#define DEC_MODE    0x09FF  // BCD decoding on all digits
#define BRIGHTNESS  0x0A0F  // max brightness
#define SCAN_LIM    0x0B07  // use all 8 digits  
#define TURN_ON     0x0C01  // no shutdown (operating)
#define SHUTDOWN    0x0C00  // shutdown
#define TEST        0x0F00  // no test

#define DT      1      // delay time in us for SPI emulation

#define TGATE   10       // gate time (currently fixed for testing purpose)
#define MAX_VAL 999999  // Max value managed by the 6-digits display

// LED on processor board
DigitalOut led1(LED1);

// definitions of peripherals and devices

I2C     i2c(D4, D5);             // I2C port
Ticker  SecTenth_Beat;           // .1 second ticker
Ticker  Sec_Beat;                // 1 second ticker
Serial  PC(USBTX, USBRX);        // Virtual COM via USB (PC connection)
Serial  GPS(D1, D0);             // Serial port for GPS module

// Global variables
uint8_t     Disp_Digit[8]; // used to manage 8-digits through MAX7219
uint16_t    Stream;        // used to stream out serial data to MAX7219
time_t      seconds;       // Real-Time Clock (RTC) timestamp
unsigned int value = 0;    // displayed value on the 6-digits of the display
uint8_t     gate = TGATE;          // displayed value on the 2-digits display
uint32_t    Count1, Count2;    // pulse counters (32-bit)
char        Text[40]="";   // used to send messages over the serial port
uint8_t     Disp_mode = 0x01, Disp_unit = 0xA0;   // status of 1st row and 2nd rows of LEDs
bool        Stopped = 0;        // status of counting activity
bool        StartStopPressed = 0;// status of counting activity
double      ADC_val;    // used to read ADC value

// ----- Prototypes of routines (defined below the main) -------------------
void UpdateInput(void);  // periodically called by the ticker
void UpdateOutput(void);  // periodically called by the ticker
void Count1_up(void);  // called every time an edge is detected on TRIG1 pin
void Count2_up(void); // called every time an edge is detected on TRIG2 pin
void Beep(void);    // used to generate a short beep (buzzer)
void Display_init(void);    // initialize MAX7219
void Display_6D_write(uint8_t);    // write to MAX7219 (Main 6-digits display)
void Display_2D_write(unsigned short);    // write to MAX7219 (Gate 2-digits display)

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

int main() 
{
    
    PC.baud(115200);        // set baud-rate of virtual COM port (PC connection)
    PC.printf("\nGEO COUNTER V1 2108");
    PC.printf(__DATE__);
    PC.printf("  ");
    PC.printf(__TIME__);
    
    GPS.baud(9600); // set the baud-rate of the serial port dedicated to the GPS
    
    CS1 = 1;    // presets CS of MAX7219
    CS2 = 1;    // preset CS of 74HC595

    Display_6D_write(0x543210);
    Display_2D_write(TGATE);
    Display_init(); // initialize MAX7219

    // RTC is supposed to be loose time at power down (no backup battery)
    // An initialization is performed anyway 
    set_time(0); // Set time
    
    PWM.period_ms(3);    // set the PWM period
    PWM.write(0.8);      // set the PWM duty-cycle
    
    Beep(); // initial beep    
    
    // set the 1 sec ticker to periodically call the Update() routine
    // NOTE: this is also the 1-sec time base for counters. A better approach
    // would replace the ticker with an interrupt from the RTC (to be implemented)
    SecTenth_Beat.attach_us(&UpdateInput,  100000);  
    Sec_Beat.attach_us(&UpdateOutput, 1000000);  
    //RTC::attach(&Update, RTC::Second);
    //RTC::detach(RTC::Second);  
  
    // main loop does nothing as all activities are interrupt driven    
    while(1) 
    {
        // dance (or drink a beer)                
    }
}


//-------- END OF MAIN --------------
//==============================================================================

// Definition of routines

//---------------------------------------------------------------------------
// Update values to be displayed  
void logToPC()
{               
   PC.printf("\nADC: %.02f", ADC_val); 
   PC.printf(Stopped ? " stopped" : " started");
   // Timestamp to PC (debug)
   seconds = time(NULL);   // get current time 
   strftime(Text, 50, "%H:%M:%S", localtime(&seconds));
   PC.printf(" RTC: %s, CNT1: %7d CNT2: %7d",Text, Count1, Count2);
   //PC.printf(" wheel %d %d", WheelCurrent, QEPB.read());
}

void UpdateOutput()   
{
    // This must be called periodically to update the LEDs
    ModeSwitch.UpdateOutput();
      
   if(Stopped)
   {    
      // disable interrupts on TRIG1 and TRIG2
        
      TRIG1.rise(NULL);      
      TRIG2.rise(NULL); 
        
      // show zero gate time   
      gate = 0;                   
      Display_2D_write(gate);
        
      // show selected content on main display
      value = (int)(Count1/TGATE);
      Display_6D_write(value);    // refresh the main display              
   }
    
   else
   {
      // Enable interrupts on rising edge of digital inputs TRIG1 & TRIG2
      TRIG1.rise(&Count1_up);     
      TRIG2.rise(&Count2_up);         
        
      if(gate==0) // show the counter value at the end of the gate time
      {
         value = (int)(Count1/TGATE);
                
         Display_6D_write(value);    // refresh the main display 
        
         Count1 = 0;     // clear both counters
         Count2 = 0;
         gate = TGATE;// and reload the gate time

      }

      Display_2D_write(gate);     // show gate time countdown 
      gate--;
   }
}

void UpdateInput()   
{
   // This must be called periodically to monitor switch input
   ModeSwitch.UpdateInput();
        
   ADC_val = KEYB.read();  // read voltage from keyboard
   if (   (ADC_val<0.1)    // START/STOP pushbutton pressed
       && (!StartStopPressed))
   {
      StartStopPressed = true;
      Stopped=!Stopped;           // toggle status
   }
   else
      StartStopPressed = false;
    
   if((ADC_val>0.6)&&(ADC_val<0.7))    // CLEAR pushbutton pressed
   { 
      Count1 = 0; // clear counters     
      Count2 = 0;              
   }
   logToPC();
   return;
}

//---------------------------------------------------------------------------
// Increment CNT1 every time a rising edge is detected on TRIG1 (interrupt)

void Count1_up(void)
{                       
    Count1++;                        
    return; 
}

//---------------------------------------------------------------------------
// Increment CNT1 every time a rising edge is detected on TRIG2 (interrupt)

void Count2_up(void)
{                      
    Count2++;                        
    return; 
}


//---------------------------------------------------------------------------
//Generates a short beep via BUZZ

void Beep(void)       
{                       
    BUZZ = 1;         // turn-on the buzzer
    wait(0.3);        // wait
    BUZZ = 0;         // turn-off the buzzer   
    return; 
}

//---------------------------------------------------------------------------
// Initialize the MAX7219

void Display_init(void)
{
    uint8_t i;
    uint16_t mask;
    uint16_t data_to_send[6] = {SHUTDOWN, TURN_ON, DEC_MODE, BRIGHTNESS, SCAN_LIM, TEST};
             //{SHUTDOWN, TURN_ON, DEC_MODE, BRIGHTNESS, SCAN_LIM, TEST};
    for(i = 0; i <6; i++)
    {
        CS1 = 0;
      
        for(mask = 0x8000; mask!= 0; mask>>= 1)
        {
            wait_us(DT);
            SCK = 0;
            if(mask & data_to_send[i])
                MOSI = 1;
            else
                MOSI = 0;
            wait_us(DT);    
            SCK = 1;
        }
        
        wait_us(DT);
        SCK = 0;
        wait_us(DT);
        CS1 = 1;
    }
    
  return;
}


//---------------------------------------------------------------------------
// Refresh the 6 digits of the main display

void Display_6D_write(uint8_t value)
{
 
    uint8_t digit;
    uint16_t mask, data_to_send;
    char TextString[6];
    
    // int to string, then string to digits
    
    sprintf(TextString, "%6d", value);   // int to string
    
    for(uint8_t i=0; i<6; i++)
    {   
        if(TextString[i] == ' ')  // blank empty digits
            Disp_Digit[i] = 0xFF;
        else
            Disp_Digit[i] = TextString[i]-'0';      
    }

    // write to chip

    SCK = 0;
    wait_us(DT);    
    
    for(digit = 1; digit <7; digit++)
    {
        // each stream consists of digit address and data to show
        data_to_send = 7 - digit;
        data_to_send<<=8;
        data_to_send = data_to_send | Disp_Digit[digit-1];
        
        CS1 = 0;
        
        for(mask = 0x8000; mask!= 0; mask>>= 1)
        {
            wait_us(DT);
            SCK = 0;
            if(mask & data_to_send)
                MOSI = 1;
            else
                MOSI = 0;
                
            wait_us(DT);
            SCK = 1;
        }
        
        wait_us(DT);    
        SCK = 0;
        wait_us(DT);
        CS1 = 1;
    }
    
  return;
}


//---------------------------------------------------------------------------
// Refresh the 2 digits of the gate display

void Display_2D_write(unsigned short value)
{
 
    uint8_t digit;
    uint16_t mask, data_to_send;
    char TextString[2];

    // int to string, then string to digits
    
    sprintf(TextString, "%2d", value);   // int to string

    if(TextString[0] == ' ')  // blank empty digits
        Disp_Digit[7] = 0xFF;    
    else
        Disp_Digit[7] = TextString[0] - '0';
    
    Disp_Digit[6] = TextString[1] - '0';

    // write to chip
    
    SCK = 0;
    wait_us(DT);    
    
    for(digit = 7; digit <9; digit++)
    {
        // each stream consists of digit address and data to show
        data_to_send = digit;
        data_to_send<<=8;
        data_to_send = data_to_send | Disp_Digit[digit-1];
        
        CS1 = 0;
        
        for(mask = 0x8000; mask!= 0; mask>>= 1)
        {
            wait_us(DT);
            SCK = 0;
            
            if(mask & data_to_send)
                MOSI = 1;
            else
                MOSI = 0;
                
            wait_us(DT);
            SCK = 1;
        }
        
        wait_us(DT);    
        SCK = 0;
        wait_us(DT);
        CS1 = 1;
    }
    
  return;
}

//-------- END OF FILE --------------
//==============================================================================