RP2040 https://rodyne.com Fri, 06 Feb 2026 07:12:22 +0000 en-NZ hourly 1 https://wordpress.org/?v=7.0.7 https://rodyne.com/wp-content/uploads/2015/11/web-header2.png RP2040 https://rodyne.com 32 32 Don’t look Behind The Curtains! https://rodyne.com/?p=3574 Fri, 30 Jan 2026 07:47:15 +0000 https://rodyne.com/?p=3574 Continue reading →]]>

My recent goals to work with and learn some newer, more popular, micro-controllers, and to try some different programming languages, has made me also take another look at the ways things have progressed since I started my career. My programming career started with Pet and ZX81 Basic at school, then Turbo Pascal for PC, and C for VMS/Unix at work/college. These were all languages I could easily grok. I still remember a magazine article where somebody poked a number into a memory location in the ZX81 and the letter “A” popped up on the screen, one line of code.. which mapped to one single CPU instruction! That was all it took for the light bulb to go on in my head.

The 80’s were simpler times, and life at that point was easy, and things worked well.. But then came the 90’s and along came Windows! I vaguely remember the 100’s of lines of weird C++ code, calling this API, then that API, just to get a window on the screen with “Hello world”, it all made zero sense at the time, not just to me, but a lot of our more traditional programmers, and I knew from that point on things had changed big time for me; I would no longer be a part of that world, I never wanted to see it ever again, and (for me at least) Windows/C++ had tainted the simplicity of C.

I guess this epiphany happened to a lot of other people too, as dozens of new programming languages, development environments, and operating systems, all sprung up around this time, each preaching a better and easier life than C/C++. My department however had committed to Windows, and we were all electronics engineers, so it was Visual Basic, then Delphi which won us over. Both languages hid the (high) complexity of Windows behind a simple event driven point and click interface, great for us engineers who simply wanted to get something done.

Someone coming into programming in 2026 will likely be offered JavaScript or Python as their first development language, both require an OS, an IDE, an interpreter or a browser, and probably the equivalent of a 1980’s supercomputer just to print “Hello World”. No beginner is really going to have a clue how their Print “Hello World” got onto their screen, because doing so requires understanding a API stack a mile high; If this was where I had to start my programming journey, I might never have begun, as I like to understand how things work. To many, I expect the inner workings of the stack between their chosen programming language, and the work their program actually does, is still black-magic.

I was lucky to have peeked behind the curtains early in my career, and have an intimate knowledge of CPU architectures, but even I have basically given up trying to understand the layers or stack. I read and write to whatever API is exposed, and hope the level below me knows what it is doing! Occasionally I have written parts of ‘the stack’, building hardware and writing a driver for Windows or Linux to support it, but even then I am conforming to a set of norms for the level above it, and I doubt anybody ever checked my code.

Only with Micro-controller projects am I fully back in control, and with them (for me at least) there generally was no stack; My program was the stack! This was however back with older 8-bit or 16-bit micros, and micro-controllers were not immune from technologies progress. Today’s micro-processors are amazing pieces of technology that have improved in leaps and bounds, going to multi-core monsters, with layers of complexity and peripherals that would shame a 1980’s super-computers. Unlike software though, they have done this while improving there efficiency and lowering there cost. For me, the best thing about all of this is you don’t really have to use any of this new complexity, and a simple blinking LED can still be done in a few primitive lines of C.

From a blinking LED I can add in all the complexity, and use as many of these new peripherals as I like. This is exactly like I did back in 1980 with my first Z80 chip, no real need for a stack or an API.

But API’s and stacks get added anyway, for convenience, reliability and speed of development. Abstracting away complex code behind a set of C SDK libraries, an RTOS, MicroPython, Arduino or even MMBasic, is a way of not having to learn the 1000’s of pages of CPU and peripheral datasheets. A lot of people are happy to take these easier options, including me, but lets not kid ourselves that we diligently read the libraries of source code that get compiled into our binaries, most of the time we are generally trusting the coders have done a good job.

A modern micro-processor, or System-On-Chip (SOC), is a far different beast from a micro-controller, adding many more layers of complexity, security, memory management, cores and peripherals, such as PCIe, USB3, Ethernet, or even a GPU. They are so complex that they often require there own bootstrap program to even initialise everything before it even finds and runs even a single line of your code. Very few programmers are brave enough to work bare-metal at this level because often as not these SOC’s, unlike micro-controllers, hide or abstract everything behind NDA’s or binary API’s, this is why for example on your cell phone, real world people accept they are going to work through an operating system and use the provided API’s.

