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:
Charles David Young
Date:
2018-09-06
Revision:
47:f004b4612069
Parent:
46:c7ce8fccb712
Child:
48:468220d69071

File content as of revision 47:f004b4612069:

//  GEO COUNTER V1 firmware
//  This FW provides a basic operation of GEO-COUNTER
//
//  Latest review: August 27, 2018 - Walter Trovo
//
//  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)
int32_t     TickerCorrection = 0;
const int16_t TickerCorrectionMax = 99;
const int16_t TickerCorrectionMin = -99;

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

void UpdateOutput()   
{
   // This must be called periodically to update the LEDs
   ModeSwitch.UpdateOutput();
      
   switch (currentModeToDisplay) {
      case CNT1:
         DigitsDisplay.Display_6D_write(Count1);
         DigitsDisplay.Display_2D_Blank();
         break;
      case CNT2:
         DigitsDisplay.Display_6D_write(Count2);
         DigitsDisplay.Display_2D_Blank();
         break;
      case PROSPECT:
         if (Count1)
            DigitsDisplay.Display_6D_write(Count1);
         else
            DigitsDisplay.Display_6D_write(Count2);
         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;
   }

   if(Stopped)
   {    
      // disable interrupts on TRIG1 and TRIG2
      TRIG1.rise(NULL);      
      TRIG2.rise(NULL); 
   }
   else
   {
      // Enable interrupts on rising edge of digital inputs TRIG1 & TRIG2
      TRIG1.rise(&Count1_up);     
      TRIG2.rise(&Count2_up);         
        
      Count1 = 0;     // clear both counters
      Count2 = 0;
   }
}

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)
             && (TickerCorrection < TickerCorrectionMax))
         {
            TickerCorrection++;
            Sec_Beat.attach_us(&UpdateOutput, 1000000 + 1000*TickerCorrection); 
         }
         else
            if (   (direction < 0)
                && (TickerCorrection > TickerCorrectionMin))
            {
               TickerCorrection--;
               Sec_Beat.attach_us(&UpdateOutput, 1000000 + 1000*TickerCorrection);  
            }
         DigitsDisplay.Display_2D_write(TickerCorrection);
         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;
      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 --------------
//==============================================================================