Skip to content

cnlohr/cnlohr_tricks

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 

Repository files navigation

Some tricks I've found over time

The contents of this readme is public domain where possible. And if licensing is required, it may be licensed under the MIT, NewBSD, ISC, Zlib, MIT0 or CC0 licenses.

Useful single-file header libraries

Included are the URLs directly to the headers themselves. You can "Copy Link Location" then wget or curl it into where you need it.

Single-file-header only libraries are intended to make it easy to add funcitonality to a C project without extra build steps and most of the time come with zero dependencies.

The pattern is typically:

In one .c file in your project:

#define PACKAGE_IMPLEMENTATION
#include "package.h"

If you need the header file to use it in other .c files in your project, just include the package, directly.

#include "package.h"

Note that some header-only libraries are actually .c files. But that's ok, you can just #include the c file in your code.

Name/Package/Page Description File/URL
stb Easily write .bmp, .png, .tga, .jpeg files from C stb_image_write.h
stb Load .ttf files and get raster pixel data stb_truetype.h
stb Load .png, .pnm, .jpg, .bmp, .psd, .tga, .gif, .hdr, and .pic files stb_truetype.h
olive.c Tiny graphics library for working on pixel buffers olive.c

Single-file headers I wrote:

Name/Package/Page Description File/URL
rawdraw Window / opengl context creation, input management on many platforms (like SDL but 1/1000th the size) good for Android, Linux, Windows, Web rawdraw_sf.h
hufftreegen_sf Create huffman trees of bitstreams, and the means to decode them hufftreegen.h
cnrbtree Arbitrary header-only (with macro magic) red-black tree cnrbtree.h
cnhash C Hash table/map implementation cnrbtree.h
mini-rv32ima Header-only RISC-V Emulator capable of booting nommu linux mini-rv32ima.h
heatshrink-sfh Very stripped down implementation of the heatshrink LVSS decompression algorithm heatshrink_sf.h
rtgz-tinf-util Custom deflate decompressor, and custom compressor for targeting tiny decode windows tinf_sf.h
csgp4 SGP4 Orbital Mechanics Header-Only file (portable to HLSL) for computing satellite positions at times csgp4.h

Embedded / C

Fast Approximate Integer Square Root

First, get the approximate square root from the next power-of-2, then refine it.

int apsqrt( int i )
{
	if( i == 0 ) return 0;
	int x = 1<<( ( 32 - __builtin_clz(i) )/2);
	x = (x + i/x)/2;
//	x = (x + i/x)/2; //Not really needed.
	return x;
}

apsqrt

Fast Binary-Shift (no-multiply) IIR filter

If you need an IIR to compute a high or low-pass filter on your data, here is a solution that gives it to you with just a "running average" state.

This is an IIR filter, which means that as time goes on old values matter less and less.

You will need to tune IIR_AMOUNT to your liking, higher values will be more damped, lower values will be faster to respond.

For removing DC offset, or computing high-pass, take your value, and subtract the filtered value.

	#define IIR_AMOUNT 8
	static int ifilt; // Accumulates the average.

	// Note, the ifilt average will be (1<<IIR_AMOUNT)*average, so
	// if IIR_AMOUNT is 8 and you are using values > 255, and ifilt
	// is a uint16_t, then, it will OVERFLOW.

	int v = rand() % 1000;
	ifilt = ifilt + v - (ifilt>>IIR_AMOUNT);


	int filtered_value = ifilt>>IIR_AMOUNT;

ifilt

Goertzel's sinewave / DFT.

A lot of times, you will want to use a sinewave, or need to do DFT for specific tone.

And sin/cos may not be fast. Well, good news, goertzels is to the rescue. You can generate a sin/cos without any sin or cos!

#include <stdio.h>
#include <math.h>

int main()
{
	const float omegaPerSample = 0.015708; // pi / 200
	const int numSamples = 400; // enough to go from 0 to 2pi

	float coeff = 2 * cos( omegaPerSample );
	int i;

	// TRICKY: When you want a sinewave, initialize with omegaPerSample.  This
	// is crucial.  The initial state will have massive consequences.
	float sprev = omegaPerSample;
	float sprev2 = 0;
	for( i = 0; i < numSamples; i++ )
	{
		float s = coeff * sprev - sprev2; // Here is where the magic happens.
		sprev2 = sprev;
		sprev = s;
		printf( "%f\n", s ); 
	}
}

goertzels

Linux

My program segfaulted, why?

Use the following command:

coredumpctl gdb
bt

To get a backtrace of the most recently crashed program.

How to make system calls in C, when programming without a standard library.

You have to make a syscall, but you can use inline assembly to wrap it so that it doesn't have to spend time/effort getting the registers setup correctly.

Be sure to compile with: gcc -Os -nostdlib -Wl,-e"start" -ffunction-sections -fdata-sections -flto -Wl,--gc-sections for optimal behavior, also set start to be your start function.

#include <asm/unistd.h>      // compile without -m32 for 64 bit call numbers

// In x86_64 only.


// call write( int fd, uint8_t ptr, int length )
asm volatile
(
    "syscall"
    : "=a" (ret)
    //                 EDI      RSI       RDX
    : "0"(__NR_write), "D"(/*fd*/fd), "S"(ptr), "d"(length)
    : "rcx", "r11", "memory"
);

Lastly don't forget to exit!

asm volatile
(
    "syscall"
    : "=a" (r)
    //                 EDI  
    : "0"(__NR_exit), "D"(/*fd*/0), "S"(0), "d"(0)
    : "memory"
);

About

CNLohr's embedded tricks repository/readme

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published