So, to segue again back to my first paragraph, if I was being honest with my real goals, I love the fact that when working with micro-controllers I am effectively going back to a simpler time, a time where I owned, and understood the stack, where the stack hardly ever changed, and when I turned my computer on I was running my program code within microseconds. I guess that is why there is a resurgence in retro-computing going on, people still want to know what is behind the curtains and understand how it all works!

I am one of those people, but I will never go back to using a retro-computer or retro-operating system for my daily drive, I am happy the stack is there and hundreds of thousands of people have stood on each others shoulders, to bring me the marvelous Linux and IOS GUI’s I have today. However there is a cost, and that cost is complexity, efficiency, and the fact that programmers (like me) take all these layers of code for granted without looking behind the curtain. A whole Eco-system based on the trust that somebody else has done your due diligence for you!

This is especially scary once you realise how many bad actors are out there, examining every line of these stacks for code vulnerabilities. This is happening every hour of the day, and they are finding them with ease. AI, over-complicated programming styles, and dependency hell, are making it harder for the developers to miss these cracks in their code reviews, and easier for the bad guys to find them.

Unfortunately, as always, it is up to you to balance the security, against the ease and convenience, or, like the vast majority of us, believe the myth that your system is secure and does not have these problems.

Thanks to Gemini for the memes, but like AI vibe-coding it pays to look at the finer details 🙂

The vulnerabilities of these programming stacks were one of the plot elements in my free sci-fi trilogy eBook The Summer Of Reasoning. I still think I did a good job in that book of explaining the problem, why it matters, and the consequences of when it fails.

]]>
Small Blinkenlight Update https://rodyne.com/?p=3533 Mon, 19 Jan 2026 22:05:55 +0000 https://rodyne.com/?p=3533 Continue reading →]]> I loaded the MM Edit program onto my new Linux/Kubuntu desktop and wanted to test it out with a Raspberry Pi Pico development board to ensure everything was working. As my Pico board was all the way over in my workshop, and it was raining and cold outside (yeah, middle of summer here – go figure!), I pulled the spare RP2040 blinkenlight board off my spares shelf and decided to have another go at the temporary C firmware on it, maybe fix it once and for all.

The original blinkenlight board was a surprise favourite with the Hacker News and HackaDay community last year, and judging from the correspondence I had, a lot of people appreciated the RP2040 version over the original 8-Bit PIC one. Obviously, as I was testing MM Edit, not VS Code, I replaced the C program with a small MMBASIC program, just to see how easy it was to to do, if it all worked, and, if BASIC was fast enough to drive a bunch of multiplexed LED’s with row and column drivers. I am pleased to say it did, and the results surprised me, this must have also been the fastest development I have ever done, maybe 3 hours start to finish! It was as simple as clicking the boot-select switch on my board, plugging it in to a free USB port, and dropping the PicoMite RP2040 6.01 firmware on the new USB drive. Then writing the super-simple program below in MM Edit, pressing reset on the blinkenlight board clicking the MM Edit upload button and presto!

I wont even bother to explain the code you don’t get much easier than this. I guess I should start testing my C compilers now, wont be as much fun 🙁

' Firmware for the Blinkenlights board (https://rodyne.com/?p=1751)
' Note we are ignoring the 4-switch inputs as not required in USB version
' Use OPTION HEARTBEAT OFF to free up the heartbeat LED which I have used

OPTION EXPLICIT     ' must declare variables and defaults
OPTION DEFAULT NONE '
ON ERROR IGNORE     ' lazy error handling for non-critical hardware

' set RP2040 pin assignments
SETPIN gp3, dout
SETpin GP4, dout
SETpin GP5, dout
SETpin GP9, dout
SETpin GP10, dout
SETpin GP11, dout
SETpin GP12, dout
SETpin GP13, dout
SETpin GP14, dout
SETpin GP15, dout
SETpin GP16, dout
SETpin GP17, dout
SETpin GP18, dout
SETpin GP19, dout
SETpin GP20, dout
SETpin GP21, dout
SETpin GP22, dout
SETpin GP23, dout
SETpin GP24, dout
SETpin GP25, dout
SETpin GP26, dout
SETpin GP27, dout
SETpin GP28, dout
SETpin GP29, dout

' global variables
dim integer regs(8) ' 8 banks (rows) of 16 leds
DIM integer row = 0 ' which row is selected for output
dim integer OpModeTimeout = 0 ' it needs to accept input from my retro comp
dim string  CBuff$="" 'input temporary sorage
dim string  Char$
DIM integer trnd, nVal, hVal

