Blog Image


About the blog

In this blog I will keep track of projects I develop though out this year and may be in the future. For now it is juts a testing ground for developing the blog itself but I hope as I put more material it will become a good place for me to hold information.

Simple NMEA Parsing

C/C++ Programming Posted on 05 Apr, 2023 13:39:58
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>

std::string GetFieldId(std::string sentenceId, int fieldIndex)
    // Combine the sentence ID and field index to create the field ID
    std::ostringstream oss;
    oss << sentenceId << "-" << fieldIndex;
    return oss.str();

std::vector<std::string> SplitString(std::string str, char delimiter)
    std::vector<std::string> parts;
    std::stringstream ss(str);
    std::string part;
    while (std::getline(ss, part, delimiter)) {
    return parts;

std::map<std::string, std::string> ParseNmeaString(std::string nmeaString)
    std::map<std::string, std::string> components;
    if (nmeaString.length() < 7 || nmeaString[0] != '$' || nmeaString[nmeaString.length()-3] != '*') {
        return components;
    std::string sentence = nmeaString.substr(1, nmeaString.length()-4);
    std::string checksum = nmeaString.substr(nmeaString.length()-2, 2);
    std::vector<std::string> parts = SplitString(sentence, ',');
    std::string sentenceId = parts[0];
    for (int i = 1; i < parts.size(); i++) {
        components[GetFieldId(sentenceId, i)] = parts[i];
    return components;

int main()
    std::string sentence = "$GPGGA,092750.000,5321.6802,N,00630.3372,W,1,8,1.03,61.7,M,55.2,M,,*76";
    std::map<std::string, std::string> components = ParseNmeaString(sentence);

    // Print the components to the console
    for (auto const& component : components) {
        std::cout << component.first << ": " << component.second << std::endl;
    return 0;

On Mouse Leave MFC

C/C++ Programming, MFC Posted on 18 Feb, 2023 09:57:18

simple article about how to use ON_WM_MOUSELEAVE leave on a button.

The button has to track the mouse while moues move (ON_WM_MOUSEMOVE) is called.

void CMYButton::OnMouseMove(UINT nFlags, CPoint point)

if (!m_bTracking)
    tme.cbSize = sizeof(tme);
    tme.hwndTrack = m_hWnd;
    tme.dwFlags = TME_LEAVE|TME_HOVER;
    tme.dwHoverTime = 1;

    m_bTracking = _TrackMouseEvent(&tme);
    m_point = point;

LRESULT CMYButton::OnMouseHover(WPARAM wparam, LPARAM lparam)
    return m_bTracking;

LRESULT CMYButton::OnMouseLeave(WPARAM wparam,LPARAM lparam)
    m_bTracking = FALSE;
    return 0;



Arduino, C/C++ Programming Posted on 19 Jul, 2022 22:01:48
//----------------------Screen Bits
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// The pins for I2C are defined by the Wire-library. 
// On an arduino UNO:       A4(SDA), A5(SCL)
// On an arduino MEGA 2560: 20(SDA), 21(SCL)
// On an arduino LEONARDO:   2(SDA),  3(SCL), ...
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

void InitDisp(void)
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever

  // Show initial display buffer contents on the screen --
  // the library initializes this with an Adafruit splash screen.
  // display.display();
  // delay(2000); // Pause for 2 seconds

  // Clear the buffer

void DisplayTemp(float cel)

  display.setTextSize(2);      // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE); // Draw white text
  display.setCursor(0, 0);     // Start at top-left corner
  display.cp437(true);         // Use full 256 char 'Code Page 437' font

  // Not all the characters will fit on the display. This is normal.
  // Library will draw what it can and the rest will be clipped.
  char buf[256];
  int integerPart = (int)cel;
  int decimalPart = ((int)(cel*100)%100);
  sprintf(buf, "Temp:%d.%d", (int)cel, decimalPart);
  for(int16_t i=0; i<strlen(buf); i++) {

//---------------------- Temperature Sensor
#include <OneWire.h>
OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)
byte g_addr[8];
byte g_type_s;
void InitTemp(void)
  if ( ! {
    Serial.println("No addresse.");

  Serial.print("ROM =");
  for(int i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(g_addr[i], HEX);

  if (OneWire::crc8(g_addr, 7) != g_addr[7]) {
      Serial.println("CRC is not valid!");
  // the first ROM byte indicates which chip
  switch (g_addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS18S20");  // or old DS1820
      g_type_s = 1;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      g_type_s = 0;
    case 0x22:
      Serial.println("  Chip = DS1822");
      g_type_s = 0;
      Serial.println("Device is not a DS18x20 family device.");
//--------------------- Digital pins
const char SW1 = 2;

//---------------------- PROGRAM
void setup(void) {

  pinMode( SW1, OUTPUT);
  digitalWrite(SW1, LOW);


void loop(void) {
  byte i;
  byte present = 0;
  byte data[12];
  float celsius, fahrenheit;
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end
  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  present = ds.reset();;    
  ds.write(0xBE);         // Read Scratchpad

  Serial.print("  Data = ");
  Serial.print(present, HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] =;
    Serial.print(data[i], HEX);
    Serial.print(" ");
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (g_type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("  Temperature = ");
  Serial.print(" Celsius, ");
  Serial.println(" Fahrenheit");

  // Do something with the temperature.
  if (celsius <= 21)
    digitalWrite(SW1, LOW);
  else if (celsius > 21)
    digitalWrite(SW1, HIGH);

  // Display temperature

Sharing serial ports

C/C++ Programming, Linux Posted on 22 Mar, 2022 21:15:39

To share one serial port among a number of programs. Use socat to create some virtual ports to which the software are going to connect and then use the software below to organize the data flow.

Socat command to create interconnected virtual ports:

socat -d -d pty,raw,link=/home/user/serialThreeA,echo=0 pty,raw,link=/home/user/serialThreeB,echo=0

Source code of the data flow software:

// C library headers
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// Linux headers
#include <fcntl.h> // Contains file controls like O_RDWR
#include <errno.h> // Error integer and strerror() function
#include <termios.h> // Contains POSIX terminal control definitions
#include <unistd.h> // write(), read(), close()
#include <stdbool.h>
#include <pthread.h>

bool open_serial( char* serialport, int* serial_port)
    if (serialport == NULL)
        return 1;

    (*serial_port) = open( serialport, O_RDWR);

    // Create new termios struct, we call it 'tty' for convention
    struct termios tty;
    // Read in existing settings, and handle any error
    if(tcgetattr((*serial_port), &tty) != 0) {
        printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
        return 1;
    tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity (most common)
    tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication (most common)
    tty.c_cflag &= ~CSIZE; // Clear all bits that set the data size 
    tty.c_cflag |= CS8; // 8 bits per byte (most common)
    tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common)
    tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1)

    tty.c_lflag &= ~ICANON;
    tty.c_lflag &= ~ECHO; // Disable echo
    tty.c_lflag &= ~ECHOE; // Disable erasure
    tty.c_lflag &= ~ECHONL; // Disable new-line echo
    tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
    tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes

    tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
    tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
    // tty.c_oflag &= ~OXTABS; // Prevent conversion of tabs to spaces (NOT PRESENT ON LINUX)
    // tty.c_oflag &= ~ONOEOT; // Prevent removal of C-d chars (0x004) in output (NOT PRESENT ON LINUX)
    tty.c_cc[VTIME] = 10;    // Wait for up to 1s (10 deciseconds), returning as soon as any data is received.
    tty.c_cc[VMIN] = 0;

    // Set in/out baud rate to be 9600
    cfsetispeed(&tty, B9600);
    cfsetospeed(&tty, B9600);

    // Save tty settings, also checking for error
    if (tcsetattr((*serial_port), TCSANOW, &tty) != 0) {
        printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
        return 1;
    return 0;

int serial_port_one, serial_port_two, serial_port_three;

void *thread_one(void *vargp)
    while (true){
        char read_buf [256];
        int num_bytes = read(serial_port_one, &read_buf, sizeof(read_buf));
        if (num_bytes > 0){
            write(serial_port_two, read_buf, num_bytes);
            write(serial_port_three, read_buf, num_bytes);
    return NULL;

void *thread_two(void *vargp)
    while (true){
        char read_buf [256];
        int num_bytes = read(serial_port_two, &read_buf, sizeof(read_buf));
        if (num_bytes > 0){
            write(serial_port_one, read_buf, num_bytes);
    return NULL;

void *thread_three(void *vargp)
    while (true){
        char read_buf [256];
        int num_bytes = read(serial_port_three, &read_buf, sizeof(read_buf));
        if (num_bytes > 0){
            write(serial_port_one, read_buf, num_bytes);
    return NULL;

int main(int argc, char* argv[]) {
    pthread_t threadone, threadtwo, threadthree;
  // Open the serial port. Change device path as needed (currently set to an standard FTDI USB-UART cable type device)
  //int serial_port_one;
    if (open_serial(argv[1], &serial_port_one) != EXIT_SUCCESS)
        return 1;

    if (open_serial(argv[2], &serial_port_two) != EXIT_SUCCESS)
        return 1;
    if (open_serial(argv[3], &serial_port_three) != EXIT_SUCCESS)
        return 1;

    pthread_create(&threadone, NULL, thread_one, NULL);
    pthread_create(&threadtwo, NULL, thread_two, NULL);
    pthread_create(&threadthree, NULL, thread_three, NULL);
    pthread_join(threadone, NULL);
    pthread_join(threadtwo, NULL);
    pthread_join(threadthree, NULL);
    /*// Write to serial port
    unsigned char msg[] = { 'H', 'e', 'l', 'l', 'o', '\r' };
    write(serial_port_one, msg, sizeof(msg));

    // Allocate memory for read buffer, set size according to your needs
    char read_buf [256];

    // Normally you wouldn't do this memset() call, but since we will just receive
    // ASCII data for this example, we'll set everything to 0 so we can
    // call printf() easily.
    memset(&read_buf, '\0', sizeof(read_buf));

    // Read bytes. The behaviour of read() (e.g. does it block?,
    // how long does it block for?) depends on the configuration
    // settings above, specifically VMIN and VTIME
    int num_bytes = read(serial_port_one, &read_buf, sizeof(read_buf));

    // n is the number of bytes read. n may be 0 if no bytes were received, and can also be -1 to signal an error.
    if (num_bytes < 0) {
        printf("Error reading: %s", strerror(errno));
        return 1;

    // Here we assume we received ASCII data, but you might be sending raw bytes (in that case, don't try and
    // print it to the screen like this!)
    printf("Read %i bytes. Received message: %s", num_bytes, read_buf);

    return 0; // success

Cross Compiling From Linux to Raspberry PI

C/C++ Programming, Linux, Pi Stuff Posted on 11 Jan, 2022 20:34:02


Before you start you need to make sure the following is installed:

apt-get install git rsync cmake libc6-i386 lib32z1 lib32stdc++6

Let’s cross compile a Pie!

Start with making a folder in your home directory called raspberrypi.

Go in to this folder and pull down the ENTIRE tools folder you mentioned above:

git clone

You wanted to use the following of the 3 ones, gcc-linaro-arm-linux-gnueabihf-raspbian, if I did not read wrong.

Go into your home directory and add:

export PATH=$PATH:$HOME/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin

to the end of the file named ~/.bashrc

Now you can either log out and log back in (i.e. restart your terminal session), or run . ~/.bashrc in your terminal to pick up the PATH addition in your current terminal session.

Now, verify that you can access the compiler arm-linux-gnueabihf-gcc -v. You should get something like this:

Using built-in specs. COLLECT_GCC=arm-linux-gnueabihf-gcc COLLECT_LTO_WRAPPER=/home/tudhalyas/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/../libexec/gcc/arm-linux-gnueabihf/4.7.2/lto-wrapper Target: arm-linux-gnueabihf Configured with: /cbuild/slaves/oort61/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.b uild/src/gcc-linaro-4.7-2012.08/configure –build=i686-build_pc-linux-gnu –host=i686-build_pc- linux-gnu –target=arm-linux-gnueabihf –prefix=/cbuild/slaves/oort61/crosstool-ng/builds/arm-l inux-gnueabihf-raspbian-linux/install –with-sysroot=/cbuild/slaves/oort61/crosstool-ng/builds/ arm-linux-gnueabihf-raspbian-linux/install/arm-linux-gnueabihf/libc –enable-languages=c,c++,fo rtran –disable-multilib –with-arch=armv6 –with-tune=arm1176jz-s –with-fpu=vfp –with-float= hard –with-pkgversion=’crosstool-NG linaro-1.13.1+bzr2458 – Linaro GCC 2012.08′ –with-bugurl= –enable-__cxa_atexit –enable-libmudflap –enable-libgom p –enable-libssp –with-gmp=/cbuild/slaves/oort61/crosstool-ng/builds/arm-linux-gnueabihf-rasp bian-linux/.build/arm-linux-gnueabihf/build/static –with-mpfr=/cbuild/slaves/oort61/crosstool- ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux-gnueabihf/build/static –with-mpc =/cbuild/slaves/oort61/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux- gnueabihf/build/static –with-ppl=/cbuild/slaves/oort61/crosstool-ng/builds/arm-linux-gnueabihf -raspbian-linux/.build/arm-linux-gnueabihf/build/static –with-cloog=/cbuild/slaves/oort61/cros stool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux-gnueabihf/build/static –wi th-libelf=/cbuild/slaves/oort61/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/a rm-linux-gnueabihf/build/static –with-host-libstdcxx=’-L/cbuild/slaves/oort61/crosstool-ng/bui lds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux-gnueabihf/build/static/lib -lpwl’ –ena ble-threads=posix –disable-libstdcxx-pch –enable-linker-build-id –enable-plugin –enable-gol d –with-local-prefix=/cbuild/slaves/oort61/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-li nux/install/arm-linux-gnueabihf/libc –enable-c99 –enable-long-long Thread model: posix gcc version 4.7.2 20120731 (prerelease) (crosstool-NG linaro-1.13.1+bzr2458 – Linaro GCC 2012.08 )

But hey! I did that and the libs still don’t work!

We’re not done yet! So far, we’ve only done the basics.

In your raspberrypi folder, make a folder called rootfs.

Now you need to copy the entire /liband /usr directory to this newly created folder. I usually bring the rpi image up and copy it via rsync:

rsync -rl –delete-after –safe-links pi@192.168.1.PI:/{lib,usr} $HOME/raspberrypi/rootfs

where 192.168.1.PI is replaced by the IP of your Raspberry Pi.

Now, we need to write a cmake config file. Open ~/home/raspberrypi/pi.cmake in your favorite editor and insert the following:

SET(CMAKE_SYSTEM_NAME Linux) SET(CMAKE_SYSTEM_VERSION 1) SET(CMAKE_C_COMPILER $ENV{HOME}/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-gcc) SET(CMAKE_CXX_COMPILER $ENV{HOME}/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++) SET(CMAKE_FIND_ROOT_PATH $ENV{HOME}/raspberrypi/rootfs) SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

Now you should be able to compile your cmake programs simply by adding this extra flag: -D CMAKE_TOOLCHAIN_FILE=$HOME/raspberrypi/pi.cmake.

Using a cmake hello world example:

git clone cd cmake-hello-world mkdir build cd build cmake -D CMAKE_TOOLCHAIN_FILE=$HOME/raspberrypi/pi.cmake ../ make scp CMakeHelloWorld pi@192.168.1.PI:/home/pi/ ssh pi@192.168.1.PI ./CMakeHelloWorld

I have taken the above from stackoverflow:

I did not managed to get the cmake to work as the pkg-config seem to have problems identifying where the libraries are and it was adding my libraries from teh host computer rather than the target ones. But following the same instructions it did worked fine when making my own call to the compiler and adding all the paths and libraries manually to the command.

Parsing results of a command line

C/C++ Programming, Linux Posted on 12 Nov, 2021 15:06:09
#include <iostream>
#include <stdexcept>
#include <stdio.h>
#include <string>

using namespace std;

string exec(string command) {
   char buffer[128];
   string result = "";

   // Open pipe to file
   FILE* pipe = popen(command.c_str(), "r");
   if (!pipe) {
      return "popen failed!";

   // read till end of process:
   while (!feof(pipe)) {

      // use buffer to read and add to result
      if (fgets(buffer, 128, pipe) != NULL)
         result += buffer;

   return result;

int main() {
   string ls = exec("ls");
   cout << ls;

Taken from:

OpenGL Things

C/C++ Programming Posted on 23 Aug, 2021 09:12:33

Nice tutorials on modern OpenGL version 3:

Email sending with libcurl

C/C++ Programming Posted on 23 Aug, 2021 09:00:24

Next »