codebite _

Light at the end of the tunnel

Mon 03 of February, 2020

Or how to bring some light to a nerd doomer

So I spent my weekend finally finishing the hardware part of my LED strip desk light thing. It all started with a note on my (based) Nextcloud instance:

Although most of it is about software, the idea can be described by first 3 points.

From there I experimented on a breadboard, and left it at that for a long time, until recently. I took out an old ATX PSU and did some tests. Measured dimensions, and read about my MCU of choice (ESP8266).

So after all that i ordered some parts, and then sat down and drew a schematic:

When the parts arrived I drilled and assembled the case to figure out how much space I have to play with.

And got to work on soldering it all.

And in the end I stuffed it all inside and soldered some more. And yes, I know I put wires on top of Wi-Fi antenna, Thug life, get over it.

After a i bit of whoopsie with the logic levels, it was done.

So now only two things left:

  1. Code the firmware
  2. Mount it.

I am still not sure if I want to over-complicate it with MQTT and OpenHAB, might just do a REST thing over HTTPS.

I'll do the software and mounting write up next.

#include "this.h"

Tue 08 of October, 2019

So, I work with a couple of Python developers, and they really like their Pythonic way. Which is fine, it has many good ideas, but they keep making import this jokes, and I just had to do one for C. And, well, here we are.

First, let's just see it in action.

// main.c
#include "this.h"


int main(int argc, char** argv)
{
    (void)argc;
    (void)argv;

    return 0;
}

The first ingredient is our regular C source file. It's just a main function that does nothing. The 2nd one, is our secret sauce, we will discuss it later. And of course, the final ingredient, the C compiler, I'll use gcc.

So, let's compile and run it:

$ gcc -Wall -Wextra -pedantic main.c -o main
$ ./main
The Zen of C, by redgek

Code is better than cliché guidelines.
Working code is better than cute, but broken one.
Simple is better than complex, complex is better than broken.
Simple is not necessarily easy.
Zero cost abstractions is lack of abstractions.
Crash often.
There are usually multiple ways to do it.
Especially if it's multi-platform.
Avoid undefined behavior.
Know your tools, understand your platform.
Code, profile, optimize. In that order.
If the implementation is hard to explain, it may be a bad idea.
Or it may be hard to explain.
Delete more code than you write.

Magic, ain't it? :) Well, needless to say the magic is in the this.h file. So let's inspect it.

// this.h
#ifndef THIS_H
#define THIS_H

#include <stdio.h>


#define main                                                                 \
    __dummy(void) {return 0;}                                                \
    int __user_main(int, char**);                                            \
    int main(int argc, char** argv)                                          \
    {                                                                        \
        printf("The Zen of C, by redgek\n"                                   \
          "\n"                                                               \
          "Code is better than cliché guidelines.\n"                         \
          "Working code is better than cute, but broken one.\n"              \
          "Simple is better than complex, complex is better than broken.\n"  \
          "Simple is not necessarily easy.\n"                                \
          "Zero cost abstractions is lack of abstractions.\n"                \
          "Crash often.\n"                                                   \
          "There are usually multiple ways to do it.\n"                      \
          "Especially if it's multi-platform.\n"                             \
          "Avoid undefined behavior.\n"                                      \
          "Know your tools, understand your platform.\n"                     \
          "Code, profile, optimize. In that order.\n"                        \
          "If the implementation is hard to explain, it may be a bad idea.\n"\
          "Or it may be hard to explain.\n"                                  \
          "Delete more code than you write.\n"                               \
          );                                                                 \
        return __user_main(argc, argv);                                      \
    }                                                                        \
    int __user_main

#endif // THIS_H

This is the secret sauce. What it does is replaces any symbol main (which is usually your program entry) with this mess. First part is __dummy(void) {return 0;}, it simply closes the int that we assume comes before main. After that, it declares a function __user_main that has the same signature as regular main. Then, we actually declare and define actual main function, we print our little joke-ish Zen, call __user_main function with arguments from the shell and return whatever it returns. And finally, at the end, we simply start the actual definition of __user_main, as we expect the user's main implementation after this.

