Understanding just enough about how these models work to stop using them like a search engine — and start using them like a collaborator.
This isn't a course on deep learning. This is my way of - how to use AI, the smallest amount of
understanding of the underlying tech to better the use of AI
Play with the demos.
Before any of the neural net machinery makes sense, what is the underlying idea? In nature inputs give outputs they adhere to a pattern. We want to reverse-engineer the function that drives it.
Say you're characterising a temperature sensor on your gateway board. You know from physics it follows a polynomial. You collect a few (temperature, voltage) pairs and solve for the coefficients. Done.
This works perfectly — when you know the shape upfront. The problem is, most real systems don't give you that luxury.
What's the function that maps pixels to "stop sign"? Nobody knows. You can't solve for coefficients if you don't know what kind of equation you're dealing with.
A neural network with enough neurons can approximate any continuous function, regardless of shape. You don't need to know the equation. You need data pairs and enough weights to tune. The weights are the coefficients of an equation you never had to write.
That guess is called an inductive bias. Neural nets make the least opinionated guess — which is why they're the most flexible, and why they need the most data.
Assumes a known shape. Solve analytically. Works when the assumption holds — sensor calibration, simple regressions.
Assumes piecewise or linearly separable. Good for structured tabular data with clear decision boundaries.
Assumes very little. Stacks parameterised transformations. Learns the shape. Needs more data and compute.
Neural net with one extra assumption: any part of the input can relate to any other part. That's attention.
A neural network is a polynomial with millions of terms and a smart structure, whose coefficients are found not by solving equations but by gradient descent — the same underlying idea, applied to functions too complex to write down.
Three ideas built on each other over 30 years. You don't need to know the math, seeing how they connect will change how you read model behaviour.
A single neuron is one weighted sum plus a squish function. Every single thing in a large model is just this — repeated billions of times.
The activation function is what lets you stack layers without which, any number of linear layers collapses to one and we lose non-linearity.
After a wrong prediction, the network works backwards through every connection asking: "how much did you contribute to this mistake?" Then nudges each weight a small amount. Repeat that a million times.
One neuron. Input x=1.0. Target output=1.0. Starting weight=0.4. Let's watch it learn.
Measures how wrong the prediction is. Like a score you're trying to drive to zero.
Step in the direction that reduces the loss. Learning rate η controls how big a step.
Stack neurons into layers. Each layer learns a progressively more abstract representation of the input. While this is by design, nobody designs it explicitly.
Raw features. For a SocketCAN frame: message ID, DLC, the 8 payload bytes, timestamp delta, bus ID. Each value = one neuron.
We define it, final state is learnt over training. Layer 1 might learn byte-level patterns, layer 2 sequences, layer 3 protocol-level abstractions. Training decides.
The final answer. Classification (fault / normal / unknown) or regression (predict next value). Softmax turns it into probabilities.
Claude, GPT-4, Gemini — all the same architecture underneath. A deep network. What changed is the data (text instead of labelled images), the scale (hundreds of billions of weights), and one key invention: attention.
The model doesn't read words. It reads tokens — subword pieces chosen by a compression algorithm run before training. Common words stay whole. Rare or compound words get split. This is why rare technical terms in your prompts often get fragmented — and why being specific still beats being vague.
This happens once per token generated. In a 200-token response, this pipeline runs 200 times.
Before transformers, networks processed tokens in order — like reading one character at a time with no ability to look back. Attention lets every token look at every other token simultaneously and decide how relevant each one is. "CAN" can directly attend to "driver" and "Linux" in one step, regardless of distance.
"CAN" and "FD" attend strongly to each other because the model has seen "CAN FD" as a compound concept billions of times in training. Your entire prompt is processed this way — all tokens attending to all others simultaneously. This is why a richer, more specific prompt gives the model more signal to attend to, not more noise to filter through.
The model doesn't understand your code the way you do. It has learned statistical co-occurrence patterns across trillions of tokens of code, docs, specs and discussion. It is an extremely powerful pattern completer. That's not a limitation — it's the mechanism. Knowing this is how you use it better.
Everything that follows is drawn from using these tools on actual SocketCAN driver work. The patterns that actually changed the output quality, or at least it seemed it did.
These tools all run LLMs under the hood. The real differences are context window size, how they integrate into your workflow, and how much autonomy they're given. Difference can be significant.
| Tool | Model | Where it lives | Context | Best use in embedded/CAN work |
|---|---|---|---|---|
| GitHub Copilot | GPT-5 / Claude / Gemini (picker) | VSCode, JetBrains, CLI, web | 64k–128k tokens |
Chat
agent
boilerplate struct definitions, ioctl patterns, register macros. Fast, low friction. Model picker lets you swap to Claude or GPT-5 per task. |
| Cursor | Claude / GPT / Gemini / DeepSeek (picker) | Full IDE (VSCode fork) | up to 200k tokens (effective less) |
refactor
codebase-aware Reads your entire driver tree. "How does my CAN filter work?" and it actually knows. Background agents for longer autonomous tasks. |
| Claude (claude.ai) | Claude Sonnet / Opus | Chat / browser / desktop | ~200k tokens |
design review
deep debugging Paste entire .c files. Strong on SocketCAN API questions, kernel patch review, architecture. |
| Claude Code | Claude Sonnet / Opus | Terminal + desktop app | up to 1M tokens |
autonomous
multi-file edits Runs bash, edits files, cross-compiles. "Add CANFD BRS support to this driver" — it does it. Parallel sub-agents for larger tasks. |
| OpenAI Codex | GPT-5.x-Codex series | CLI, desktop app, web, IDEs | ~192k tokens |
code gen
test harness gen Solid at generating kunit test scaffolding for protocol state logic. Parallel cloud sandboxes per task. |
The model doesn't know your toolchain, your kernel version, your hardware, or your team's conventions unless you tell it. A context block pasted at the start of a session pays for itself in the first response. Write it once, save it somewhere, paste it in.
Every answer that follows is now grounded in your actual environment. Without this, the model interpolates from the average of all Linux driver code it has seen — which might be kernel 5.4 on x86.
Remember: the model is doing weighted attention over your tokens. Filler words dilute the signal. Nouns and verbs — especially domain-specific ones — carry the weight. You don't have to write like a "caveman", but you do want the high-information tokens early.
Second prompt gives the model hardware, kernel version, exact symptom, and code. The attention mechanism has real signal to work with. Output is precise.
Asking for code from scratch produces average code. Giving the model a flawed implementation and asking it to fix it produces better output — it has something concrete to reason against. This works especially well for ISR safety and error paths.
For multi-step debugging and architecture questions, adding "think through this step by step" measurably improves correctness. For simple codegen it adds noise — use it when the problem has hidden steps.
Codegen skews optimistic — it produces the happy path well. Error handling, edge cases, and resource cleanup are almost always underspecified unless you ask for them explicitly. Make it a habit to follow every implementation with a second prompt.
You will almost always get at least two things the first pass missed — null pointer handling, missing error returns, unhandled -EAGAIN from socket ops.
Describe the behaviour you want. Ask for a kunit test or a user-space mock first. Then ask for the implementation that passes it. This forces the model to make the spec concrete before generating, which surfaces ambiguities early.
This model has read everything on the internet, It does not think. It predicts the most statistically likely next token given everything in its context window. The richer, more specific, more grounded your context — the more that prediction looks like what an expert would hopefully write. Context quality is the lever. Everything else is technique.