' program main loop
DO
  if OpModeTimeout=0 then ' no input so do some random light show
    trnd = rnd*400 ' adjust this to speed up or slow down light show
    if trnd<10 then regs(row)=regs(row)<<1  ' shift bank LEDs left
    if trnd=13 then regs(row)=regs(row)>>1  ' and right
    if trnd=14 then regs(row)=not regs(row) ' invert them
    if trnd=15 then regs(row)=rnd*65000     ' pop a new random pattern in
    if trnd>380 then regs(row)=regs(row)+1  ' increment them
  else
    OpModeTimeout=OpModeTimeout-1 ' if no input for 12s then timeout to rnd light show 
  endif  

  ' asset the scan row driver (1=ROW ON)
  pin(gp22)=(row=7)
  pin(gp23)=(row=6)
  pin(gp24)=(row=5)
  pin(gp25)=(row=4)
  pin(gp26)=(row=3)
  pin(gp27)=(row=2)
  pin(gp28)=(row=1)
  pin(gp29)=(row=0)
  
  ' decode and asset the correct column driver for the 16 LED's (0=COL ON)
  if regs(row) and &h0001 then PIN(GP3)=0 else pin(gp3)=1
  if regs(row) and &h0002 then PIN(GP4)=0 else pin(gp4)=1
  if regs(row) and &h0004 then PIN(GP5)=0 else pin(gp5)=1
  if regs(row) and &h0008 then PIN(GP9)=0 else pin(gp9)=1
  if regs(row) and &h0010 then PIN(GP10)=0 else pin(gp10)=1
  if regs(row) and &h0020 then PIN(GP11)=0 else pin(gp11)=1
  if regs(row) and &h0040 then PIN(GP12)=0 else pin(gp12)=1
  if regs(row) and &h0080 then PIN(GP13)=0 else pin(gp13)=1
  if regs(row) and &h0100 then PIN(GP14)=0 else pin(gp14)=1
  if regs(row) and &h0200 then PIN(GP15)=0 else pin(gp15)=1
  if regs(row) and &h0400 then PIN(GP16)=0 else pin(gp16)=1
  if regs(row) and &h0800 then PIN(GP17)=0 else pin(gp17)=1
  if regs(row) and &h1000 then PIN(GP18)=0 else pin(gp18)=1
  if regs(row) and &h2000 then PIN(GP19)=0 else pin(gp19)=1
  if regs(row) and &h4000 then PIN(GP20)=0 else pin(gp20)=1
  if regs(row) and &h8000 then PIN(GP21)=0 else pin(gp21)=1

  pause 1 ' 1mS
  
  ' after pause turn all scan lines off so we dont get ghosting when we change states
  pin(gp3)=1
  pin(gp4)=1
  pin(gp5)=1
  pin(gp9)=1
  pin(gp10)=1
  pin(gp11)=1
  pin(gp12)=1
  pin(gp13)=1
  pin(gp14)=1
  pin(gp15)=1
  pin(gp16)=1
  pin(gp17)=1
  pin(gp18)=1
  pin(gp19)=1
  pin(gp20)=1
  pin(gp21)=1
  
  ' process banks/rows 0-7 in round-robin
  row=row+1
  if row>7 then row=0
  
  ' The USB port in this firmware acts like a virtual terminal so you can send
  ' text strings into it as if you are coming from a serial port, just need to 
  ' pretend a serial char is a keypress :-)
  ' format if r=nnnn where r is the row (0-7), and nnnn is a 16-bit hex string
  ' eg "4=2FE7<CR>" will put the value 2FE7 into bank 4 of the leds
  ' if no serial received for more than 12 seconds then revert back to rnd light show
  Char$=inkey$
  if Char$<>"" then ' check if character received
    if Char$=CHR$(10) OR Char$=CHR$(13) then ' if its CR then process buffer
      ' Note I'm not doing any checks on input using lazy error handling
      print "'"+CBuff$+"'" 'for debugging
      nVal = Val(LEFT$(CBuff$,1)) ' get the register value 0-7
      hVal = val("&H" + mid$(CBuff$,3,4))' convert 4 char hex str to value
      regs(nVal)=hVal ' set the register
      OpModeTimeout=10000 ' reset the timeout to display it
      CBuff$="" ' clear buffer string when processed 
    else  
      CBuff$=CBuff$+Char$ ' if not a CR then add char to buffer string
    endif  
  endif  

loop

Schematic and Gerbers for the Blinkenlights RP2040 = > here

]]>
Das Blinkenlights (mit RP2040!) https://rodyne.com/?p=1751 Sun, 26 Jan 2025 09:17:55 +0000 https://rodyne.com/?p=1751 Continue reading →]]> Got my updated design back from JLPCB on Friday and this morning decided to test them and have a go at programming them. While I have done a hardware RP2040 design for a customer before I have never actually gotten around to programming one.