Let's see the output of C preprocessor, ignoring the stdio.h stuff:

$ cpp main.c
# 1 "main.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "main.c"
# 1 "this.h" 1

// tons of stdio.h stuff...

# 5 "this.h" 2
# 2 "main.c" 2

# 4 "main.c"
int __dummy(void) {return 0;} int __user_main(int, char**); int main(int argc, char** argv) { printf("The Zen of C, by redgek\n" "\n" "Code is better than cliché guidelines.\n" "Working code is better than cute, but broken one.\n" "Simple is better than complex, complex is better than broken.\n" "Simple is not necessarily easy.\n" "Zero cost abstractions is lack of abstractions.\n" "Crash often.\n" "There are usually multiple ways to do it.\n" "Especially if it's multi-platform.\n" "Avoid undefined behavior.\n" "Know your tools, understand your platform.\n" "Code, profile, optimize. In that order.\n" "If the implementation is hard to explain, it may be a bad idea.\n" "Or it may be hard to explain.\n" "Delete more code than you write.\n" ); return __user_main(argc, argv); } int __user_main(int argc, char** argv)
{
    (void)argc;
    (void)argv;

    return 0;
}

If we just massage the code to make it bit more readable, since all of it is on the same line, plus remove all the cpp stuff. We get:

// stdio.h stuff...

int __dummy(void) {return 0;}
int __user_main(int, char**);

int main(int argc, char** argv)
{
    printf("The Zen of C, by redgek\n"
           "\n"
           "Code is better than cliché guidelines.\n"
           "Working code is better than cute, but broken one.\n"
           "Simple is better than complex, complex is better than broken.\n"
           "Simple is not necessarily easy.\n"
           "Zero cost abstractions is lack of abstractions.\n"
           "Crash often.\n"
           "There are usually multiple ways to do it.\n"
           "Especially if it's multi-platform.\n"
           "Avoid undefined behavior.\n"
           "Know your tools, understand your platform.\n"
           "Code, profile, optimize. In that order.\n"
           "If the implementation is hard to explain, it may be a bad idea.\n"
           "Or it may be hard to explain.\n"
           "Delete more code than you write.\n");

           return __user_main(argc, argv);
}

int __user_main(int argc, char** argv)
{
    (void)argc;
    (void)argv;

    return 0;
}

And I think, that's pretty self-explanatory if you know C. Needless to say, this has a lot of issues. It works only assuming you include it in the file that contains main function, and that its signature is int (*)(int, char**), which is not always true. So this is just a toy to generate a bit of airflow through some nostrils of a few programmers.

Have a nice one!

Getting into Hardware

Mon 08 of April, 2019

You know I like software. I like making it, but you can't hold software in your hands, and I always wanted to make something that I can hold in my hands.

So what's this all about? Well, I finally got into some hardware, and I decided to write a little update about that.

Recently I made a small hardware hacking station for myself, it's nothing much, just a soldering iron, a hot glue gun, a multimeter, and a bunch of parts.

My coworker gave me a quick lesson in soldering, and I watched few more videos online, and then just did some practice runs. It was fun!

So naturally next up is to make something more or less useful, for that is my desk lighting. I want it to change colors like redshift does. So I thought about using arduino, but decided to go with ESP8266 so I can also control it with my phone.

Instead of ready made ESP8266 devboard, I decided to make my own, so I can practice more. I used KiCAD to make a schematic and then just went at it.

So next up is to jig something up to drive my LED strip with the ESP (Since the LED strip works at 5V, and ESP at 3.3V). I bought some BJTs and MOSFETs, so that is probably what I am going to use.

My other hardware project is to use old ATX PSU as a lab power supply. It's not going to variable or anything, just 3 rails (3.3, 5, and 12 volts), but should be enough for me.

Anyways, that's about it for this small update.


Been some time, eh? Well, I'll try to get back into blogging bit more. ;)

More posts...