Compare commits

...

7 Commits

31 changed files with 462 additions and 181 deletions

View File

@@ -36,7 +36,6 @@
banner="banner.webp"
bannerAlt="Mirror picture of me, pixelated beyond recognition"
subtitle="subtitle missing"
date="2026-04-06"
/>
{@render pageButtons(data.currentPage)}

View File

@@ -1,7 +1,8 @@
<script lang="ts">
import Banner2 from "$lib/banner2.svelte";
import TableOfContents from "$lib/components/table-of-contents.svelte";
import { type Project, games, hardware, apps, music, getStatusText, getStatusCode } from './projects';
// import { type Project, games, hardware, apps, music, getStatusText, getStatusCode } from './projects';
import { projects, type Project, getStatusCode } from "./projects2";
import LinkList from "$lib/lists/link-list.svelte";
import Content from "$lib/viewport/content.svelte";
import GalleryRow, { type GalleryRowEntry } from "$lib/lists/gallery-row.svelte";
@@ -35,15 +36,15 @@
bannerAlt="An upside-down New 3DS XL lying open on a desk with a small USB-C breakout board attached to it, and a USB-C cable plugged in. The 3DS is glowing to indicate that it is charging."
subtitle="Things I have worked on" />
<p>Welcome to my projects page! Here I show off all the things I have done. Projects are ordered by general topic, sorted reverse-chronologically, and have a status marker assigned that shows whether they are active or not. have fun browsing~!</p>
<!-- <p>Welcome to my projects page! Here I show off all the things I have done. Projects are ordered by general topic, sorted reverse-chronologically, and have a status marker assigned that shows whether they are active or not. have fun browsing~!</p> -->
<p>The projects page also has two sister pages that go into detail about specific subgroups of projects:</p>
<!-- <p>The projects page also has two sister pages that go into detail about specific subgroups of projects:</p>
<GalleryRow entries={subpages} />
<GalleryRow entries={subpages} /> -->
<TableOfContents />
<!-- <TableOfContents /> -->
<h2 id="games">Games</h2>
<!-- <h2 id="games">Games</h2>
{#each games as project}
{@render projectSummary({ project: project })}
{/each}
@@ -61,10 +62,20 @@
<h2 id="music">Music</h2>
{#each music as project}
{@render projectSummary({ project: project })}
{/each}
{/each} -->
<div class="project-container">
{#each projects as p}
{@render project(p)}
{/each}
</div>
</Content>
{#snippet projectSummary({
{#snippet project(p: Project)}
<a href="{p.category}/{p.id}">{p.title}</a>
{/snippet}
<!-- {#snippet projectSummary({
project
}: {
project: Project;
@@ -83,7 +94,7 @@
{#if project.date}
{project.date} |
{/if}
{getStatusText(project)}
{project}
</p>
{#if project.icon}
@@ -93,10 +104,15 @@
<p>{@html paragraph}</p>
{/each}
<LinkList entries={project.links} />
{/snippet}
{/snippet} -->
<style>
.project-subtitle {
.project-container {
display: grid;
grid-template-columns: 1fr 1fr;
}
/* .project-subtitle {
font-family: var(--font-mono);
font-size: 1.0rem;
margin-top: 0;
@@ -108,7 +124,7 @@
}
.project-banner {
margin: 0; /* reset left/right margins */
margin: 0;
width: 100%;
object-fit: cover;
max-height: 300px;
@@ -139,7 +155,7 @@
font-size: 1.0rem;
font-weight: 700;
color: var(--color-status);
}
} */
/* #region Project Status Colours */
.project-status-c-act {

View File

@@ -0,0 +1,29 @@
<script>
import Banner2 from "$lib/banner2.svelte";
import Content from "$lib/viewport/content.svelte";
// import TableOfContents from "$lib/components/table-of-contents.svelte";
export let data;
</script>
<svelte:head>
<title>{data.projectDetails.title} | denizk0461</title>
<meta name="description" content="{data.projectDetails.description}">
<meta name="DCTERMS.created" content="{data.projectDetails.date}T12:00">
</svelte:head>
<Content>
<Banner2
title="{data.projectDetails.title}"
subtitle="{data.projectDetails.subtitle}"
date="{data.projectDetails.date}"
dateUpdated="{data.projectDetails.dateUpdated}"
banner="{data.projectDetails.banner}"
bannerAlt="{data.projectDetails.bannerAlt}"
/>
<!-- <TableOfContents /> -->
<svelte:component this={data.content} />
</Content>

View File

@@ -0,0 +1,22 @@
import { projects, type Project } from '../../projects2';
export async function load({ params }) {
const post = await import(`../../${params.category}/${params.id}.md`);
// const tag: string = `${params.year}/${params.date}`; // link to the page. not to be confused with tags. i know it's confusing naming
const projectDetails = projects.find((p: Project) => p.category.toString() == params.category.toString() && p.id == params.id);
const content = post.default;
// const title: string = postValues?.title ?? "";
// const subtitle: string = postValues?.subtitle ?? "";
// const date: string = postValues?.date ?? "";
// const dateUpdated: string = postValues?.dateUpdated ?? "";
// const time: string = postValues?.time ?? "";
// const banner: string = postValues?.banner ?? "";
// const description: string = postValues?.description ?? "";
// const tags: BlogPostTag[] = postValues?.tags ?? []; // blog post tags. should be renamed 'keywords'
return {
content,
projectDetails,
};
}

View File

@@ -1,118 +0,0 @@
<script lang="ts">
import Banner2 from "$lib/banner2.svelte";
import Content from "$lib/viewport/content.svelte";
import TableOfContents from "$lib/components/table-of-contents.svelte";
</script>
<svelte:head>
<title>Daisy FM Synth | denizk0461</title>
</svelte:head>
<Content>
<Banner2
title="Daisy FM Synth"
date="2025-04-04"
banner="/projects/daisyfm/banner.webp"
bannerAlt="Close-up of Daisy, focussed on the effect knobs" />
<img src="/projects/daisyfm/fullview.webp" alt="Top view of the Daisy FM synth">
<p>A friend showed me the <a href="https://electro-smith.com/products/daisy-seed">Daisy Seed</a>, an Arduino-compatible microcontroller made for developing audio equipment. With a little bit of motivation and absolutely no experience in either programming synthesisers or electronics in general, I quickly got my hands on one and started to toy around.</p>
<p>So... <i>how did we get here?</i></p>
<TableOfContents />
<h2 id="creation">How did I make this?</h2>
<h3 id="components">Components</h3>
<p><a href="https://www.reichelt.de/my/2171501">Here's a list of the components</a> I used in this project.</p>
<ul>
<li>21 Cherry MX Low Profile Red switches, of which 15 are used for the playing keys, and 6 are used for the wavetable select (sine, square, saw) 3 for the carrier signal, and another 3 for the modulator signal.</li>
<li>11 rotating potentiometers RK11K113-LIN10K by Alps are used to adjust the volume ADSR curve as well as the effects.</li>
<li>Two CD 4051BE multiplexers are used to connect further inputs, since the analogue inputs on the Daisy did not suffice. One of them connects the majority of the rotating potentiometers to Daisy, the other connects two potentiometers and the 6 wavetable keys. Takumi Ogata has a great guide on how to use these things with Daisy <a href="https://forum.electro-smith.com/t/cd4051-multiplexer-tutorial-is-here/3481">on the Daisy forum</a>!</li>
<li>A toggle switch is used to toggle the flanger on and off.</li>
<li>A 75mm sliding potentiometer is used to adjust the master volume.</li>
<li>An audio jack breakout board provides means to connect the synth to an audio output. This can theoretically be replaced by any kind of analogue connector; this breakout board by Soldered just proved to be the most convenient for both soldering and mounting to the case.</li>
<li>A USB-C breakout board, also by Soldered, is used for power and data transfer (flashing the synth). This isn't necessary, though since Daisy only provides a microUSB connector, I felt this was sorely needed.</li>
<li>Two 5.1 kΩ, 0.25 W resistors are used as pulldown resistors to enable C-to-C functionality on the Daisy, making it compatible to the USB-C standard. Again, not necessary, though quite recommended if you're using a USB-C port.</li>
</ul>
<p>I also bought <a href="https://www.amazon.de/dp/B07WTMGX6C">this 5-pack of 45mm sliding potentiometers</a> from Amazon. They're not of the highest quality and they don't have a covering protecting the resistance strips on the inside from debris, but they do snap to 50%, which I didn't know when I bought them, but turns out to be super convenient when used as a pitch slider!</p>
<h3 id="pcb-assembly">PCB & Assembly</h3>
<h4 id="kicad">KiCad</h4>
<p>I designed the PCB in <a href="https://www.kicad.org/">KiCad</a>. I had no prior experience in designing PCBs, but designing one merely for interactable components was simple, as I didn't have to worry quite so much about electronic interference and similar issues commonly found in original PCB design utilising ICs and other complex components. I don't know much about this... but all of this is to say, learning KiCad for this project wasn't too difficult.</p>
<p>I split the PCB into four layers, separating power, ground, digital signals (switches and toggle), and analogue signals (potentiometers, audio out). I made some exceptions, such as for the waveform buttons, since they cross the playing key traces.</p>
<div class="horizontally-centre-aligned">
<img src="/projects/daisyfm/pcb-sketch.webp" alt="Screenshot of KiCad schematic">
<img src="/projects/daisyfm/pcb-empty.webp" alt="The finished PCB produced from the KiCad schematic">
</div>
<p>The PCB was manufactured by <a href="https://jlcpcb.com/">JLCPCB</a>.</p>
<h4 id="usbc">USB-C</h4>
<p>If using a USB-C breakout board, wire in two 5.1 kΩ pulldown resistors by soldering a resistor between the pin CC1 and ground. Do the same for pin CC2 with a second resistor.</p>
<p>Alternatively, if your USB-C breakout board does not have CC pins exposed, there's a chance you could still connect pulldown resistors to make it compatible. On <a href="https://www.amazon.de/dp/B09FPZDDD9">this breakout board</a> I purchased on Amazon, I discovered that the third pin from the right exposes a CC connection. Wiring a resistor between this pin and ground enabled C-to-C functionality. If you want to test the functionality before soldering, you can hold a resistor between this pin and either the ground connector on the board or the USB port's outer shell, since that one's grounded as well.</p>
<div class="horizontally-centre-aligned">
<img src="/projects/daisyfm/usbc-breakout-small.webp" alt="Close-up of the USB-C breakout board with the CC pin marked">
<img src="/projects/daisyfm/hand.webp" alt="The tiny USB-C breakout board compared to my hand">
</div>
<p>Do keep in mind that this type of connector does not have mounting holes and requires either a more sophisticated mounting mechanism in the chassis, hot glue, or both. Also, soldering to this pin is insanely finicky, since it is VERY small, so I strongly recommend a breakout board such as <a href="https://www.reichelt.de/entwicklerboards-usb-typ-c-adapterboard-buchse-debo-usb-c-f-p376522.html">this one by Soldered</a> that exposes the CC pins.</p>
<p>Actually, I later found out that this breakout board does expose CC solder pads on the back, where an SMD resistor such as <a href="https://www.reichelt.de/smd-widerstand-0402-5-1-kohm-63-mw-1--rnd-0402-1-5-1k-p182941.html">this one</a> can be placed. Since this is a 1mm long SMD component, however, and since I don't have a rework station or anything of the sort, it's safe to say I have not tried this yet.</p>
<p>Now, how do you connect the breakout to Daisy? Daisy does expose USB pins, but they require a little bit of setup. There's another way though, one that's simpler, if perhaps stupid: look for an old microUSB cable (one that carries data) and chop it up, then solder the wires of the end with the microUSB connector to the breakout board. The microUSB end can then be plugged straight into Daisy. By convention, the wiring is as follows:</p>
<ul>
<li>the red wire is power and goes to V or VUSB</li>
<li>the black wire is ground and goes to G or GND</li>
<li>the green wire is data+ and goes to D+</li>
<li>the white wire is data- and goes to D-</li>
</ul>
<p>I used an angled microUSB cable for my chassis.</p>
<h3 id="3d-print">Case & 3D Printing</h3>
<p>All components were printed using a <a href="https://eu.store.bambulab.com/collections/3d-printer/products/a1-mini?variant=49311552176476">Bambu Lab A1 mini printer</a> as well as Bambu Lab PLA Metal in the colours <a href="https://eu.store.bambulab.com/products/pla-metal?variant=46797850902876">Iron Gray</a> and <a href="https://eu.store.bambulab.com/products/pla-metal?variant=46797851099484">Iridium Gold</a>. These materials do not contain metal particles and are very easy to print.</p>
<p>The components were designed using <a href="https://www.autodesk.com/eu/products/fusion-360/overview">Autodesk Fusion</a>. Honestly, this program annoys me to no end sometimes, but it does prove to be quite useful. You can <a href="https://www.autodesk.com/education/edu-software/overview">get it for free</a> if you're a student, educator, or school IT admin, but they really make it difficult to find this page, I'm telling ya.</p>
<h3 id="programming">Programming</h3>
<p>The synth runs on a script written in the Arduino IDE using the <a href="https://electro-smith.github.io/DaisySP/index.html">DaisySP library</a>. Documentation was sparse... but it worked out. Finding the website wasn't actually all too easy, I found, though it proved to be my best resource.</p>
<p>The synth essentially works by holding an array of 15 carrier oscillators and another 15 modulator oscillators. Each oscillator only plays when the volume is greater than 0, meaning that nothing is processed until a key is pressed. However, the load of processing 30 oscillators plus effects, if they are active, when pressing all the keys is too much and will cause Daisy to freeze and crash. This is not an issue during regular use, though.</p>
<p>Find the script on <a href="https://codeberg.org/denizk0461/daisy-fm-synth">my Codeberg page</a>!</p>
<h2 id="features">What can it do?</h2>
<h3 id="osc">Oscillators</h3>
<p>This synth offers 3 waveforms that can be played via the carrier oscillator: sine, square, saw. This oscillator can be modified using frequency modulation by using the modulator oscillator, which also offers sine, square, and saw waveforms. The modulator's pitch deviation from the carrier oscillator can be set, as well as its wet/dry mix.</p>
<h3 id="fx">Effects</h3>
<p>The synth has a flanger effect that can be enabled via a switch and tweaked using frequency, depth, and delay parameters. Distortion and sample reduction are also available.</p>
<h2 id="improvements">What could I have done better?</h2>
<p>There are a few things I would add or do differently, if I was to create a second one of these:</p>
<p>The case has too few screw standoffs, which would result in the PCB flexing when buttons were pushed. I remedied this by gluing in some standoffs that lack screw holes, but it would of course be more ideal to model these into the actual case body. On that note, I would also add more screw holes in the PCB wherever possible, as the PCB didn't feature many holes, and the ones it did have were quite concentrated on the left side of the board.</p>
<p>Some visual feedback would also be nice; a power LED could be nice. A display could have been even better, perhaps a small OLED display like <a href="https://www.reichelt.de/entwicklerboards-display-oled-0-96-128x64-pixel-blau-debo-oled5-0-96-p384685.html">this one</a>. It could have given feedback on individual parameters, such as a percentage on effects when the user turns a knob.</p>
</Content>

View File

@@ -1,9 +1,3 @@
---
title: My First Month Drawing
subtitle: self-imposed drawing challenge
date: February March 2026
---
<script lang="ts">
import ImageGallery from "$lib/lists/image-gallery.svelte";
</script>
@@ -24,7 +18,7 @@ Here are some of my favourite drawings from around that time, in chronological o
],
},
{
src: "drawings/2026/breadgirl.webp",
src: "breadgirl.webp",
alt: "An anime-style girl chewing on a piece of bread. She wears a ponytail and a sleeveless top.",
desc: [
"<b>2026-01-30</b> (before the challenge)",
@@ -77,7 +71,7 @@ Here are some of my favourite drawings from around that time, in chronological o
],
},
{
src: "drawings/2026/0310.webp",
src: "0310.webp",
alt: "A digital drawing of a girl with long brown hair in a ponytail. She has green eyes and is wearing a cropped shirt with stripes, an orange spaghetti top underneath, and dark trousers. She is holding her hands behind her back.",
desc: [
"<b>2026-03-10</b> (after the challenge)",

View File

@@ -1,16 +1,10 @@
---
title: 3DS USB-C mod
subtitle: DIY charging port mod
date: October 2024
---
<script lang="ts">
import SubtitledImage from "$lib/components/subtitled-image.svelte";
import ImageGallery from "$lib/lists/image-gallery.svelte";
</script>
<SubtitledImage
image="electronics/3ds-usb-c/showcase.mp4"
image="showcase.mp4"
subtitle="it charges via USB-C! also do you like my A Hat in Time theme?"
video
/>
@@ -20,12 +14,12 @@ I modded my New 3DS XL (SNES Edition) to give it a USB-C port to charge!
<ImageGallery
images={[
{
src: "electronics/3ds-usb-c/finished.webp",
src: "finished.webp",
alt: "A back view at a New Nintendo 3DS XL with a USB-C port added between the charging port and the right shoulder buttons.",
desc: ["the USB-C port in all its glory"],
},
{
src: "electronics/3ds-usb-c/hole.webp",
src: "hole.webp",
alt: "At the top is a view at a USB-C-shaped hole cut into the back half of a New 3DS XL. At the bottom is a look at the same hole from the inside of the case. There are rough cutouts where the stylus slides in.",
desc: [
"a closer look at the holes I cut, and how they affect the stylus slot",

View File

@@ -0,0 +1,100 @@
<script lang="ts">
import TableOfContents from "$lib/components/table-of-contents.svelte";
</script>
![Top view of the Daisy FM synth](fullview.webp)
A friend showed me the [Daisy Seed](https://electro-smith.com/products/daisy-seed), an Arduino-compatible microcontroller made for developing audio equipment. With a little bit of motivation and absolutely no experience in either programming synthesisers or electronics in general, I quickly got my hands on one and started to toy around.
So... *how did we get here?*
<TableOfContents />
## How did I make this?
### Components
[Here's a list of the components](https://www.reichelt.de/my/2171501) I used in this project.
- 21 Cherry MX Low Profile Red switches, of which 15 are used for the playing keys, and 6 are used for the wavetable select (sine, square, saw) 3 for the carrier signal, and another 3 for the modulator signal.
- 11 rotating potentiometers RK11K113-LIN10K by Alps are used to adjust the volume ADSR curve as well as the effects.
- Two CD 4051BE multiplexers are used to connect further inputs, since the analogue inputs on the Daisy did not suffice. One of them connects the majority of the rotating potentiometers to Daisy, the other connects two potentiometers and the 6 wavetable keys. Takumi Ogata has a great guide on how to use these things with Daisy [on the Daisy forum](https://forum.electro-smith.com/t/cd4051-multiplexer-tutorial-is-here/3481)!
- A toggle switch is used to toggle the flanger on and off.
- A 75mm sliding potentiometer is used to adjust the master volume.
- An audio jack breakout board provides means to connect the synth to an audio output. This can theoretically be replaced by any kind of analogue connector; this breakout board by Soldered just proved to be the most convenient for both soldering and mounting to the case.
- A USB-C breakout board, also by Soldered, is used for power and data transfer (flashing the synth). This isn't necessary, though since Daisy only provides a microUSB connector, I felt this was sorely needed.
- Two 5.1 kΩ, 0.25 W resistors are used as pulldown resistors to enable C-to-C functionality on the Daisy, making it compatible to the USB-C standard. Again, not necessary, though quite recommended if you're using a USB-C port.
I also bought [this 5-pack of 45mm sliding potentiometers](https://www.amazon.de/dp/B07WTMGX6C) from Amazon. They're not of the highest quality and they don't have a covering protecting the resistance strips on the inside from debris, but they do snap to 50%, which I didn't know when I bought them, but turns out to be super convenient when used as a pitch slider!
### PCB & Assembly
#### KiCad
I designed the PCB in [KiCad](https://www.kicad.org/). I had no prior experience in designing PCBs, but designing one merely for interactable components was simple, as I didn't have to worry quite so much about electronic interference and similar issues commonly found in original PCB design utilising ICs and other complex components. I don't know much about this... but all of this is to say, learning KiCad for this project wasn't too difficult.
I split the PCB into four layers, separating power, ground, digital signals (switches and toggle), and analogue signals (potentiometers, audio out). I made some exceptions, such as for the waveform buttons, since they cross the playing key traces.
<div class="horizontally-centre-aligned">
<img src="pcb-sketch.webp" alt="Screenshot of KiCad schematic">
<img src="pcb-empty.webp" alt="The finished PCB produced from the KiCad schematic">
</div>
The PCB was manufactured by [JLCPCB](https://jlcpcb.com/).
#### USB-C
If using a USB-C breakout board, wire in two 5.1 kΩ pulldown resistors by soldering a resistor between the pin CC1 and ground. Do the same for pin CC2 with a second resistor.
Alternatively, if your USB-C breakout board does not have CC pins exposed, there's a chance you could still connect pulldown resistors to make it compatible. On [this breakout board](https://www.amazon.de/dp/B09FPZDDD9) I purchased on Amazon, I discovered that the third pin from the right exposes a CC connection. Wiring a resistor between this pin and ground enabled C-to-C functionality. If you want to test the functionality before soldering, you can hold a resistor between this pin and either the ground connector on the board or the USB port's outer shell, since that one's grounded as well.
<div class="horizontally-centre-aligned">
<img src="usbc-breakout-small.webp" alt="Close-up of the USB-C breakout board with the CC pin marked">
<img src="hand.webp" alt="The tiny USB-C breakout board compared to my hand">
</div>
Do keep in mind that this type of connector does not have mounting holes and requires either a more sophisticated mounting mechanism in the chassis, hot glue, or both. Also, soldering to this pin is insanely finicky, since it is VERY small, so I strongly recommend a breakout board such as [this one by Soldered](https://www.reichelt.de/entwicklerboards-usb-typ-c-adapterboard-buchse-debo-usb-c-f-p376522.html) that exposes the CC pins.
Actually, I later found out that this breakout board does expose CC solder pads on the back, where an SMD resistor such as [this one](https://www.reichelt.de/smd-widerstand-0402-5-1-kohm-63-mw-1--rnd-0402-1-5-1k-p182941.html) can be placed. Since this is a 1mm long SMD component, however, and since I don't have a rework station or anything of the sort, it's safe to say I have not tried this yet.
Now, how do you connect the breakout to Daisy? Daisy does expose USB pins, but they require a little bit of setup. There's another way though, one that's simpler, if perhaps stupid: look for an old microUSB cable (one that carries data) and chop it up, then solder the wires of the end with the microUSB connector to the breakout board. The microUSB end can then be plugged straight into Daisy. By convention, the wiring is as follows:
- the red wire is power and goes to V or VUSB
- the black wire is ground and goes to G or GND
- the green wire is data+ and goes to D+
- the white wire is data- and goes to D-
I used an angled microUSB cable for my chassis.
### Case & 3D Printing
All components were printed using a [Bambu Lab A1 mini printer](https://eu.store.bambulab.com/collections/3d-printer/products/a1-mini?variant=49311552176476) as well as Bambu Lab PLA Metal in the colours [Iron Gray](https://eu.store.bambulab.com/products/pla-metal?variant=46797850902876) and [Iridium Gold](https://eu.store.bambulab.com/products/pla-metal?variant=46797851099484). These materials do not contain metal particles and are very easy to print.
The components were designed using [Autodesk Fusion](https://www.autodesk.com/eu/products/fusion-360/overview). Honestly, this program annoys me to no end sometimes, but it does prove to be quite useful. You can [get it for free](https://www.autodesk.com/education/edu-software/overview) if you're a student, educator, or school IT admin, but they really make it difficult to find this page, I'm telling ya.
### Programming
The synth runs on a script written in the Arduino IDE using the [DaisySP library](https://electro-smith.github.io/DaisySP/index.html). Documentation was sparse... but it worked out. Finding the website wasn't actually all too easy, I found, though it proved to be my best resource.
The synth essentially works by holding an array of 15 carrier oscillators and another 15 modulator oscillators. Each oscillator only plays when the volume is greater than 0, meaning that nothing is processed until a key is pressed. However, the load of processing 30 oscillators plus effects, if they are active, when pressing all the keys is too much and will cause Daisy to freeze and crash. This is not an issue during regular use, though.
Find the script on [my Codeberg page](https://codeberg.org/denizk0461/daisy-fm-synth)!
## What can it do?
### Oscillators
This synth offers 3 waveforms that can be played via the carrier oscillator: sine, square, saw. This oscillator can be modified using frequency modulation by using the modulator oscillator, which also offers sine, square, and saw waveforms. The modulator's pitch deviation from the carrier oscillator can be set, as well as its wet/dry mix.
### Effects
The synth has a flanger effect that can be enabled via a switch and tweaked using frequency, depth, and delay parameters. Distortion and sample reduction are also available.
## What could I have done better?
There are a few things I would add or do differently, if I was to create a second one of these:
The case has too few screw standoffs, which would result in the PCB flexing when buttons were pushed. I remedied this by gluing in some standoffs that lack screw holes, but it would of course be more ideal to model these into the actual case body. On that note, I would also add more screw holes in the PCB wherever possible, as the PCB didn't feature many holes, and the ones it did have were quite concentrated on the left side of the board.
Some visual feedback would also be nice; a power LED could be nice. A display could have been even better, perhaps a small OLED display like [this one](https://www.reichelt.de/entwicklerboards-display-oled-0-96-128x64-pixel-blau-debo-oled5-0-96-p384685.html). It could have given feedback on individual parameters, such as a percentage on effects when the user turns a knob.

View File

@@ -1,57 +1,41 @@
---
title: deej0461
subtitle: PC companion audio source controller
date: August 2024
---
<script lang="ts">
import SubtitledImage from "$lib/components/subtitled-image.svelte";
import ImageGallery from "$lib/lists/image-gallery.svelte";
</script>
<SubtitledImage
image="electronics/deej0461/finished.webp"
image="finished.webp"
altText="A golden 3D printed shell with a slider on its left, two LEDs recessed, and four black buttons on its right. The buttons have symbols of speakers, monitors, and headphones printed on them. Three screws at the top are visible. A USB-C cable is plugged into the back of it."
subtitle="a handful of device for controlling a handful of other devices"
alignment="left"
smaller
/>
This little device was inspired by one a friend of mine built his own version of: a [deej](https://github.com/omriharel/deej) volume slider panel. This thing allows you to control different applications with individual, *physical*, sliders. Super cool thing.
Except I didn't need all these sliders, really. A single slider would be cool, I thought. You know what I really wanted? Buttons to control the audio <i>source</i>, because I switch between speakers and headphones constantly, and that's at least 3 clicks every time I want to switch. So I built a device based on deej, but with some expansions.
Except I didn't need all these sliders, really. A single slider would be cool, I thought. You know what I really wanted? Buttons to control the audio *source*, because I switch between speakers and headphones constantly, and that's at least 3 clicks every time I want to switch. So I built a device based on deej, but with some expansions.
I only used few components: a HID-enabled Arduino-compatible Pro Micro with USB-C controls the whole thing. Hooked up to it are four Cherry switches and a Soldering slider I had lying around from my [Daisy project](/projects/daisy), and I added two LEDs for good measure. It's all packaged into a 3D-printed enclosure I designed myself. The slider is screwed in tightly, and so is the top of the case; the key switches are clipped in from the top so they don't fall out; the Arduino and the LEDs are just hot-glued in. For extra flair, the four output buttons are marked with symbols for my outputs: two monitors, a pair of loudspeakers, and a pair of headphones. In the final device, they're arranged so that my two most frequently-used buttons are at the bottom for easier reach.
Software-wise, I set this up with the original deej software to control main volume. For the audio, I used a program called [SoundSwitch](https://soundswitch.aaflalo.me/). The program listened to key presses for the `F21-F24` keys, which the Arduino triggers when the output keys are pressed. The red LED lights up when a key is pressed; the white LED has no assigned function. This worked pretty well, but this is no longer the setup I use, since I switched to Fedora Linux, as I needed to adapt/change the software for the new OS!
<ImageGallery
images={[
{
src: "electronics/deej0461/printing.webp",
src: "printing.webp",
alt: "A Bambu Lab A1 mini 3D printer in the middle of printing casing parts using a golden filament. The printer head has two googly eyes attached.",
desc: ["googly-eyed printer hard at work"],
},
{
src: "electronics/deej0461/soldering.webp",
src: "soldering.webp",
alt: "An Arduino set into a 3D printed case with a slider, two LEDs, and four key switches soldered to it using wires. The components are spread out and hanging out the top of the case.",
desc: ["no PCB? no problem"],
},
]}
/>
When pressing a keyboard's volume button, Windows raises or lowers volume in increments of 2. Fedora does 5. I found this much handier, so I stopped reaching for the slider and just defaulted to using my keyboard. This meant I didn't bother setting up the slider in Fedora. The buttons work, though, but they needed some adjustment. I think (and I might be wrong??) that Linux doesn't support function keys past F12, so I changed the Arduino script so the buttons trigger `Shift + F9-F12`. Instead of a separate program (which kept asking to be updated...), I now use KDE's built-in Shortcuts that trigger a script. The script is one line: `pactl set-default-sink [sink-name]`. The sink name is hard-coded into the file because, as extensive testing proved, Shortcuts does not allow arguments when entering a command. I currently only have two files set up: one for the primary monitor, one for the headphones.
I much prefer the setup now because it doesn't rely on third-party
software anymore.
I much prefer the setup now because it doesn't rely on third-party software anymore.
This thing is, no exaggeration, one of the handiest things I have ever built, because I use it quite literally ***every single day***. I often switch between my monitor's speakers and my headphones, and being able to do that with the press of a single button is *unbelievably* handy. I don't even think about it anymore, I just reach for the buttons whenever I switch. It's a part of my routine now and I wouldn't want to miss it.

View File

@@ -1,9 +1,3 @@
---
title: LIGHTYEARS font
subtitle: Stylised font
date: March 2026
---
<p class="lightyears-text">The world looks so different now. The world looks so different now. The world looks so different now.</p>
One of my favourite music artists, [Jaron](https://youtu.be/GXvqQ5-P82I), released his album LIGHTYEARS a little over a year ago. For his visuals, he uses a variety of symbols in place of Latin letters, and there's a converter on [his website](https://jaronsteele.com/) too. Only problem is that my browser can't seem to display most of the characters because the characters aren't included in most fonts. That's why I made a font! It allows you to type Latin characters from `A-Z` as well as numbers `0-9` and `!?` in the LIGHTYEARS style. Like this:

View File

@@ -0,0 +1,272 @@
export interface Project {
category: ProjectCategory;
id: string;
banner: string;
bannerAlt: string;
title: string;
subtitle: string;
description: string;
isOngoing: boolean; // whether the project is currently active (true) or a past project (false)
date: string;
status: ProjectStatus;
};
export enum ProjectCategory {
DRAWINGS = "drawings",
GAMES = "games",
ELECTRONICS = "electronics",
MUSIC = "music",
APPS = "apps",
MISC = "misc",
}
export enum ProjectStatus {
ACTIVE = "active",
INACTIVE = "inactive",
ABANDONED = "abandoned",
FINISHED = "finished",
EOL = "end-of-life", // end of life
}
/**
* Returns static codes that can be used to reference same-name CSS classes
* without relying on display text.
*/
export function getStatusCode(project: Project): String {
switch (project.status) {
case ProjectStatus.ACTIVE:
return "act";
case ProjectStatus.INACTIVE:
return "ina";
case ProjectStatus.ABANDONED:
return "aba";
case ProjectStatus.FINISHED:
return "fin";
case ProjectStatus.EOL:
return "eol";
}
}
export const projects: Project[] = [
{
category: ProjectCategory.MISC,
id: "lightyears-font",
banner: "banner.webp",
bannerAlt: "A rainbow-like holographic effect produced by bending a reflective sheet of cardboard.",
title: "LIGHTYEARS font",
subtitle: "stylised font",
description: "",
isOngoing: false,
date: "March 2026",
status: ProjectStatus.FINISHED,
},
{
category: ProjectCategory.DRAWINGS,
id: "firstmonth",
banner: "",
bannerAlt: "",
title: "My First Month Drawing",
subtitle: "self-imposed drawing challenge",
description: "",
isOngoing: false,
date: "February March 2026",
status: ProjectStatus.FINISHED,
},
{
category: ProjectCategory.ELECTRONICS,
id: "3ds-usb-c",
banner: "",
bannerAlt: "",
title: "3DS USB-C mod",
subtitle: "DIY charging port mod",
description: "",
isOngoing: false,
date: "October 2024",
status: ProjectStatus.FINISHED,
},
{
category: ProjectCategory.ELECTRONICS,
id: "deej0461",
banner: "",
bannerAlt: "",
title: "deej0461",
subtitle: "PC companion audio source controller",
description: "",
isOngoing: false,
date: "August 2024",
status: ProjectStatus.FINISHED,
},
{
category: ProjectCategory.GAMES,
id: "projectn5",
banner: "/projects/projectn5/banner2.webp",
bannerAlt: "",
title: "Homesick",
subtitle: "",
description: "",
isOngoing: true,
date: "September 2023 now",
status: ProjectStatus.ACTIVE,
},
{
category: ProjectCategory.GAMES,
id: "magician",
banner: "/projects/magician/banner.webp",
bannerAlt: "",
title: "Magician",
subtitle: "Online Multiplayer Card Game",
description: "",
isOngoing: false,
date: "July 2025",
status: ProjectStatus.ABANDONED,
},
{
category: ProjectCategory.GAMES,
id: "projektike",
banner: "/projects/projektike/banner.webp",
bannerAlt: "",
title: "Projektike",
subtitle: "PvP Game",
description: "",
isOngoing: false,
date: "August 2024 May 2025",
status: ProjectStatus.ABANDONED,
},
{
category: ProjectCategory.GAMES,
id: "swordsnstuff",
banner: "/projects/swordsnstuff/banner.webp",
bannerAlt: "",
title: "Swords & Stuff",
subtitle: "Unity 2D RPG",
description: "",
isOngoing: false,
date: "August 2023",
status: ProjectStatus.ABANDONED,
},
{
category: ProjectCategory.GAMES,
id: "tads",
banner: "/projects/tads/banner.webp",
bannerAlt: "",
title: "Totally Accurate Dating Simulator",
subtitle: "HTML Text Adventure",
description: "",
isOngoing: false,
date: "August 2023",
status: ProjectStatus.FINISHED,
},
{
category: ProjectCategory.ELECTRONICS,
id: "daisyfm",
banner: "banner.webp",
bannerAlt: "Close-up of Daisy, focussed on the effect knobs",
title: "Daisy FM Synth",
subtitle: "Electro-Smith Daisy-based FM synth",
description: "",
isOngoing: false,
date: "July September 2024",
status: ProjectStatus.FINISHED,
},
{
category: ProjectCategory.APPS,
id: "weserplaner",
banner: "/projects/weserplaner/banner.webp",
bannerAlt: "",
title: "WeserPlaner",
subtitle: "University Timetable & Canteen Info App",
description: "",
isOngoing: false,
date: "April 2023 January 2024",
status: ProjectStatus.EOL,
},
{
category: ProjectCategory.APPS,
id: "textbasic",
banner: "",
bannerAlt: "",
title: "Text Basic",
subtitle: "Extremely Basic Text Widget App",
description: "",
isOngoing: false,
date: "May November 2023",
status: ProjectStatus.EOL,
},
{
category: ProjectCategory.APPS,
id: "qwark",
banner: "",
bannerAlt: "",
title: "Qwark Grade Log",
subtitle: "Grade Logging App",
description: "",
isOngoing: false,
date: "June 2019 March 2020",
status: ProjectStatus.EOL,
},
{
category: ProjectCategory.APPS,
id: "avhplan",
banner: "",
bannerAlt: "",
title: "AvH-Vertretungsplan",
subtitle: "Substitution Plan App",
description: "",
isOngoing: false,
date: "April 2019 March 2020",
status: ProjectStatus.EOL,
},
{
category: ProjectCategory.MUSIC,
id: "dreamworld",
banner: "/projects/dreamworld/banner.webp",
bannerAlt: "",
title: "Dreamworld",
subtitle: "My First Album",
description: "",
isOngoing: false,
date: "July 2019 September 2021",
status: ProjectStatus.FINISHED,
},
{
category: ProjectCategory.MUSIC,
id: "anewbeginning",
banner: "",
bannerAlt: "",
title: "A New Beginning",
subtitle: "",
description: "",
isOngoing: false,
date: "May August 2018",
status: ProjectStatus.FINISHED,
},
{
category: ProjectCategory.MUSIC,
id: "soundcloud",
banner: "",
bannerAlt: "",
title: "Soundcloud",
subtitle: "Demo Dump & Archive",
description: "",
isOngoing: false,
date: "",
status: ProjectStatus.INACTIVE,
},
];

View File

@@ -1,5 +0,0 @@
import { redirect } from "@sveltejs/kit";
export function load() {
redirect(308, '/feed');
}

View File

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 932 KiB

After

Width:  |  Height:  |  Size: 932 KiB

View File

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 77 KiB

View File

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View File

Before

Width:  |  Height:  |  Size: 4.0 MiB

After

Width:  |  Height:  |  Size: 4.0 MiB

View File

Before

Width:  |  Height:  |  Size: 2.2 MiB

After

Width:  |  Height:  |  Size: 2.2 MiB

View File

Before

Width:  |  Height:  |  Size: 2.5 MiB

After

Width:  |  Height:  |  Size: 2.5 MiB

View File

Before

Width:  |  Height:  |  Size: 111 KiB

After

Width:  |  Height:  |  Size: 111 KiB

View File

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

View File

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

View File

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File

Before

Width:  |  Height:  |  Size: 305 KiB

After

Width:  |  Height:  |  Size: 305 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 87 KiB

View File

Before

Width:  |  Height:  |  Size: 196 KiB

After

Width:  |  Height:  |  Size: 196 KiB

View File

Before

Width:  |  Height:  |  Size: 218 KiB

After

Width:  |  Height:  |  Size: 218 KiB

View File

Before

Width:  |  Height:  |  Size: 303 KiB

After

Width:  |  Height:  |  Size: 303 KiB