Tag Archives: programming

Busy .. work and play

While working on my clients projects, I’ve been busy with other Fun stuff.

All will be posted more about soon

  • Designing 3D models for printing
  • Testing Arduino Code for RS485!
  • Creating T-shirt prints using 3D printing and bleach/paint with Vincent !
  • Transforming my Lab
  • Testing UM25C logging possibilities
  • Testing queries on overpass-turbo.eu (So much fun)
  • Playing chiptune music using Synthcart + Midi
  • Made V2 displayer on my 64×64 HUB75 led display
  • Bought a directional Wi-Fi antenna, tweaking wireshark to pinpoint rogue access points and clients.

March stuff, being busy

Working for clients, so fragmented personal stuff.
New workplace setup so even more space!

My BBQ monitor V3

As posted before, but now an esphome version, with big-ass buzzer

Code available soon, when made generic.

4Button controller using ESPHOME

Code allready posted

STL FILE https://media.henriaanstoot.nl/4buttons.stl

Flash trick for XYUSB

Flashing this to ESPHOME, use sowing pins!

CODE

substitutions:
  name: usb-relay
  friendly_name: "USB Relay"
  default_state: "RESTORE_DEFAULT_OFF"


esphome:
  name: xyusb1
  friendly_name: xyusb1

esp8266:
  board: esp01_1m

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "ndm8xxxxxxxxxxxxxxxxxjlvrggJv3a1BkY="

ota:
  - platform: esphome
    password: "12cc9xxxxxxxxxxxxxxxxfb6a01e672"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Xyusb1 Fallback Hotspot"
    password: "xxxxxxxxxxx"

captive_portal:

time:
  - platform: homeassistant

# Blue LED
status_led:
  pin:
    number: GPIO16

# Relay
switch:
  - platform: gpio
    id: switch_relay
    pin: GPIO5

  # Green LED
  - platform: gpio
    pin: GPIO14
    id: green_led
    inverted: true # start on

  # Switch template to link relay and green LED states
  # LED is on when relay is off
  - platform: template
    id: relay
    name: "${friendly_name}"
    lambda: |-
      if (id(switch_relay).state) {
        return true;
      } else {
        return false;
      }
    turn_on_action:
        - switch.turn_on:
            id: green_led
        - switch.turn_on:
            id: switch_relay
    turn_off_action:
        - switch.turn_off:
            id: green_led
        - switch.turn_off:
            id: switch_relay

# Button
binary_sensor:
  - platform: gpio
    id: hardware_button
    pin:
      number: GPIO04
      mode: INPUT_PULLUP
      inverted: True
    on_press:
      - switch.toggle: relay

# WiFi Signal Sensor
sensor:
  - platform: wifi_signal
    name: "WiFi Status"
    update_interval: 60s

# Restart button
button:
  - platform: restart
    name: "Restart"

Reflashed my USB Volume button and added a LED-Ring.

Example is green and blue.

Funny text on box

What is a termianl assortment? LOL

Wireless Temperature/Humidity sensor for ESPHome.

Wemos D1 mini with deep sleep, voltage monitoring using A0 line.
BME280 Temperature/Humidity sensor.
And a 18650 battery with TP4065 battery manager.
Now 3D print a little case.

Made a PCB for a 24 Channel Logic analyzer

See post:

Better thumb thingy for short movie clips

(Improvement of previous posted script)

Place below bash script in a subdir with media.

Animated GIFs are generated from the video files.
You can set the number of frames per length

#!/bin/bash
#set -x
mkdir -p tmp prev
: > list
: > index.html
find ../ -type f -print | egrep -i "mp4$|wmv$|avi$|mpg$|mpeg$|flv$|mov$|divx$"  > list

