Compare commits

...

6 Commits

Author SHA1 Message Date
3c0c510a0d new blog post about my fancy keyboard B) 2025-08-12 03:23:57 -04:00
aa3dcb2b60 fix my rss feed 2025-08-10 00:02:46 -04:00
428174271d whoops, wrong date 2025-08-09 09:08:39 -04:00
16813d67ab update website look and add a new blogpost 2025-08-09 08:51:23 -04:00
f3e07290e3 links are now underlined on hover instead of italicised 2025-06-26 23:21:45 -04:00
87d2781a0e add a people section 2025-06-26 23:21:24 -04:00
11 changed files with 857 additions and 195 deletions

View File

@ -0,0 +1,228 @@
<!DOCTYPE HTML>
<html lang="en">
<title>'New Keyboard!'</title>
<meta name="date" content="2025/08/12">
<link rel="stylesheet" href="/style.css">
<style>
img { width: 100%; }
pre { color: white; }
</style>
<body id="blog">
<h1>New Keyboard!</h1>
<a href="#fine_here_it_is">tl;dr show me the board</a>
<p>
Throughout the past few years I've hopped from keyboard to keyboard
initally as a need for something to type on, but eventually as an obession
with the sound and feel which to this day I cannot shake.
</p>
<h2>Keyboard #1</h2>
<p>
I started on a Razer Cynosa Chroma which as far as I can tell is no longer
for sale. But for the sake of context you should know that it's a 100%
membrane keyboard with per key backlighting. For a starter keyboard it was
fine, but looking back any old office keyboard would've worked and the
$40(?) that I spent on it was not worth it. But who cares, lets go to the
next keyboard!
</p>
<h2>Keyboard #2</h2>
<p>
After being pushed by a friend who was <s>obsessed</s> interested in
keyboards I finally took the plunge and built my first custom keyboard.
This keyboard was a what I thought would be best after using a membrane
for over two years (I had very little clue what I was doing). I ended up
choosing a TKL board called the NINJA87BT which came with gateron milky
yellow switches. This may not sound custom, but then I went and ordered
some very very expensive switches called Helios v2s which are very quiet
and so soft to type on. I also bought some keycaps with legends printed
on the side nothing too expensive, but very nice to look at. Because this
was my first board I had no clue what I was doing and I ended up spending
around $300...
</p>
<h2>Keyboard #3</h2>
<p>
I started thinking about the future and how I really needed to take care
of the hands that I use every day for programming. Though I wanted to go
fully ergonomic, like where I'm at now, I chose to pace myself and decided
to go with a UHK 60v2. It was expensive, but it promised something
spectacular: a split keyboard without the ortho keywells and qmk
configuration of my current keyboard which would've been very hard to
switch to coming from a normal TKL. Instead of sticking with the cherry
reds it came with I put my Helios in (because they are still the best
switches I've ever felt). While this board was not nearly as custom as my
last I was able to enjoy it much more knowing I was not going to get
carpel tunnel halfway through my life.
</p>
<p>
I ended up using this board for about a year and a half until around mid
July of 2025 when I updated the firmware for the first time since getting
the board and it caused the keyboard to start crashing every once in a
while. I tried to roll back to the version I was using before, but my
configuration wasn't able to migrate back. So I decided it was time to
move on to the keyboard I'd been dreaming of making.
</p>
<h2>Keyboard #4 (my current one)</h2>
<p>
The keyboard I've been typing this post on is a dactyl manuform 4x5, and
It's my first truly hand built keyboard. I 3d printed the case, sanded,
primed, painted (although it did not hide the layer lines very well), and
wired. Wiring was a bit tricky but thanks to the pictures in the
<a href="https://github.com/abstracthat/dactyl-manuform">github repo</a>
I was able to do it without too much trouble.
</p>
<img src="/blog/New-Keyboard!/pics/sanded.jpg">
<img src="/blog/New-Keyboard!/pics/wiring.jpg">
<p>
After finishing the wiring, which took around 12 hours, I tried to flash
qmk to both halves. At which point realized that the right half had the
rows wired to the arduino pro micro in reverse order. After fixing the
slight hiccup I flashed and viola a working keyboard. I then put on some
black legend-less keycaps, and here is the final(ish) result:
</p>
<img id="fine_here_it_is" src="/blog/New-Keyboard!/pics/final-ish.jpg">
<p>
The ish in final(ish) is because I've yet to add a baseplate which would
add some much needed weight so the halves doesn't slide across my desk,
but for now I'm happy with it.
</p>
<h3>Build your own</h3>
<p>
Incase you're reading this in the hopes of some tips for building your
own here they are:
<ul>
<li>get the model for the keyboard from
<a href="https://ryanis.cool/dactyl/#manuform">ryanis.cool/dactyl/#manuform</a></li>
<li>when wiring your keyboard try and make the wires going from the
rows/columns around 1.5-2x longer than they need to be that way you
don't snap when you're fiddling around in there</li>
<li>if you want to get rid of layer lines look into acetone dipping your
print, I only learned about this after showing my fully wired board
to a friend otherwise I would've done it</li>
</ul>
</p>
<p>
When it comes to using my keyboard it's setup for typing as that's what I
do on it it most of the time, however when I play games things get a bit
tricky. For games where I can remap the keys I shift every key over by one
except for the keys on the bottom row, and then I set the sprint key as a.
For the games where I can't remap the keys... I just stop playing them.
If I had more of an interest in gaming I would've gone with the 4x6 as
6 more keys it offeres could've been really nice.
</p>
<p>
For those curious about the specs: I decided on a rj9 port mainly because
I like the look of them over the TRRS cables everyone seems to be using
nowadays. For the pro micro I went with the cheapest one I could find
with a usb-c port, you can't really go wrong here. As for the actual
layout my qmk config is below incase you really wanna know how I type:
</p>
<pre>
/*
This is the c configuration file for the keymap
Copyright 2012 Jun Wako <wakojun@gmail.com>
Copyright 2015 Jack Humbert
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include QMK_KEYBOARD_H
bool process_record_user(uint16_t keycode, keyrecord_t* record) {
switch (keycode) {
case KC_BSPC: {
static uint16_t registered_key = KC_NO;
if (record->event.pressed) { // On key press.
const uint8_t mods = get_mods();
#ifndef NO_ACTION_ONESHOT
uint8_t shift_mods = (mods | get_oneshot_mods()) & MOD_MASK_SHIFT;
#else
uint8_t shift_mods = mods & MOD_MASK_SHIFT;
#endif // NO_ACTION_ONESHOT
if (shift_mods) { // At least one shift key is held.
registered_key = KC_DEL;
// If one shift is held, clear it from the mods. But if both
// shifts are held, leave as is to send Shift + Del.
if (shift_mods != MOD_MASK_SHIFT) {
#ifndef NO_ACTION_ONESHOT
del_oneshot_mods(MOD_MASK_SHIFT);
#endif // NO_ACTION_ONESHOT
unregister_mods(MOD_MASK_SHIFT);
}
} else {
registered_key = KC_BSPC;
}
register_code(registered_key);
set_mods(mods);
} else { // On key release.
unregister_code(registered_key);
}
} return false;
}
return true;
}
#define _BASE 0
#define _RAISE 1
#define _LOWER 2
#define SFT_ESC SFT_T(KC_ESC)
#define CTL_BSPC CTL_T(KC_BSPC)
#define ALT_SPC ALT_T(KC_SPC)
#define SFT_ENT SFT_T(KC_ENT)
#define KC_ML KC_MS_LEFT
#define KC_MR KC_MS_RIGHT
#define KC_MU KC_MS_UP
#define KC_MD KC_MS_DOWN
#define KC_MB1 KC_MS_BTN1
#define KC_MB2 KC_MS_BTN2
#define RAISE MO(_RAISE)
#define LOWER MO(_LOWER)
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_BASE] = LAYOUT(
KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P,
KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,
KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_QUOT,
KC_LBRC, KC_RBRC, KC_MINS, KC_EQL,
KC_LCTL, KC_LSFT, KC_TAB, RSFT_T(KC_ESC),
KC_SPC, KC_LALT, KC_ENT, KC_BSPC,
LOWER, KC_LGUI, KC_RGUI, RAISE
),
[_RAISE] = LAYOUT(
QK_BOOT, KC_MPRV, KC_MSTP, KC_MPLY, KC_MNXT, KC_PGDN, MS_BTN1, MS_BTN2, KC_PGUP, KC_VOLU,
_______, MS_LEFT, MS_DOWN, MS_UP, MS_RGHT, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_MUTE,
_______, MS_WHLL, MS_WHLD, MS_WHLU, MS_WHLR, KC_BSLS, KC_SLSH, KC_LBRC, KC_RBRC, KC_VOLD,
_______, _______, _______, _______,
_______, _______, _______, _______,
_______, _______, _______, _______,
_______, _______, _______, _______
),
[_LOWER] = LAYOUT(
KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN,
KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0,
KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10,
KC_F11, KC_F12, KC_GRV, _______,
_______, _______, _______, _______,
_______, _______, _______, _______,
_______, _______, _______, _______
)
};
</pre>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 KiB

View File

@ -0,0 +1,280 @@
<!DOCTYPE HTML>
<html lang="en">
<title>'Serializing data in C'</title>
<meta name="date" content="2025/08/09">
<meta name="colorscheme" content="mellow"></meta>
<link rel="stylesheet" href="/style.css">
<style>
.-spell {}
.Number {color: #e29eca}
.Function {color: #c1c0d4}
.String {color: #90b99f}
.Character {color: #90b99f}
.PreCondit {color: #ea83a5}
.-property {color: #c1c0d4}
.Comment {color: #757581; font-style: italic}
.Macro {color: #ea83a5}
.-type-builtin {color: #e29eca}
.Type {color: #b9aeda}
.Keyword {color: #aca1cf}
.Constant {color: #ea83a5}
.-variable-parameter {color: #e29eca}
.-punctuation-delimiter {color: #9998a8}
.-punctuation-bracket {color: #9998a8}
.Include {color: #aca1cf}
.Structure {color: #e6b99d}
.-variable {color: #c9c7cd}
.Operator {color: #e6b99d}
</style>
<body id="blog">
<h1>Serializing data in C</h1>
<p>
I've started work on a new project! The project in question is one that
I have wanted to tackle for a long time but did not have the courage to
do so. However at long last it is time...
</p>
<p>
time to get funky...
</p>
<p>
I'm writing a music player, and not one that simply plays music like
spotify. This music player falls more inline with MPD in which it's a
daemon running in the background playing the music and clients may
communicate with it to tell it what to play when and the likes.
</p>
<p>
Currently I'm at that very important part in which the daemon needs to
communicate to clients via a protocol *fancy*, and to do so I have decided
to go with a socket that way <i>in theory</i> I can control my daemon from
other devices on the network. With the communication method decided I now
have to define what data goes between devices. At the current moment I've
settled on an enum for different signals.
</p>
<p>
As seen here:
</p>
<pre>
<span class="Structure"><span class="Keyword">enum</span></span> <span class="Type">libmoo_signal</span> <span class="-punctuation-bracket">{</span>
<span class="Comment"><span class="Comment"><span class="-spell">/* core signals are in the &lt; 100 range */</span></span></span>
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_ESTCON</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">1</span></span><span class="-punctuation-delimiter">,</span>
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_ESTDCON</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">2</span></span><span class="-punctuation-delimiter">,</span>
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_INCOMPATABLE_VERSION</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">3</span></span><span class="-punctuation-delimiter">,</span>
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_OK</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">50</span></span><span class="-punctuation-delimiter">,</span> <span class="Comment"><span class="Comment"><span class="-spell">/* previous message received was ok */</span></span></span>
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_NOK</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">51</span></span><span class="-punctuation-delimiter">,</span> <span class="Comment"><span class="Comment"><span class="-spell">/* previous message received was not ok */</span></span></span>
<span class="Comment"><span class="Comment"><span class="-spell">/* setting/adding data happens in the 100 range */</span></span></span>
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_ADD_SONG</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">101</span></span><span class="-punctuation-delimiter">,</span>
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_SET_PLAY</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">103</span></span><span class="-punctuation-delimiter">,</span>
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_SET_PAUSE</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">104</span></span><span class="-punctuation-delimiter">,</span>
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_SET_TOGGLE_PAUSE</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">105</span></span><span class="-punctuation-delimiter">,</span>
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_SET_SKIP_NEXT</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">110</span></span><span class="-punctuation-delimiter">,</span>
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_SET_SKIP_PREV</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">111</span></span><span class="-punctuation-delimiter">,</span>
<span class="Comment"><span class="Comment"><span class="-spell">/* removing data happens in the 200 range */</span></span></span>
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_REM_SONG</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">201</span></span><span class="-punctuation-delimiter">,</span>
<span class="Comment"><span class="Comment"><span class="-spell">/* getting data happens in the 300 range */</span></span></span>
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_GET_CUR_SONG</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">301</span></span><span class="-punctuation-delimiter">,</span>
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_GET_PAUSE</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">303</span></span><span class="-punctuation-delimiter">,</span>
<span class="-variable"><span class="Constant"><span class="Constant">LIBMOO_SIGNAL_GET_PROGRESS</span></span></span> <span class="Operator">=</span> <span class="Number"><span class="Number">310</span></span><span class="-punctuation-delimiter">,</span>
<span class="-punctuation-bracket">}</span><span class="-punctuation-delimiter">;</span>
</pre>
<p>
As for how I actually transmit the signals, I've settled on a format which
defaults to 42 bytes of data being sent with the option to send more by
setting the 41st-42nd bytes to a uint16 containing the additional number
of bytes being sent.
</p>
<pre>
<span class="Comment"><span class="Comment"><span class="-spell">/* byte - data</span></span><span class="-spell">
<span class="Comment"> *</span>
<span class="Comment"> * 0-7 - libmoo protocol version</span>
<span class="Comment"> *</span>
<span class="Comment"> * 8-31 - reserved for the future</span>
<span class="Comment"> *</span>
<span class="Comment"> * 32-40 - libmoo_signal</span>
<span class="Comment"> *</span>
<span class="Comment"> * 41-42 - uint16 more_data</span>
<span class="Comment"> *</span>
<span class="Comment"> * 43-8191 - char *data</span>
<span class="Comment"> */</span></span><span class="Comment"></span></span>
<span class="Structure"><span class="Keyword">typedef</span></span> <span class="Type"><span class="-type-builtin">char</span></span> <span class="Operator">*</span> <span class="Type">libmoo_payload</span><span class="-punctuation-delimiter">;</span>
</pre>
<p>
I'm not sure how this compares to other protocols used to transmit data,
but I'm quite proud of how I've laid this out.
</p>
<p>
Moving on to actual the point of this article: serialization. For the sake
of useablilty I've defined a datatype which models our payload which you
can see here:
</p>
<pre>
<span class="Structure"><span class="Keyword">typedef</span></span> <span class="Structure"><span class="Keyword">struct</span></span> <span class="-punctuation-bracket">{</span>
<span class="Structure"><span class="Keyword">enum</span></span> <span class="Type">libmoo_signal</span> <span class="-property">signal</span><span class="-punctuation-delimiter">;</span> <span class="Comment"><span class="Comment"><span class="-spell">/* the signal */</span></span></span>
<span class="Type"><span class="-type-builtin">uint16_t</span></span> <span class="-property">more_data</span><span class="-punctuation-delimiter">;</span> <span class="Comment"><span class="Comment"><span class="-spell">/* the number bytes of the additional data */</span></span></span>
<span class="Type"><span class="-type-builtin">char</span></span> <span class="Operator">*</span><span class="-property">data</span><span class="-punctuation-delimiter">;</span> <span class="Comment"><span class="Comment"><span class="-spell">/* additional data */</span></span></span>
<span class="-punctuation-bracket">}</span> <span class="Type"><span class="Type">libmoo_data</span></span><span class="-punctuation-delimiter">;</span>
</pre>
<p>
And a function which allows you to easily create libmoo_data:
</p>
<pre>
<span class="Comment"><span class="Comment"><span class="-spell"><span class="Comment">/**</span>
<span class="Comment"> * @brief create a new libmoo_data</span>
<span class="Comment"> *</span>
<span class="Comment"> * @param signal the signal to set</span>
<span class="Comment"> * @param data the data to set</span>
<span class="Comment"> * @return the data object</span>
<span class="Comment"> */</span></span></span></span>
<span class="Type">libmoo_data</span> <span class="Operator">*</span><span class="-variable"><span class="Function">libmoo_create_data</span></span><span class="-punctuation-bracket">(</span><span class="Structure"><span class="Keyword">enum</span></span> <span class="Type">libmoo_signal</span> <span class="-variable"><span class="-variable-parameter">signal</span></span><span class="-punctuation-delimiter">,</span> <span class="Type"><span class="-type-builtin">char</span></span> <span class="-variable-parameter"><span class="Operator">*</span><span class="-variable">data</span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
</pre>
<p>
I've provided this so that you don't have to deal with manually setting
the size of the data that you pass into the object, although (if you so
choose) you may easily override it.
</p>
<h2>Serializing</h2>
<p>
Now that we've gone over the interface for interacting with the payload
let's get to the intersting stage in which we get the data ready for
launch.
</p>
<pre>
<span class="Comment"><span class="Comment"><span class="-spell"><span class="Comment">/**</span>
<span class="Comment"> * @brief convert data into a payload.</span>
<span class="Comment"> * The payload must be allocated prior to calling this function it should be</span>
<span class="Comment"> * LIBMOO_PAYLOAD_SIZE chars long unless you think you know better.</span>
<span class="Comment"> *</span>
<span class="Comment"> * @param payload pointer to the payload</span>
<span class="Comment"> * @param data data which will be serialized</span>
<span class="Comment"> * @return the size of the resulting payload</span>
<span class="Comment"> */</span></span></span></span>
<span class="Type"><span class="-type-builtin">size_t</span></span>
<span class="-variable"><span class="Function">libmoo_serialize_data</span></span><span class="-punctuation-bracket">(</span><span class="Type">libmoo_payload</span> <span class="-variable"><span class="-variable-parameter">payload</span></span><span class="-punctuation-delimiter">,</span> <span class="Type">libmoo_data</span> <span class="-variable-parameter"><span class="Operator">*</span><span class="-variable">data</span></span><span class="-punctuation-bracket">)</span>
<span class="-punctuation-bracket">{</span>
<span class="Type"><span class="-type-builtin">void</span></span> <span class="Operator">*</span><span class="-variable">ptr</span><span class="-punctuation-delimiter">;</span>
<span class="-variable">ptr</span> <span class="Operator">=</span> <span class="-variable">payload</span><span class="-punctuation-delimiter">;</span>
<span class="Comment"><span class="Comment"><span class="-spell">/* add LIBMOO_VERSION */</span></span></span>
<span class="-variable"><span class="Function">mempcpy</span></span><span class="-punctuation-bracket">(</span><span class="-variable">ptr</span><span class="-punctuation-delimiter">,</span> <span class="-variable"><span class="Constant">LIBMOO_VERSION</span></span><span class="-punctuation-delimiter">,</span> <span class="-variable"><span class="Function">strlen</span></span><span class="-punctuation-bracket">(</span><span class="-variable"><span class="Constant">LIBMOO_VERSION</span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
<span class="Comment"><span class="Comment"><span class="-spell">/* skip the reserved space */</span></span></span>
<span class="-variable">ptr</span> <span class="Operator">+=</span> <span class="Number"><span class="Number">24</span></span><span class="-punctuation-delimiter">;</span>
<span class="Comment"><span class="Comment"><span class="-spell">/* add the signal type */</span></span></span>
<span class="-variable"><span class="Function">mempcpy</span></span><span class="-punctuation-bracket">(</span><span class="-variable">ptr</span><span class="-punctuation-delimiter">,</span> <span class="Operator">&amp;</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">signal</span></span><span class="-punctuation-delimiter">,</span> <span class="Operator"><span class="Keyword">sizeof</span></span><span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">signal</span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
<span class="Comment"><span class="Comment"><span class="-spell">/* add the size of the more data */</span></span></span>
<span class="-variable"><span class="Function">mempcpy</span></span><span class="-punctuation-bracket">(</span><span class="-variable">ptr</span><span class="-punctuation-delimiter">,</span> <span class="Operator">&amp;</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">more_data</span></span><span class="-punctuation-delimiter">,</span> <span class="Operator"><span class="Keyword">sizeof</span></span><span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">more_data</span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
<span class="Comment"><span class="Comment"><span class="-spell">/* the more data */</span></span></span>
<span class="Conditional"><span class="Keyword">if</span></span> <span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">more_data</span></span><span class="-punctuation-bracket">)</span> <span class="-punctuation-bracket">{</span>
<span class="-variable"><span class="Function">mempcpy</span></span><span class="-punctuation-bracket">(</span><span class="-variable">ptr</span><span class="-punctuation-delimiter">,</span> <span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">data</span></span><span class="-punctuation-delimiter">,</span> <span class="-variable"><span class="Function">strlen</span></span><span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">data</span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
<span class="-punctuation-bracket">}</span>
<span class="Statement"><span class="Keyword">return</span></span> <span class="-variable"><span class="Constant">LIBMOO_HEADER_SIZE</span></span> <span class="Operator">+</span> <span class="Operator"><span class="Keyword">sizeof</span></span><span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">more_data</span></span><span class="-punctuation-bracket">)</span> <span class="Operator">+</span> <span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">more_data</span></span><span class="-punctuation-delimiter">;</span>
<span class="-punctuation-bracket">}</span>
</pre>
<p>
As you may have noticed in the code snippet above libmoo_serialize_data is
a function that takes in a pre-allocated payload, and the data to
serialize. I've opted to allow the user to allocate space for the payload
if they determine that they know what they're doing incase my dumb
function is too generous. Moving onto the body of the function you'll see
an unfamiliar function called mempcpy which is a macro for copying data
into the payload. This macro takes in the same arguments as memcpy (dest,
src, size), but in addition it increments dest by size so I can append
data to the payload without making this code horrible to read.
</p>
<p>
In earlier stages of development I didn't actually return the size of the
resulting payload, thinking that I could just strlen it. This was a rookie
mistake. Because I've included extra space (bytes 8-31) when you run
strlen on any payload it results in 5 (the length of the version string).
After finding this out I decided that I do actually want to send more
than the version information, and so now libmoo_serialize_data returns a
size_t continaing the number of bytes that have been serialized.
</p>
<h2>Deserializing</h2>
<p>
Now that we've serialized and <i>presumably</i> sent the data to a client
we need to do the magic part which completes this transaction:
deserialization.
</p>
<p>
Below is my method of deserializing the data. It's pretty much the
opposite of the serialization function with the key exception that we
need to do some validation. <i>Which I haven't implemented yet.</i>
</p>
<pre>
<span class="Type">libmoo_data</span>
<span class="Operator">*</span><span class="-variable"><span class="Function">libmoo_deserialize_data</span></span><span class="-punctuation-bracket">(</span><span class="Type">libmoo_payload</span> <span class="-variable"><span class="-variable-parameter">payload</span></span><span class="-punctuation-delimiter">,</span> <span class="Type"><span class="-type-builtin">unsigned</span></span> <span class="Type"><span class="-type-builtin"><span class="-type-builtin">int</span></span></span> <span class="-variable"><span class="-variable-parameter">payload_size</span></span><span class="-punctuation-bracket">)</span>
<span class="-punctuation-bracket">{</span>
<span class="Type">libmoo_data</span> <span class="Operator">*</span><span class="-variable">data</span><span class="-punctuation-delimiter">;</span>
<span class="Type"><span class="-type-builtin">char</span></span> <span class="-variable">libmoo_version</span><span class="-punctuation-bracket">[</span><span class="-variable"><span class="Constant">LIBMOO_VERSION_LEN</span></span> <span class="Operator">+</span> <span class="Number"><span class="Number">1</span></span><span class="-punctuation-bracket">]</span><span class="-punctuation-delimiter">;</span>
<span class="Comment"><span class="Comment"><span class="-spell">/* ensure that there's enough data to comply to spec */</span></span></span>
<span class="Conditional"><span class="Keyword">if</span></span> <span class="-punctuation-bracket">(</span><span class="-variable">payload_size</span> <span class="Operator">&lt;</span> <span class="-variable"><span class="Constant">LIBMOO_HEADER_SIZE</span></span><span class="-punctuation-bracket">)</span> <span class="-punctuation-bracket">{</span>
<span class="-variable">errno</span> <span class="Operator">=</span> <span class="-variable"><span class="Constant">EBADE</span></span><span class="-punctuation-delimiter">;</span>
<span class="Statement"><span class="Keyword">return</span></span> <span class="Constant"><span class="-constant-builtin">NULL</span></span><span class="-punctuation-delimiter">;</span>
<span class="-punctuation-bracket">}</span>
<span class="Comment"><span class="Comment"><span class="-spell">/* attempt to allocate space and if we fail return NULL errno contains the</span></span><span class="-spell">
<span class="Comment"> * error</span>
<span class="Comment"> */</span></span><span class="Comment"></span></span>
<span class="-variable">data</span> <span class="Operator">=</span> <span class="-variable"><span class="Function">calloc</span></span><span class="-punctuation-bracket">(</span><span class="Number"><span class="Number">1</span></span><span class="-punctuation-delimiter">,</span> <span class="Operator"><span class="Keyword">sizeof</span></span><span class="-punctuation-bracket">(</span><span class="-variable">libmoo_data</span><span class="-punctuation-bracket">)</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
<span class="Conditional"><span class="Keyword">if</span></span> <span class="-punctuation-bracket">(</span><span class="-variable">data</span> <span class="Operator">==</span> <span class="Constant"><span class="-constant-builtin">NULL</span></span><span class="-punctuation-bracket">)</span> <span class="-punctuation-bracket">{</span>
<span class="-variable">errno</span> <span class="Operator">=</span> <span class="Constant"><span class="-variable"><span class="Constant">ENOMEM</span></span></span><span class="-punctuation-delimiter">;</span>
<span class="Statement"><span class="Keyword">return</span></span> <span class="Constant"><span class="-constant-builtin">NULL</span></span><span class="-punctuation-delimiter">;</span>
<span class="-punctuation-bracket">}</span>
<span class="Comment"><span class="Comment"><span class="-spell">/* get the libmoo_version */</span></span></span>
<span class="-variable"><span class="Function">memscpy</span></span><span class="-punctuation-bracket">(</span><span class="-variable">libmoo_version</span><span class="-punctuation-delimiter">,</span> <span class="-variable">payload</span><span class="-punctuation-delimiter">,</span> <span class="-variable"><span class="Constant">LIBMOO_VERSION_LEN</span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
<span class="-variable">libmoo_version</span><span class="-punctuation-bracket">[</span><span class="-variable"><span class="Constant">LIBMOO_VERSION_LEN</span></span><span class="-punctuation-bracket">]</span> <span class="Operator">=</span> <span class="SpecialChar"><span class="Character">'<span class="-string-escape">\0</span>'</span></span><span class="-punctuation-delimiter">;</span>
<span class="Comment"><span class="Comment"><span class="-spell">/*<span class="TodoBgNOTE"> </span></span></span><span class="-spell"><span class="TodoBgNOTE"><span class="Todo">TODO</span><span class="Comment"><span class="TodoFgNOTE">:</span></span></span><span class="Comment"><span class="TodoFgNOTE"> check that the version of the library we're talking to and our</span></span>
<span class="Comment"> * <span class="TodoFgNOTE">version are compatable</span></span>
<span class="Comment"> */</span></span><span class="Comment"></span></span>
<span class="Comment"><span class="Comment"><span class="-spell">/* gotta tell the client that we're incompatible */</span></span></span>
<span class="Conditional"><span class="Keyword">if</span></span> <span class="-punctuation-bracket">(</span><span class="-variable"><span class="Function">strcmp</span></span><span class="-punctuation-bracket">(</span><span class="-variable">libmoo_version</span><span class="-punctuation-delimiter">,</span> <span class="-variable"><span class="Constant">LIBMOO_VERSION</span></span><span class="-punctuation-bracket">)</span> <span class="Operator">!=</span> <span class="Number"><span class="Number">0</span></span><span class="-punctuation-bracket">)</span> <span class="-punctuation-bracket">{</span>
<span class="-variable">errno</span> <span class="Operator">=</span> <span class="Constant"><span class="-variable"><span class="Constant">EINVAL</span></span></span><span class="-punctuation-delimiter">;</span>
<span class="-variable"><span class="Function">free</span></span><span class="-punctuation-bracket">(</span><span class="-variable">data</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
<span class="Statement"><span class="Keyword">return</span></span> <span class="Constant"><span class="-constant-builtin">NULL</span></span><span class="-punctuation-delimiter">;</span>
<span class="-punctuation-bracket">}</span>
<span class="Comment"><span class="Comment"><span class="-spell">/* skip the reserved space */</span></span></span>
<span class="-variable">payload</span> <span class="Operator">+=</span> <span class="Number"><span class="Number">24</span></span><span class="-punctuation-delimiter">;</span>
<span class="Comment"><span class="Comment"><span class="-spell">/* get the signal */</span></span></span>
<span class="-variable"><span class="Function">memscpy</span></span><span class="-punctuation-bracket">(</span><span class="Operator">&amp;</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">signal</span></span><span class="-punctuation-delimiter">,</span> <span class="-variable">payload</span><span class="-punctuation-delimiter">,</span> <span class="Operator"><span class="Keyword">sizeof</span></span><span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">signal</span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
<span class="Comment"><span class="Comment"><span class="-spell">/* get the more data marker */</span></span></span>
<span class="-variable"><span class="Function">memscpy</span></span><span class="-punctuation-bracket">(</span><span class="Operator">&amp;</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">more_data</span></span><span class="-punctuation-delimiter">,</span> <span class="-variable">payload</span><span class="-punctuation-delimiter">,</span> <span class="Operator"><span class="Keyword">sizeof</span></span><span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">more_data</span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
<span class="Comment"><span class="Comment"><span class="-spell">/* get the data */</span></span></span>
<span class="Conditional"><span class="Keyword">if</span></span> <span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">more_data</span></span><span class="-punctuation-bracket">)</span> <span class="-punctuation-bracket">{</span>
<span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">data</span></span> <span class="Operator">=</span> <span class="-variable"><span class="Function">malloc</span></span><span class="-punctuation-bracket">(</span><span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">more_data</span></span> <span class="Operator">+</span> <span class="Number"><span class="Number">1</span></span><span class="-punctuation-bracket">)</span> <span class="Operator">*</span> <span class="Operator"><span class="Keyword">sizeof</span></span><span class="-punctuation-bracket">(</span><span class="Type"><span class="Type"><span class="-type-builtin">char</span></span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
<span class="-variable"><span class="Function">memscpy</span></span><span class="-punctuation-bracket">(</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">data</span></span><span class="-punctuation-delimiter">,</span> <span class="-variable">payload</span><span class="-punctuation-delimiter">,</span> <span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">more_data</span></span> <span class="Operator">*</span> <span class="Operator"><span class="Keyword">sizeof</span></span><span class="-punctuation-bracket">(</span><span class="Type"><span class="Type"><span class="-type-builtin">char</span></span></span><span class="-punctuation-bracket">)</span><span class="-punctuation-bracket">)</span><span class="-punctuation-delimiter">;</span>
<span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">data</span></span><span class="-punctuation-bracket">[</span><span class="-_parent"><span class="-variable">data</span><span class="Operator">-&gt;</span><span class="-property">more_data</span></span><span class="-punctuation-bracket">]</span> <span class="Operator">=</span> <span class="SpecialChar"><span class="Character">'<span class="-string-escape">\0</span>'</span></span><span class="-punctuation-delimiter">;</span> <span class="Comment"><span class="Comment"><span class="-spell">/* null terminate this string, yo */</span></span></span>
<span class="-punctuation-bracket">}</span>
<span class="Statement"><span class="Keyword">return</span></span> <span class="-variable">data</span><span class="-punctuation-delimiter">;</span>
<span class="-punctuation-bracket">}</span>
</pre>
<p>
And that's kinda it just like with the mempcpy macro I've made a memscpy
macro which increments the src by the size of the data to make reading
the data easy.
</p>
<p>
See you next year o/
<sub>I might have my project done by then, who knows</sub>
</p>
<br>
<br>
</body>
</html>

View File

@ -1,35 +0,0 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>Squibid's Blog</title>
<link rel="stylesheet" href="/style.css">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<style type="text/css">
#bloglist {
text-align: left;
font-size: 2ch;
}
p#bloglist span {
float: right;
color: white;
}
</style>
<body style="background-color: #161617;">
<div id="master">
<header>
<h1 id="font", style="margin-bottom: 0">
<a href="/">Squibid's</a> Blog
</h1>
</header>
<hr style="color: #f7f7f7;">
<p id="bloglist">
<?php include(__DIR__.'/../misc/tools.php'); blog_entries("../blog"); ?>
</p>
<h2 id="font" style="text-align: center; margin-top: 0;">
<a href="/blog/rss.xml", title="rss">subscribe</a>
</h2>
</div>
</body>
</html>

View File

@ -11,6 +11,237 @@
<!-- LB -->
<item>
<title> 'New Keyboard!'</title>
<guid>https://squi.bid/blog/New-Keyboard!/index.html</guid>
<link>https://squi.bid/blog/New-Keyboard!/index.html</link>
<pubDate>Tue, 12 Aug 2025 03:23:38 -0400</pubDate>
<description><![CDATA[<!DOCTYPE HTML>
<html lang="en">
<title>'New Keyboard!'</title>
<meta name="date" content="2025/08/12">
<link rel="stylesheet" href="/style.css">
<style>
img { width: 100%; }
pre { color: white; }
</style>
<body id="blog">
<h1>New Keyboard!</h1>
<a href="#fine_here_it_is">tl;dr show me the board</a>
<p>
Throughout the past few years I've hopped from keyboard to keyboard
initally as a need for something to type on, but eventually as an obession
with the sound and feel which to this day I cannot shake.
</p>
<h2>Keyboard #1</h2>
<p>
I started on a Razer Cynosa Chroma which as far as I can tell is no longer
for sale. But for the sake of context you should know that it's a 100%
membrane keyboard with per key backlighting. For a starter keyboard it was
fine, but looking back any old office keyboard would've worked and the
$40(?) that I spent on it was not worth it. But who cares, lets go to the
next keyboard!
</p>
<h2>Keyboard #2</h2>
<p>
After being pushed by a friend who was <s>obsessed</s> interested in
keyboards I finally took the plunge and built my first custom keyboard.
This keyboard was a what I thought would be best after using a membrane
for over two years (I had very little clue what I was doing). I ended up
choosing a TKL board called the NINJA87BT which came with gateron milky
yellow switches. This may not sound custom, but then I went and ordered
some very very expensive switches called Helios v2s which are very quiet
and so soft to type on. I also bought some keycaps with legends printed
on the side nothing too expensive, but very nice to look at. Because this
was my first board I had no clue what I was doing and I ended up spending
around $300...
</p>
<h2>Keyboard #3</h2>
<p>
I started thinking about the future and how I really needed to take care
of the hands that I use every day for programming. Though I wanted to go
fully ergonomic, like where I'm at now, I chose to pace myself and decided
to go with a UHK 60v2. It was expensive, but it promised something
spectacular: a split keyboard without the ortho keywells and qmk
configuration of my current keyboard which would've been very hard to
switch to coming from a normal TKL. Instead of sticking with the cherry
reds it came with I put my Helios in (because they are still the best
switches I've ever felt). While this board was not nearly as custom as my
last I was able to enjoy it much more knowing I was not going to get
carpel tunnel halfway through my life.
</p>
<p>
I ended up using this board for about a year and a half until around mid
July of 2025 when I updated the firmware for the first time since getting
the board and it caused the keyboard to start crashing every once in a
while. I tried to roll back to the version I was using before, but my
configuration wasn't able to migrate back. So I decided it was time to
move on to the keyboard I'd been dreaming of making.
</p>
<h2>Keyboard #4 (my current one)</h2>
<p>
The keyboard I've been typing this post on is a dactyl manuform 4x5, and
It's my first truly hand built keyboard. I 3d printed the case, sanded,
primed, painted (although it did not hide the layer lines very well), and
wired. Wiring was a bit tricky but thanks to the pictures in the
<a href="https://github.com/abstracthat/dactyl-manuform">github repo</a>
I was able to do it without too much trouble.
</p>
<img src="/blog/New-Keyboard!/pics/sanded.jpg">
<img src="/blog/New-Keyboard!/pics/wiring.jpg">
<p>
After finishing the wiring, which took around 12 hours, I tried to flash
qmk to both halves. At which point realized that the right half had the
rows wired to the arduino pro micro in reverse order. After fixing the
slight hiccup I flashed and viola a working keyboard. I then put on some
black legend-less keycaps, and here is the final(ish) result:
</p>
<img id="fine_here_it_is" src="/blog/New-Keyboard!/pics/final-ish.jpg">
<p>
The ish in final(ish) is because I've yet to add a baseplate which would
add some much needed weight so the halves doesn't slide across my desk,
but for now I'm happy with it.
</p>
<h3>Build your own</h3>
<p>
Incase you're reading this in the hopes of some tips for building your
own here they are:
<ul>
<li>get the model for the keyboard from
<a href="https://ryanis.cool/dactyl/#manuform">ryanis.cool/dactyl/#manuform</a></li>
<li>when wiring your keyboard try and make the wires going from the
rows/columns around 1.5-2x longer than they need to be that way you
don't snap when you're fiddling around in there</li>
<li>if you want to get rid of layer lines look into acetone dipping your
print, I only learned about this after showing my fully wired board
to a friend otherwise I would've done it</li>
</ul>
</p>
<p>
When it comes to using my keyboard it's setup for typing as that's what I
do on it it most of the time, however when I play games things get a bit
tricky. For games where I can remap the keys I shift every key over by one
except for the keys on the bottom row, and then I set the sprint key as a.
For the games where I can't remap the keys... I just stop playing them.
If I had more of an interest in gaming I would've gone with the 4x6 as
6 more keys it offeres could've been really nice.
</p>
<p>
For those curious about the specs: I decided on a rj9 port mainly because
I like the look of them over the TRRS cables everyone seems to be using
nowadays. For the pro micro I went with the cheapest one I could find
with a usb-c port, you can't really go wrong here. As for the actual
layout my qmk config is below incase you really wanna know how I type:
</p>
<pre>
/*
This is the c configuration file for the keymap
Copyright 2012 Jun Wako <wakojun@gmail.com>
Copyright 2015 Jack Humbert
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include QMK_KEYBOARD_H
bool process_record_user(uint16_t keycode, keyrecord_t* record) {
switch (keycode) {
case KC_BSPC: {
static uint16_t registered_key = KC_NO;
if (record->event.pressed) { // On key press.
const uint8_t mods = get_mods();
#ifndef NO_ACTION_ONESHOT
uint8_t shift_mods = (mods | get_oneshot_mods()) & MOD_MASK_SHIFT;
#else
uint8_t shift_mods = mods & MOD_MASK_SHIFT;
#endif // NO_ACTION_ONESHOT
if (shift_mods) { // At least one shift key is held.
registered_key = KC_DEL;
// If one shift is held, clear it from the mods. But if both
// shifts are held, leave as is to send Shift + Del.
if (shift_mods != MOD_MASK_SHIFT) {
#ifndef NO_ACTION_ONESHOT
del_oneshot_mods(MOD_MASK_SHIFT);
#endif // NO_ACTION_ONESHOT
unregister_mods(MOD_MASK_SHIFT);
}
} else {
registered_key = KC_BSPC;
}
register_code(registered_key);
set_mods(mods);
} else { // On key release.
unregister_code(registered_key);
}
} return false;
}
return true;
}
#define _BASE 0
#define _RAISE 1
#define _LOWER 2
#define SFT_ESC SFT_T(KC_ESC)
#define CTL_BSPC CTL_T(KC_BSPC)
#define ALT_SPC ALT_T(KC_SPC)
#define SFT_ENT SFT_T(KC_ENT)
#define KC_ML KC_MS_LEFT
#define KC_MR KC_MS_RIGHT
#define KC_MU KC_MS_UP
#define KC_MD KC_MS_DOWN
#define KC_MB1 KC_MS_BTN1
#define KC_MB2 KC_MS_BTN2
#define RAISE MO(_RAISE)
#define LOWER MO(_LOWER)
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_BASE] = LAYOUT(
KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P,
KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,
KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_QUOT,
KC_LBRC, KC_RBRC, KC_MINS, KC_EQL,
KC_LCTL, KC_LSFT, KC_TAB, RSFT_T(KC_ESC),
KC_SPC, KC_LALT, KC_ENT, KC_BSPC,
LOWER, KC_LGUI, KC_RGUI, RAISE
),
[_RAISE] = LAYOUT(
QK_BOOT, KC_MPRV, KC_MSTP, KC_MPLY, KC_MNXT, KC_PGDN, MS_BTN1, MS_BTN2, KC_PGUP, KC_VOLU,
_______, MS_LEFT, MS_DOWN, MS_UP, MS_RGHT, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_MUTE,
_______, MS_WHLL, MS_WHLD, MS_WHLU, MS_WHLR, KC_BSLS, KC_SLSH, KC_LBRC, KC_RBRC, KC_VOLD,
_______, _______, _______, _______,
_______, _______, _______, _______,
_______, _______, _______, _______,
_______, _______, _______, _______
),
[_LOWER] = LAYOUT(
KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN,
KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0,
KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10,
KC_F11, KC_F12, KC_GRV, _______,
_______, _______, _______, _______,
_______, _______, _______, _______,
_______, _______, _______, _______
)
};
</pre>
]]></description>
</item>
<item>
<title> 'Serializing data in C'</title>
<guid>https://squi.bid/blog/Serializing-data-in-C/index.html</guid>
<link>https://squi.bid/blog/Serializing-data-in-C/index.html</link>
<pubDate>Sat, 09 Aug 2025 08:50:12 -0400</pubDate>
<description><![CDATA[This post seems to screw up my rss feed. You can read it on my website: https://squi.bid/blog/Serializing-data-in-C/index.html]]></description>
</item>
<item>
<title>Why "suckless" software is important</title>
<guid>https://squi.bid/blog/Why-"suckless"-software-is-important/index.html</guid>
@ -62,7 +293,7 @@
it can serve as a great starting place to hack upon until you get the
software of your dreams.
</p>
]]></description>
</item>
@ -90,7 +321,7 @@
squibid. Eventually, when trying to find a good username I chose squibid
because that would cover both the username and profile picture.
</p>
]]></description>
</item>

151
index.php
View File

@ -3,67 +3,114 @@
<head>
<title>Squibid's Site</title>
<link rel="stylesheet" href="style.css">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- prevent darkreader extension from messing with our already dark site -->
<meta name="darkreader-lock" />
<!-- prevent darkreader from messing with our already dark site -->
<meta name="darkreader-lock"/>
</head>
<body style="background-color: #161617;">
<body>
<div id="master">
<header>
<h1 id="font"><a href="/">Squibid's</a> Website</h1>
<h1 id="font"><a href="/">Squibid</a></h1>
</header>
<hr style="color: #f7f7f7;">
<div id="left">
<div id="group"> <!-- Welcome Section -->
<hgroup>
<h2 id="font">Welcome</h2>
</hgroup>
<p>
Hi my name is Squibid, and this is my website! I will be using it
for anything that I find interesting along with some of my personal
projects and a blog.
<br><br>
Got a question? <a href="mailto:me@zacharyscheiman.com",
title="me@zacharyscheiman.com">Email me</a>.
It's not likely that I will respond fast as I do not check my
messages often.
</p>
</div>
<br>
<div id="group"> <!-- Git Section -->
<hgroup>
<h2 id="font", style="margin-bottom: 0;">Pinned Git Repos</h2>
<p style="margin-top: 0;">
my best projects
</p>
</hgroup>
<p>My best repos are</p>
<div id="group"> <!-- Welcome Section -->
<p>
Welcome to my website. I do a bunch of coding, I try to lean towards
lower level languages (mostly C) as I find it more fun when there's a
challenge. As for the content of this website: I put blog posts up
when I've got something interesting to talk about and host my own git
server with stuff I make (you can find the things I'm proud of below).
</p>
<p>
Thank you for visiting, if you've got something you wanna say to me,
feel free to contact me somewhere below:
<ul>
<li><a href="https://git.squi.bid/squibid/wiz">wiz</a> - An idle event
manager for Wayland. Written in C!</li>
<li><a href="https://git.squi.bid/squibid/eat-it">eat it</a> -
Eat It is a <a href="https://mpv.io", title="Mpv's Website">Mpv</a>
package manager written in <a href="https://lua.org",
title="Lua's Website">Lua</a> with the intent of making Mpv
scripts easier to update and use.</li>
<li><a href="mailto:me@zacharyscheiman.com">email</a></li>
<li><a href="https://github.com/squibid">github.com</a></li>
<li><a href="https://codeberg.org/squibid">codeberg.org</a></li>
</ul>
<p><a href="https://git.squi.bid/squibid">more...</a></p>
</div>
</p>
</div>
<div id="right">
<div id="group"> <!-- Blog Section -->
<hgroup>
<h2 id="font", style="margin-bottom: 0;">My Blog</h2>
<p style="text-align: center; margin-top: 0;">
<a href="/blog/rss.xml", title="rss">subscribe</a>
</p>
</hgroup>
<p id="blogpreview">
<?php include('misc/tools.php'); blog_entries("blog", 5); ?>
<div id="group"> <!-- Git Section -->
<h2 id="font", style="margin-bottom: 0;">Pinned Git Repos</h2>
<p>My best projects:</p>
<ul>
<li><a href="https://git.squi.bid/squibid/wiz">wiz</a> - An idle event
manager for Wayland. Written in C!</li>
<!-- <li><a href="https://git.squi.bid/squibid/eat-it">eat it</a> - -->
<!-- Eat It is a <a href="https://mpv.io", title="Mpv's Website">Mpv</a> -->
<!-- package manager written in <a href="https://lua.org", -->
<!-- title="Lua's Website">Lua</a> with the intent of making Mpv -->
<!-- scripts easier to update and use.</li> -->
</ul>
<p><a href="https://git.squi.bid/squibid">more...</a></p>
</div>
<div id="group"> <!-- Blog Section -->
<hgroup>
<h2 id="font", style="margin-bottom: 0;">My Blog</h2>
<a href="/blog/rss.xml", title="rss">(rss btw)</a>
</hgroup>
<br>
<?php
$path = "blog";
$limit = isset($_GET['all_blog']) ? false : 5;
$files = scandir($path."/");
$entries = [];
$i = 0;
/* get all the files */
foreach ($files as $file) {
if (is_dir($path.'/'.$file) && $file[0] != ".") {
$tags = get_meta_tags($path.'/'.$file.'/index.html');
$entries[$i][0] = preg_replace("/\//", "", $tags["date"]);
$entries[$i][1] = $file;
$entries[$i][2] = $tags["date"];
$i++;
}
}
/* reverse the list */
rsort($entries);
/* print the blogs out */
printf('<table id="bloglist">');
$i = 0;
for (; $i < count($entries); $i++) {
if ($limit && $i > $limit - 1) {
break;
}
$file = $entries[$i][1];
$age = $entries[$i][2];
printf('<tr><td><a href=/%s/%s>%s</a></td><td class="date">%s</td></tr>',
$path, $file, str_replace("-", " ", $file),
$age ? $age : "¯\_(ツ)_/¯");
}
printf('<tr><td><a href=%s>%s</a></td></tr>',
isset($_GET['all_blog']) ? "/" : "/?all_blog",
isset($_GET['all_blog']) ? "...less" : "more...");
printf('</table>');
?>
</div>
<div id="group"> <!-- People Section -->
<hgroup>
<h2 id="font", style="margin-bottom: 0;">Interesting People</h2>
<p style="margin-top: 0;">
(nvim users)
</p>
<a href="/blog">more...</a>
</div>
</hgroup>
<ul>
<li>
<a href="https://lunarflame.dev">lunarflame.dev</a>
- Fantastic game studio run by the amazing Adrian aka Phantom.
<li>
<a href="https://eggbert.xyz/">eggbert.xyz</a>
- Insanely intelligent developer who writes good blog posts and
great code.
</li>
</ul>
</div>
</div>
</body>

View File

@ -1,23 +0,0 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>Squibid's Site - 404</title>
<link rel="stylesheet" href="/style.css">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<style>
h1 {
color: var(--cyan);
font-family: sans-serif;
font-size: 404px;
width: 100vw;
vertical-align: middle;
}
</style>
<body style="background-color: #161617;">
<h1><a href="/">whoops</a></h1>
</body>
</html>

View File

@ -1,27 +0,0 @@
<?php
function blog_entries($path = "blog", $limit = false) {
$files = scandir($path."/");
$entries = [];
$i = 0;
foreach ($files as $file) {
if (is_dir($path.'/'.$file) && $file[0] != ".") {
$tags = get_meta_tags($path.'/'.$file.'/index.html');
$entries[$i][0] = preg_replace("/\//", "", $tags["date"]);
$entries[$i][1] = $file;
$entries[$i][2] = $tags["date"];
$i++;
}
}
rsort($entries);
for ($i = 0; $i < count($entries); $i++) {
if ($limit && $i > $limit - 1)
break;
$file = $entries[$i][1];
$age = $entries[$i][2];
printf('<a href=/%s/%s>%s</a><span>%s</span><br>',
$path, $file, str_replace("-", " ", $file),
$age ? $age : "¯\_(ツ)_/¯");
}
}
?>

View File

@ -1,7 +1,5 @@
/* root */
:root {
--lr-width: 45%;
/* mellow theme colors */
--bg: #161617;
--fg: #c9c7cd;
@ -29,70 +27,33 @@
--gray05: #757581;
--gray06: #9998a8;
--gray07: #c1c0d4;
/* site background color */
--site-bg: var(--bg-dark);
}
html, body {
max-height: 100%;
}
/* desktop mode */
@media only screen and (min-width: 100ch) {
#master {
width: 95ch;
}
div#master #left {
float: left;
text-align: left;
width: var(--lr-width);
}
div#master #right {
float: right;
text-align: right;
width: var(--lr-width);
}
p#blogpreview a {
max-width: 30ch;
}
}
/* mobile mode */
@media only screen and (max-width: 100ch) {
#master {
width: 85%;
}
p#blogpreview a {
max-width: 50vw;
}
}
html, body {
display: flex;
justify-content: center;
}
body[id=blog] {
background-color: var(--bg);
display: unset !important;
background-color: var(--site-bg);
max-width: 80ch;
margin: auto;
}
div#master header {
text-align: center;
font-size: 30px;
}
div#group hgroup {
text-align: center;
}
#font, p, ul, ol, h1, h2, h3, h4, h5 {
#font, p, ul, ol, h1, h2, h3, h4, h5, table {
font-family: sans-serif;
color: white;
}
p#blogpreview a {
float: left;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
h1 {
font-size: 3em;
}
p#blogpreview span {
float: right;
iframe[src="/blog"] {
width: 100%;
border: none;
}
table#bloglist {
width: 100%;
td.date {
text-align: right;
}
}
a {
font-family: sans-serif;
@ -100,5 +61,5 @@ a {
color: var(--cyan);
}
a:hover, a:active {
font-style: italic;
text-decoration: underline;
}