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-10-07
Revision:
80:5770804da1b0
Parent:
79:5cdbe0d2adbb

File content as of revision 80:5770804da1b0:

//  GEO COUNTER V1 firmware
//  This FW provides a basic operation of GEO-COUNTER
//
//  Latest review: August 27, 2018 - Walter Trovo
//
//  Sep 13, 2018: Charles Young: CNT1 and CNT2 smooth
//  Sep  9, 2018: Charles Young: CNT1 and CNT2 accurate except for jumping up
//  Sep  6, 2018: Charles Young: Functioning mode selection - modes partially implemented
//  Sep  5, 2018: Charles Young: Created LED7segDisplay class
//  Sep  5, 2018: Charles Young: Still developing mode selection.  LEDs turn off
//                when not in mode selection.  Pressing once enters mode selection.
//                Pressing again enters submode.  Temporarily the rotary switch
//                adjusts the display brightness.  This is just for testing.
//  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"
#include "LED7segDisplay.hpp"

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

enum Modes {
   CNT1,
   CNT2,
   PROSPECT,
   NULL1,
   NULL2,
   VOLTS,
   VOLUME,
   DIM,
   NumberOfModes
};
uint8_t currentMode          = CNT1;
uint8_t currentModeToDisplay = CNT1;

// 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
time_t      seconds;       // Real-Time Clock (RTC) timestamp
unsigned int value = 0;    // displayed value on the 6-digits of the display

uint32_t Count1, Count2;    // pulse counters (32-bit)
#define  CountAvg 4
uint32_t Count1Avg[CountAvg], Count2Avg[CountAvg];    // pulse counters (32-bit)
uint8_t  CountAvgIndex = 0;
uint32_t Count1Save;
uint32_t Count2Save;

uint32_t    TickerPeriod = 100000;
uint32_t    TickerPeriodCount = 0;
const uint32_t TickerPeriodsPerSecond = 1000000/TickerPeriod;
const uint32_t TickerTicksPerSecond   = TickerPeriod*TickerPeriodsPerSecond;

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
float       direction = 0;

#define maxVolume 10
uint8_t     volume = maxVolume;

// ----- Prototypes of routines (defined below the main) -------------------
void UpdateInput(void);  // periodically called by the ticker
void UpdateOutput(void);  // periodically called by the ticker
void UpdateIO(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)

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

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

   DigitsDisplay.Display_6D_write(0x543210);
   DigitsDisplay.Display_2D_write(0);

   // RTC is supposed to lose 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(&UpdateIO,  TickerPeriod);
   //RTC::attach(&Update, RTC::Second);
   //RTC::detach(RTC::Second);  

   TRIG1.fall(&Count1_up);     
   TRIG2.fall(&Count2_up);         

   for (uint8_t i=0;i<CountAvg;i++)
   {
      Count1Avg[i] = 0;
      Count2Avg[i] = 0;
   }

   // main loop does nothing as all activities are interrupt driven    
   while(1) 
   {
      // somehow this makes it worse
      // // Manage user I/O outside Ticker interrupt for accuracy
      // wait_us(TickerPeriod);
      // if (TickerPeriodCount == 0)
      //    UpdateOutput();
      // UpdateInput();
   }
}


//-------- 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 %f", direction);
}

void UpdateIO()   
{
   if (++TickerPeriodCount >= TickerPeriodsPerSecond)
   {
      // Capture the counts early so they will be more accurate
      Count1Avg[CountAvgIndex] = Count1;
      Count2Avg[CountAvgIndex] = Count2;
      CountAvgIndex = ++CountAvgIndex % CountAvg;

      // smooth counts while accounting for small roundoff error
      uint32_t Count1Sum = 1, Count2Sum = 1;
      for (uint8_t i=0;i<CountAvg;i++)
      {
         Count1Sum += Count1Avg[i];
         Count2Sum += Count2Avg[i];
      }
      Count1Save = Count1Sum / CountAvg;
      Count2Save = Count2Sum / CountAvg;
      Count1 = 0;
      Count2 = 0;

      TickerPeriodCount = 0;

      UpdateOutput();
   }
   UpdateInput();
}

void UpdateOutput()
{
   if(Stopped)
   {    
      // disable interrupts on TRIG1 and TRIG2
      TRIG1.fall(NULL);      
      TRIG2.fall(NULL); 
   }

   // This must be called periodically to update the LEDs
   ModeSwitch.UpdateOutput();
      
   switch (currentModeToDisplay) {
      case CNT1:
         DigitsDisplay.Display_6D_write(Count1Save);
         DigitsDisplay.Display_2D_Blank();
         break;
      case CNT2:
         DigitsDisplay.Display_6D_write(Count2Save);
         DigitsDisplay.Display_2D_Blank();
         break;
      case PROSPECT:
         if (Count1Save)
            DigitsDisplay.Display_6D_write(Count1Save);
         else
            DigitsDisplay.Display_6D_write(Count2Save);
         DigitsDisplay.Display_2D_Blank();
         break;
      case NULL1:
         DigitsDisplay.Display_6D_write(0);
         DigitsDisplay.Display_2D_Blank();
         break;
      case NULL2:
         DigitsDisplay.Display_6D_write(0);
         DigitsDisplay.Display_2D_Blank();
         break;
      case VOLTS:
         DigitsDisplay.Display_6D_write(0);
         DigitsDisplay.Display_2D_Blank();
         break;
      case VOLUME:
      case DIM:
      default:
         break;
   }
}

void UpdateInput()   
{
   // This must be called periodically to monitor switch input
   direction   = ModeSwitch.UpdateInput();
   currentMode = ModeSwitch.GetPosition();
        
   switch (currentMode) {
      case CNT1:
      case CNT2:
         currentModeToDisplay = currentMode;

         if (direction > 0)
         {
         }
         else
            if (direction < 0)
            {
            }
         break;
      case PROSPECT:
      case VOLTS:
         currentModeToDisplay = currentMode;
         break;
      case NULL1:
      case NULL2:
         break;
      case VOLUME:
         if (   (direction > 0)
             && (volume < maxVolume))
            volume++;
         else
            if (   (direction < 0)
                && (volume > 0))
               volume--;

         DigitsDisplay.Display_2D_write(volume);
         break;
      case DIM:
         if (direction > 0)
            DigitsDisplay.Display_brightness_up();
         else
            if (direction < 0)
               DigitsDisplay.Display_brightness_down();

         DigitsDisplay.Display_2D_write(DigitsDisplay.GetBrightness());
         break;
      default:
         break;
   }

   // ADC_val = KEYB.read();  // read voltage from keyboard
   // if (   (ADC_val<0.1)    // START/STOP pushbutton pressed
   //     && (!StartStopPressed))
   // {
   //    StartStopPressed = true;
   //    if (Stopped)
   //    {
   //       // Enable interrupts on rising edge of digital inputs TRIG1 & TRIG2
   //       TRIG1.rise(&Count1_up);     
   //       TRIG2.rise(&Count2_up);         
   //    }
   //    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)
{                       
   //Beep();
   Count1++;                        
   return; 
}

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

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


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

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

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