Charles Young's development fork. Going forward I only want to push mature code to main repository.
Fork of GEO_COUNTER_L432KC by
Diff: main.cpp
- Revision:
- 1:75827d765e34
- Parent:
- 0:6d1742703713
- Child:
- 2:ac0ed3d84d44
--- a/main.cpp Tue Feb 13 13:30:08 2018 +0000 +++ b/main.cpp Fri Feb 16 16:32:58 2018 +0000 @@ -1,42 +1,90 @@ -#include "mbed.h" -#include <string> -#include "max7219.h" -#include "QEI.h" +// GEO COUNTER V1 firmware +// +// 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 "mbed.h" // global Mbed library (always needed) +#include <string> // strings management +#include "QEI.h" // Quadrature Encoder functions + +// definitions of fixed parameters -#define TGATE 1 -#define MAX_VAL 999999 +#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 + +#define CPM 0x01 +#define CPS 0x02 +#define PLS 0x04 +#define VOLTS 0x08 +#define CNT1 0x10 +#define CNT2 0x20 +#define HV 0x40 +#define MENU 0x80 + +// definitions of the input/outputs (pins) +DigitalOut AUX (D2); // AUX control for GPS module InterruptIn TRIG1 (D3); // Counter 1 trigger InterruptIn TRIG2 (D6); // Counter 2 trigger +DigitalIn QEIPB (D9); // Quadrature encoder pushbutton PwmOut PWM (D10); // PWM output -DigitalOut BUZZ (D2); // Buzzer -DigitalOut AUX (D2); // AUX control for GPS module -DigitalIn QEIPB (D9); // Quadrature encoder pushbutton +DigitalOut BUZZ (D13); // Buzzer -QEI Wheel(D11, D12, NC, 16); // Quadrature encoder -I2C i2c(D4, D5); // I2C port -Ticker Sec_Beat; -Max7219 Display(A6, A5, A4, A3); //LED diplay driver (MOSI, MISO, SCK, SS) -Serial PC(USBTX, USBRX); // Virtual COM via USB -Serial GPS(D1, D0); +AnalogIn AIN0 (A0); // ADC input 0 (High Voltage) +AnalogIn AIN1 (A1); // ADC input 1 (aux) +DigitalOut CS2 (A2); // 74HC595 RCLK (pin 12) +DigitalOut CS1 (A3); // MAX7219 CS (pin 12) +DigitalOut SCK (A4); // 74HC595 SRCLK (pin 11) & MAX7219 SCK (pin 13) +AnalogIn KEYB (A5); // Keyboard input (SW2 & SW3) +DigitalOut MOSI (A6); // 74HC595 SER (pin 14) & MAX7219 DIN (pin 1) +DigitalIn UN (A7); // Unused (in V1 PCB A5 and A7 must be connected) + + + + +// definitions of peripherals and devices +QEI Wheel(D12, D11, NC, 16); // Quadrature encoder +I2C i2c(D4, D5); // I2C port +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 Digit_Disp[8]; -uint16_t Stream; - -time_t seconds; // RTC timestamp +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 = 1; // status of counting activity +double ADC_val; // used to read ADC value -unsigned int value = 0; -uint32_t CNT1, CNT2; // pulse counters -uint8_t gate; -char Text[40]=""; - -// ------------------- Prototypes ----------------------- -void RefreshDisplay(void); -void Update(void); -void CNT1_count(void); -void CNT2_count(void); - +// ----- Prototypes of routines (defined below the main) ------------------- +void Update(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 LEDs_write(unsigned short); // write to 74HC595 (8x LEDs) +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) //============================================================================== //============================================================================== @@ -44,149 +92,340 @@ int main() { - PC.baud(115200); - PC.printf("Connected...\n"); - GPS.baud(9600); + PC.baud(115200); // set baud-rate of virtual COM port (PC connection) + PC.printf("GEO COUNTER V1 2108\n"); + PC.printf(__DATE__); + PC.printf(" "); + PC.printf(__TIME__); + PC.printf("\nReady...\n"); + + GPS.baud(9600); // set tyhe baud-rate of the serial port dedicated to the GPS - max7219_configuration_t cfg = { - .device_number = 1, - .decode_mode = 0xFF, - .intensity = Max7219::MAX7219_INTENSITY_F, // max brightness - .scan_limit = Max7219::MAX7219_SCAN_6 // 6 digits - }; + CS1 = 1; // presets CS of MAX7219 + CS2 = 1; // preset CS of 74HC595 + + Display_6D_write(0); + Display_2D_write(TGATE); + Display_init(); // initialize MAX7219 - Display.init_device(cfg); - Display.enable_device(1); - Display.device_all_on(1); - - set_time(1256729737); // Set time to Wed, 28 Oct 2009 11:35:37 + // RTC is supposed to be loose time at power down (no backup battery) + // An initialization is performed anyway + set_time(0); // Set time + Wheel.reset(); // clear the variable associated to the encoder + + PWM.period_ms(3); // set the PWM period + PWM.write(0.8); // set the PWM duty-cycle + + LEDs_write(0x00); // initialize LEDs (CPM and CNT1 on) + Beep(); // initial beep + + uint8_t LED_status = CNT1 | CPS; + LEDs_write(LED_status); + + // 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) + Sec_Beat.attach(&Update, 1); //RTC::attach(&Update, RTC::Second); - //RTC::detach(RTC::Second); - - Wheel.reset(); // clear encoder - - PWM.period_ms(3); // set LCD backlight PWM - PWM.write(0.8); - /* - BUZZ.period_ms(30); // set LCD backlight PWM - BUZZ.write(0.2); - */ - Sec_Beat.attach(&Update, 1); - - // enable & attach interrupts on rising edge of digital inputs - TRIG1.rise(&CNT1_count); - TRIG2.rise(&CNT2_count); - - + //RTC::detach(RTC::Second); + + // main loop does nothing as all activities are interrupt driven while(1) { - // do nothing - + // dance (or do nothing) } } -// ------------- Refresh Display ------------------------ - -void RefreshDisplay(void) -{ - Display.write_digit(1, 1, Digit_Disp[6]); // device, digit, data - Display.write_digit(1, 2, Digit_Disp[5]); // device, digit, data - Display.write_digit(1, 3, Digit_Disp[4]); // device, digit, data - Display.write_digit(1, 4, Digit_Disp[3]); // device, digit, data - Display.write_digit(1, 5, Digit_Disp[2]); // device, digit, data - Display.write_digit(1, 6, Digit_Disp[1]); // device, digit, data - Display.write_digit(1, 7, Digit_Disp[0]); // device, digit, data - - return; -} - - - +//-------- END OF MAIN -------------- //============================================================================== -void Update() // refresh display data -{ - char TextString[9]; - gate++; - - if(QEIPB) - AUX = 1; - else - AUX = 0; +// Definition of routines + +//--------------------------------------------------------------------------- +// Update values to be displayed + +void Update() +{ + ADC_val = KEYB.read(); // read voltage from keyboard - if(gate==TGATE) - { - //value = (int)(CNT1/TGATE); - value = int(Wheel.getPulses()); - - if(value<MAX_VAL) - { - snprintf(TextString, 8, "%7d", value); // int to string - seconds = time(NULL); - strftime(Text, 50, "%d-%b-%Y %H:%M:%S", localtime(&seconds)); - PC.printf("RTC: %s, CNT1: %7d CNT2: %7d\n",Text, CNT1, CNT2); + if(ADC_val<0.1) // RESET pushbutton pressed + { + Count1 = 0; // clear counters + Count2 = 0; + } + + if((ADC_val>0.4)&&(ADC_val<0.6)) // START/STOP pushbutton pressed + Stopped=!Stopped; // toggle status + + if(Stopped) + { + // disable interrupts on TRIG1 and TRIG2 + TRIG1.rise(NULL); + TRIG2.rise(NULL); - for(uint8_t i=0; i<7; i++) - { - if(TextString[i]==' ') // blanking empty digits - TextString[i]= 0xFF; - else - TextString[i]=TextString[i]-'0'; - - Digit_Disp[i] = TextString[i]; - - } - } + // show zero gate time + gate = 0; + Display_2D_write(gate); - else - { - for(uint8_t i=0; i<7; i++) // all minus - Digit_Disp[i] = 10; - } - - RefreshDisplay(); + // show selected content on main display + value = (int)(Count1/TGATE); + Display_6D_write(value); // refresh the main display + } - CNT1=0; - CNT2=0; - gate = 0; - } else { - value = TGATE - gate; - snprintf(TextString, 8, "%7d", value); - for(uint8_t i=6; i<8; i++) - { - if(TextString[i]==' ') // blanking empty digits - TextString[i]= 0xFF; - else - TextString[i]=TextString[i]-'0'; - } - - //Digit_Disp[1] = TextString[6]; - //Digit_Disp[0] = TextString[7]; + // 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); + //value = int(Wheel.getPulses()); - RefreshDisplay(); + 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--; + + // Timestamp to PC (debug) + seconds = time(NULL); // get current time + //strftime(Text, 50, "%d-%b-%Y %H:%M:%S", localtime(&seconds)); + strftime(Text, 50, "%H:%M:%S", localtime(&seconds)); + PC.printf("RTC: %s, CNT1: %7d CNT2: %7d\n",Text, Count1, Count2); + } + - return; } //--------------------------------------------------------------------------- -void CNT1_count(void) -{ //function to call upon interrupt - CNT1++; //increment counter object +// 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; } //--------------------------------------------------------------------------- -void CNT2_count(void) -{ //function to call upon interrupt - CNT2++; //increment counter object +//Write to 74HC595 (LEDs) - Take care to avoid conflict with MAX7219 + +void LEDs_write(unsigned short data_val) +{ + // Update 74HC595 shift registers + unsigned short mask; + + SCK = 0; + wait_us(DT); + CS2 = 0; + + for(mask = 0x80; mask!= 0; mask>>= 1) + { + wait_us(DT); + SCK = 0; + if(mask & data_val) + MOSI = 0; + else + MOSI = 1; + wait_us(DT); + SCK = 1; + } + + SCK = 0; + wait_us(DT); + CS2 = 1; + 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 -------------- +//============================================================================== + + +