The changes to the original blinkenlights are:

  1. RP2040 Microcontroller
  2. Reversed the numbering on the silk screen (Once I saw this mistake I could not unsee it!)
  3. Connects via USB cable (No host PC required, can just be used for power and it will blink)

The first thing of note is that the guy I made the boards for wanted the RP2350 (the worthy successor to the RP2040), but that chip is unfortunately not available anywhere, though rumours are they are on their way and may be in stock by the time you read this! Why the guy wanted a chip so capable for basically blinking some LED’s is beyond me, but he was so keen to get the boards he went for the older RP2040, which is still far too powerful for the task, however with both chips being under US$1.00 I guess I should just stop asking stupid questions!

The design is a bit easier as the RP2040 has 30 GPIO pins, this means we don’t have to resort to any weird external chips and can just drive the 8 rows of 16 LEDs directly through MOSFETS, though I need to move everything from 5V to 3.3V. The spare pins connected to a 4-pin dip-switch the only use at the moment for this is to ensure differing panels have different random light sequences but could also be read by the host to send different info to different panels if this functionality is programmed.

As the guy is away for a few weeks I decided I would check them out myself. Previously I have checked the RP2040 is working by simply setting the BOOT SEL switch, to disable the flash chip, and plugging the USB into my PC. If all was well, a new drive would appear in the file manager as a mounted USB Drive with two readable files. As this part worked I thought I would try and be smart and take a ride with ChatGPT to see if I could convert my original PIC C code to the RP2040.

TLDR; The hardware is fine, the LEDs blink, but buggered if I could get the USB/CDC serial interface working in the few hours allocated.

Note I decided to move the BOOT SEL switch back to a push-button in the final design, even though the DIP switch did make it easier to use without having three hands.

If you want to make this project, again all the files are here => OSHWLab

If you don’t like that, then all the files are also zipped up here => zip-files

No licence, everything public domain.

My journey with a new Microcontroller and ChatGPT. (from zero to hero!)

OK so this morning I knew as much as your average PIC programmer about VS Code, Pico SDK’s or any of the workings of the RP2040 outside of the (meager) hardware design reference which I used 18 months previous for another board design.

After having my usual Sunday stroll up Blenheim’s own Mount Vernon, a 400M high stroll, with a bunch of other old farts, I sat down at my PC at 1PM and opened the getting started with the Pico guide, followed the quite good instructions and compiled my first blink program in C.

The only bits that caused an issue were the fact I have never used VS Code before and the first project I created took about 10 minutes to even show up as it silently downloaded the SDK. Of course me being impatient closed VS Code after a minute of nothing seeming to happen, then I noticed the little messages at the bottom right of the IDE and decided to let it do its thing. All good after then, though man, that IDE is really slow!

With blinky LED under the belt I decided to ask ChatGPT to create me a bare RP2040 C Program with a 1mS interrupt, which it nicely did, and I proceeded to modify the interrupt to put the LED scan code. Pressing compile totally failed as I forgot about the make file, CMakeList.txt. Now make files are usually handled by whatever IDE I am using, MPLABX or STM32 cube, I never need to touch them and never do anything fancy with them, having it exposed to a newbie like me was a bit of a shock, (Sigh, why did Pascal never catch on!) luckily ChatGPT to the rescue.

Now ChatGPT has been pretty good and getting better, but I know it’s limitations. The perfect example of this was a few weeks ago after it gave me the perfect description how to connect some 74LS193 counters on my retro-computer. A very upbeat naive version of me then asked it for a schematic, and what I got was below!

So WTF! Yes it will make a good t-shirt to mock our AI overlords in the future, but as it stands, AI is not quite at the level of replacing an EE. (yet!)

Anyway, back to the story. I was a bit shocked with the number of configurations you needed in the CMakeList.txt file, e.g. just including a file in the C code before was good enough, but the compiler here will not do anything unless the make file knows about it. I guess there is some logic, since there are about a million C libraries out there.

Anyway, to my surprise on first compiling my program and dropping the UF2 file onto my RP2040 USB drive it worked! Hi Five to me and ChatGPT, the winning combo!

Except it didn’t work as none of the USB serial part worked and no matter what prompts I fed to it, I did not get a resolution to my problem. But the lights blink magically!

Anyway it does seem a nice chip to work with, and I may look into it (and the RP2350 when available) a bit more for my home and professional projects in the future. As for ChatGPT, it is scarily good, and like a good politician very persuasive even when it is wrong, unlike a politician though it should be able to fix its mistakes. Welcome to the future!

Note from future self: I fixed the code in about an hour in MMBasic => here, it might be a lot easier to understand if C is not your scene and/or you just want it working.

]]>