cat list | while read movie; do 
	rm -f tmp/*
	newname=$( echo $movie | tr -d ' /.[]{}()' ) 
	if [ ! -f prev/${newname}.gif ] ; then

		echo "Filename : $movie"

		kseconds=$( mediainfo --Inform="Video;%Duration%"  "$movie" )
		minutes=$(( $kseconds / 60000 ))
		echo "Minutes : $minutes"
		if [ $minutes -gt 10 ] ; then 
			rate=0.032
		else
			rate=0.128
		fi
echo "ffmpeg -hide_banner -loglevel error -i $movie -r $rate  -vf scale=640:-1 tmp/output_%04d.png"
		ffmpeg -hide_banner -loglevel error -i "$movie" -r $rate  -vf scale=640:-1 tmp/output_%04d.png < /dev/null
		# remove first (most of the time just black or logo)
		rm tmp/output_0001.png
		echo -n "Frames : "
		ls tmp/out* | wc -l
		convert -delay 50 -loop 0  tmp/output*.png prev/${newname}.gif
	else
		echo "$movie exists ... skipping"
	fi
	echo "<h1>${movie}</h1><br>" >> index.html
	echo "<img src=\"prev/${newname}.gif\"><br>" >> index.html
done
exit 0

run and get something like below (output is still running as I made this post)

Display work

While working on a client project, I tested multiple displays.

  • ILI9341
  • 1.3inch SPI TFT LCD Display RGB (ST7789)
  • Waveshare 4.2 Epaper with ESP32 Controller

I thought it was fun to connect the Epaper to ESPHome.

This probably ends up being a Quote displayer
Universal e-Paper Driver Board with WiFi / Bluetooth SoC ESP32 onboard, supports various Waveshare SPI e-Paper raw panels

It was not without problems. For example, the ESPHome editor gave squiggly lines under type.
This has to be changed in the libraries.
(Already notified developers)

model: 4.20in-V2 does not work .. use model: 4.20in-v2

esphome:
  name: epaperqoute
  friendly_name: epaperqoute

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "tzRSzZky3Jk+hUYtiybzT90kxxxxxxxxxxxxxxxxxxxxx="

ota:
  - platform: esphome
    password: "4f127e114a7a44fxxxxxxxxxxxxxxxxxxxxx"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Epaperqoute Fallback Hotspot"
    password: "yLSoxxxxxxxxxx"

captive_portal:


external_components:
  - source: github://pr#6209
    components: [ waveshare_epaper ]

text_sensor:
  - platform: homeassistant
    entity_id: input_text.epaper_display_text
    id: epaper_display_text
    on_value:
      then:
        - component.update: epaperdisplay
    
spi:
  clk_pin: GPIO13
  mosi_pin: GPIO14

# Upload own ttf to a directory in esphome/fonts using file editor in Home Assistant
font:
  - file: "fonts/newspaper.ttf"
    id: tahoma
    size: 64

http_request:
  verify_ssl: false

# image test
online_image:
  - url: "https://www.henriaanstoot.nl/epapertest.png"
    id: example_image
    format: PNG

#it.image(0, 0, id(example_image));

display:
  - platform: waveshare_epaper
    id: epaperdisplay
    cs_pin: GPIO15
    dc_pin: GPIO27
    busy_pin: GPIO25
    reset_pin: GPIO26
    model: 4.20in-v2
    reset_duration: 200ms
    update_interval: never
    lambda: |
           it.printf(0, 0, id(tahoma), "%s", id(epaper_display_text).state.c_str());  

Webcam plus OpenCV fun

While attending Bornhack 2024 in Danmark, I came up with the below fun ideas.

Using Python and OpenCV, I made some funny webcam hacks.

Note: My laptop webcam is very bad, a better webcam should give you a more stable result.

First, a virtual workspace flipper. Just using my head movement to flip through my virtual desktops. (Turning left and right)

Next, an image viewer.
Using your head movement up, down, left and right to control the image.
Note : this is not the same movement as above. This won’t use rotation of your head!

Working on a demo part

Started coding a demo with a friend of mine.

I made a part that uses raster interrupts and gives the illusion that the picture is up in the border.

  • Opening the borders
  • Changing the border colour midway
  • Using NOPs to get a stable rastersplit
  • Sprites in the border
  • Fixing the sprite mirroring in the bottom part
  • Learning a lot about bad raster lines, I had to make a lot of workarounds to get it working

Hopefully I’ve got some rastertime left to play music. But I learned a lot!
UPDATE: Yes also with SID music!

Not shown: Bad raster lines, split colors background and bordercolor.
Maybe I’ll add these later.

UPDATE: 20240720

Sprite multiplexing done and self modifying code.

Keyboard switch part 1

Testing the first keyboard. It is the 8085-SDK hex matrix keyboard.

It is running on a Raspberry Pi Zero 2, without X server.
So the images are displayed using the framebuffer.
Also the touch data is read using evdev and the raw devices.

Todo:

  • HID part
  • Add a rotary button for the selection of the different Keyboard Layouts
  • Improvement keyboard matrix calculation to find out which key is being pressed.
  • Code to control AT/PS2 computers directly using GPIO pins
  • Add a controller to use Raw controlling of matrix pins ( 6502 C64 hardware for example )

Bash test and configuring the OS for testing.

cat <<EOF >> /boot/config.txt
hdmi_group=2
hdmi_mode=87
hdmi_timings=400 0 100 10 140 1280 10 20 20 2 0 0 0 60 0 43000000 3
display_rotate=3
EOF

# Image testing
apt-get install fbi
sudo fbi -d /dev/fb0 -T 1 8085.png  -a --noverbose

apt-get install python3-evdev python3-uinput evtest
evtest

First simple python test

import select
from math import floor
import sys
slot = 0

keysname=[["F","E","D","C","vect-int","reset"],
          ["B","A","9","8","GO","Single-Step"],
          ["7","6","5","4","Exam-reg","Subst-mem"],
          ["3","2","1","0","Exec","Next"],
          ]
keysnames=[["F","E","D","C","vect-int","reset"],
          ["B","A","L","H","GO","Single-Step"],
          ["PCL","PCH","SPL","SPH","Exam-reg","Subst-mem"],
          ["3","2","1","0",".",","],
          ]

for path in evdev.list_devices():
    device = evdev.InputDevice(path)
    if evdev.ecodes.EV_ABS in device.capabilities():
        break
else:
    sys.stderr.write('Failed to find the touchscreen.\n')
    sys.exit(1)

while True:
    r, w, x = select.select([device.fd], [], [])

    id_ = -1
    x = y = 0

    for event in device.read():

        if event.code == event.value == 0:
           if id_ != -1:
                yy = floor(( x - 600 ) / 700)
                xx = floor(( y - 1377 ) / 226)
                if yy < 4 and yy >=0 and xx < 6 and xx >= 00:
                     if slot == 1:
                         print(keysnames[yy][xx])
                     else:
                         print(keysname[yy][xx])

        elif event.code == ABS_MT_TRACKING_ID:
            id_ = event.value
        elif event.code == ABS_MT_SLOT:
            slot = event.value
        elif event.code == ABS_MT_POSITION_X:
            x = event.value
        elif event.code == ABS_MT_POSITION_Y:
            y = event.value

I came up with a simple matrix calculation

Pressing the 4 corner keys gave me x and y.
I took averages for min and max reading.
I don’t need pixel-perfect reading, and I noticed values between 960 and 3080 vertically.
We want 960 – 3080 into 4 blocks, but the middle should start @ 960.

So 3080/3 = about 700
700 / 2 = 350
block 1 starts 350 sooner than 960 is ~ 600
Upper key y coords = 600-> + 700
Next is 1300 -> + 700
converting to whole numbers using floor gives me:
floor(( y – 600 ) / 700)
NOTE: My x and y are rotated

Example using coordinates
1600, 1600
floor(( 1600 – 600 ) / 700) = floor(1,4…) = 1st row
(from row 0,1,2,3)

64×64 Etch a Sketch

In the past I made a Etch a Sketch with my lasercutter.

Using two rotary encoders and the 64×64 matrix display I recently bought, I made a drawing thingy.
Like a Etch a Sketch.

Some Circuit Python code.
Now I have to fix an out of memory issue using below.
And make a colour selection button??? 🙂

import time
import board
import displayio
import math
import vectorio
import rgbmatrix
import framebufferio
import array
import bitmaptools

import rotaryio
import board

encoder1 = rotaryio.IncrementalEncoder(board.GP27, board.GP26)
encoder2 = rotaryio.IncrementalEncoder(board.GP18, board.GP19)

last_position1 = 0
last_position2 = 0

# Release any existing displays
displayio.release_displays()

# --- Matrix Properties ---
DISPLAY_WIDTH = 64
DISPLAY_HEIGHT = 64

# --- Matrix setup ---
BIT_DEPTH = 2
matrix = rgbmatrix.RGBMatrix(
    width=64, bit_depth=2, height=64,
    rgb_pins=[board.GP0, board.GP1, board.GP2, board.GP3, board.GP4, board.GP5],
    addr_pins=[board.GP6, board.GP7, board.GP8, board.GP9, board.GP22],
    clock_pin=board.GP10, latch_pin=board.GP12, output_enable_pin=board.GP13)
colrs = 13
display = framebufferio.FramebufferDisplay(matrix, auto_refresh=True)
b1 = displayio.Bitmap(display.width, display.height, colrs )
palette = displayio.Palette(colrs )
palette[0] = 0x000000  # black
palette[1] = 0x964B00  # brown (light yellow) 
palette[2] = 0x00FFFF  # cyan
palette[3] = 0x850101  # deep red 
palette[4] = 0x7F00FF  # violet
palette[5] = 0xC46210  # orange
palette[6] = 0x3D9140  # Cobalt green  
palette[7] = 0x004225  # british racing green 
palette[8] = 0x8B008B  # dark magenta 
palette[9] = 0x1F75FE  # crayola  blue
palette[10] =0x00308F  # air force blue US air force    
palette[11] =0xBF00FF  # electric purple 
palette[12] =0x08E8DE  # turquoise
g1 = displayio.Group(scale=1)
display.root_group = g1 

bmp = displayio.Bitmap(64,64, 2)

tilegrid = displayio.TileGrid(bitmap=bmp, pixel_shader=palette)
g1.append(tilegrid)
display.auto_refresh = True

tilegrid = displayio.TileGrid(bitmap=bmp, pixel_shader=palette)
while True:
        position1 = encoder1.position
        if last_position1 is None or position1 != last_position1:

            if position1 > last_position1:
                position1 = position1 + 1
            if position1 < last_position1:
                position1 = position1 - 1
            if position1 < 0:
                position1 = 0
            last_position1 = position1
        position2 = encoder2.position
        if last_position2 is None or position2 != last_position2:
            if position2 > last_position2:
                position2 = position2 + 1
            if position2 > last_position2:
                position2 = position2 - 1
            if position2 < 0:
                position2 = 0
            last_position2 = position2

        bmp[position1,position2]=1
        tilegrid = displayio.TileGrid(bitmap=bmp, pixel_shader=palette)
        g1.append(tilegrid)
        display.auto_refresh = True

68000 SBC, C64 Git and SID Player

Working on 68000 Single Board Computer.

Made a clock circuit and busy designing a power-on-reset schematic. I’ve made one before, but this circuit needs RESET and HALT being pulled low.

8mhz 5V

The 68000 being 24 bit address and 16 bit data needs 2x 8-bit roms and 2x 8 bit ram, but i didn’t have the components yet in this picture.

Address decoder using ATF22V10C is also halfway.
Schematics online soon.

Started a protected Git repo for C64 demo and proof of concepts for our old ICECREW group.

Installed Gitea, behind a reverse proxy.
Part of reverse proxy

ProxyRequests Off
ProxyPreserveHost On
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off

<Location />
ProxyPass   http://10.x.y.z:3000/
ProxyPassReverse  http://10.x.y.z:3000/
Require ip 213.10.144.27
Require ip a.b.c.d
Require ip e.f.g.h
</Location>

Gitea config with token login over https

Generate token
Login https://icecrew.henriaanstoot.nl/

Select your profile (upper right)

And select Settings > Applications

Select a name for your token. And press generate

Top screen shows a token, copy this!

Create new project
Press explore (upper left)

Select organisation and icecrew

Press New Repository, give a name and create

(press https when not defaulted, there is NO ssh to this server)

The example is wrong! (Use below changing TOKENHERE and PROJECTNAME

touch README.md
git init -b master
git add README.md
git commit -m "first commit"
git remote add origin https://TOKENHERE@icecrew.henriaanstoot.nl/icecrew/PROJECTNAME.git
git push -u origin master

Clone a project
Goto a project

press HTTPS when not defaulted to this.

git clone https://icecrew.henriaanstoot.nl/icecrew/borderflag.git 

edit .git/config and add your token to the url ! to push

My Sidplayer as an option to select own collection.
And I’ve made a top list

# Best composers (no order)
Ouwehand_Reyn
Tel_Jeroen
Huelsbeck_Chris
Rowlands_Steve
Hubbard_Rob
Daglish_Ben
Follin_Tim
Gray_Matt
Tjelta_Geir
Mibri (from get in the Van)

# Best tunes (no order)
R-Type.sid
Arkanoid.sid
Bottom.sid
Turbo_Outrun.sid
A_Tune_for_Unity.sid
Ohne_Dich_Rammstein.sid

# Start of own collection (not in above collection)
Abyssus_Ignis_[8580].sid
Catastrophe_[8580].sid
Dumb_Terminal_[8580].sid
Get_in_the_Van_[8580].sid
Getting_in_the_Van_[8580].sid
Supercharger_[8580].sid
Tuna_Guitar_[8580].sid

Investigating syncing effect to Sid music.

I got a great tip from Youth who made the Freakandel demo presented at X2024.

> Setup the loop to play the music

> Copy part of the memory to the screen ($0400) in the same loop to look for memory locations that are used as variables for the music. > Looking at

> Memory where the music is stored

> Zeropage ($00-$ff)

> See if there's some useful changes that coincide with for example drums

> For my own tunes, I use a music routine where I can put event markers in the music itself and react to those from the code. That's >how I synced https://www.micheldebree.nl/posts/big_angry_sprite/

> You could also try reading the SID registers for voice 3 (waveform and ADSR), those are the only ones that are not write-only. > Obviously you can then only react to those changes in voice 3.

I used retrodebugger to see which bytes are changing.
Then I wrote a program which changes the background colour to this value.
I also made a program to use a joystick to see which address have the most interesting effect.
(use up)

     1                                       !to "sidbgnd.prg",cbm
     2                          
     3                                  * = $0801
     4                          			
     5                          sysline:	
     6  0801 0b0801009e323036...        !byte $0b,$08,$01,$00,$9e,$32,$30,$36,$31,$00,$00,$00 ;= SYS 2061
     7                          
     8                                  * = $080d 
     9                          
    10  080d 78                 	sei
    11  080e a960               	lda #<irq
    12  0810 a208               	ldx #>irq
    13  0812 8d1403             	sta $314
    14  0815 8e1503             	stx $315
    15  0818 a91b               	lda #$1b
    16  081a a200               	ldx #$00
    17  081c a07f               	ldy #$7f 
    18  081e 8d11d0             	sta $d011
    19  0821 8e12d0             	stx $d012
    20  0824 8c0ddc             	sty $dc0d
    21  0827 a901               	lda #$01
    22  0829 8d1ad0             	sta $d01a
    23  082c 8d19d0             	sta $d019 
    24  082f a900               	lda #$00
    25  0831 200010             	jsr $1000 
    26  0834 58                 	cli
    27  0835 a920               	lda #$20
    28  0837 8d6b08             	sta vector
    29  083a a917               	lda #$17
    30  083c 8d6c08             	sta vector+1
    31  083f a000               	ldy #$00
    32  0841 b93017             hold 	lda $1730,y
    33  0844 8d20d0             	sta $D020
    34  0847 ad00dc             	lda $dc00
    35  084a 2901               	and #$1
    36  084c c901               	cmp #$1
    37  084e f0f1               	beq hold
    38  0850 ad00dc             	lda $dc00
    39  0853 2901               	and #$1
    40  0855 c900               	cmp #$0
    41  0857 f0e8               	beq hold
    42  0859 c8                 	iny
    43  085a 8c6d08             	sty vector+2
    44  085d 4c4108             	jmp hold 
    45                          irq
    46  0860 a901               	lda #$01
    47  0862 8d19d0             	sta $d019 
    48  0865 200310             	jsr $1003 
    49  0868 4c31ea             	jmp $ea31
    50                          
    51                          vector
    52  086b 0000               	!byte $00,$00
    53                                      
    54                          	* = $1000
    55  1000 4c37104c85104c2f...	!binary "Techno_Drums.sid" ,, $7c+2