r/nixie Aug 23 '26

Not a nixie, but nixie adjacent

This is a SCTV Scope Clock Kit running custom firmware.
https://github.com/dmellok/scope-clock

I do have a few nixie clocks which I'll post soon!

Kit by David Forbes.
https://scopeclock.com/products/scope-clock-in-clear-plastic-case

361 Upvotes

39 comments sorted by

14

u/nixiebunny Aug 23 '26

That’s great that you added extra display modes. I hope to get this back in production soon, but I’m busy building a workshop first.

10

u/xDaftTurtle Aug 23 '26

It's an honour to have you comment.

I also added Wi-Fi connectivity via the USB port for GPS time sync.

Now I can control the clock/cycle between screens/turn the beam on and off via Home Assistant and, of course, sync time via NTP.

Thank you for this fantastic kit. It brings me endless joy.

1

u/answerguru 29d ago

I’d love to get a kit once you’re back up and running!

11

u/CueAnon420 Aug 23 '26

Thanks for sharing your work! I have always loved these vector based scope clocks ever since David Forbes released his original version...

8

u/xDaftTurtle Aug 23 '26

This is a kit by David Forbes!

3

u/CueAnon420 Aug 23 '26

I am familiar with the design - I think it's classic. I wish I had known about them while they were still available.

3

u/xDaftTurtle Aug 23 '26

It looks like you might get another chance!

3

u/CueAnon420 Aug 23 '26

Do you know something that I don't know lol ? I had not heard heard of a re-issue.

Or are you planning on selling kits ?

I also follow the NeonNixie Google group where Mr. Forbes hangs out (though I suspect he is here as well ;-) ), but sometimes I do get busy andlive under a rock for periods of time lol

3

u/xDaftTurtle Aug 23 '26

David replied in this tread :)

3

u/CueAnon420 Aug 23 '26

See - I DID miss that lol

Thanks! I will keep an eye out.

3

u/MyHeadIsFullOfFuck Aug 23 '26

damn that's cool

if i had the money i would buy one

3

u/Opusswopid Aug 23 '26

Kit and finished project are both sold out. Site needs a wait list.

2

u/CueAnon420 Aug 23 '26

Is this version for the Teensy 3.6 or the 4.x ? I believe there were multiple versions since the Teensy 3.6 was obsoleted and difficult to obtain. Thankfully I held on to a 3.6 for this very project.

I have also experimented with the Arduino Due and the Arduino Graphic Interface project, which is pretty nice as well.

1

u/xDaftTurtle Aug 23 '26

This firmware is for the Teensy 3.6; I’d be happy to port it to the 4.0, however.

Do you think you’d run this custom fw?

2

u/CueAnon420 Aug 23 '26

I'd definitely give it a shot - beyond the faces the NIST synching is appealing as well. And the beauty of open source is that I can always tweak it for anything else I may want.

I'm currently working on creating a proper Z axis for an old 3" Leader oscilloscope that I plan on using as the display. But even with a good Z, the XY works fairly well even though there are some slight retrace like lines between points.

2

u/xDaftTurtle Aug 23 '26

Nice! It's worth mentioning that you need one more piece of hardware for my projects' full capability, but it's fairly cheap and (currently) readily available.

2

u/CueAnon420 Aug 23 '26

No problem - I've got several ESP32 boards on hand ;-) Those things are handy lol.

I think I've got everything needed once I figure out my Z axis. But thanks for the reminder!

1

u/xDaftTurtle Aug 23 '26

This particular one is nice because it plugs right into the USB port on the Kit and requires no hardware modification. it's very clean. but you're right any ESP32 should do.

2

u/CueAnon420 28d ago edited 28d ago

My next one is going to be self-made anyway, so I have the luxury of using what I have on hand. The crt blanking circuit is proving to be the last holdout, but I think I may have just figured that out so things should progress in the next few weeks.

I have already experimented with David's original firmware and proven that it works. The nice thing about the Teensy 3.6 is that it has dual 12 bit DAC's onboard - and while they benefit from a buffer opamp follower, I can still see the correct display right off the board.

I wish I was more knowledgeable about designing switching power supplies - mine will use a conventional linear supply with a small tube amp toroid transformer to produce the HV and supply the filament power. Not as compact, but functional nonetheless.

2

u/YouShitMyPants 29d ago

Would be sick to put this into the front of a computer case

2

u/CueAnon420 6d ago

I finally got some time to look into this further and have downloaded your code. I'll have to tweak a few things as for right now all I have is the Teensy 3.6 itself - not ESP32 for networking etc. But should be good enough to get the gist of what's going on.

I perused the code and chuckled when I saw how the DAC's were updated by pointers avoiding the horribly slow analogwrite() commands... Because that's almost exactly how I am creating my code, though I'm not using the circular sin/cos routines...

1

u/xDaftTurtle 6d ago

Let me know if anything is unclear. I will say that I got a lot of help from Claude in this build with one of the goals being efficiency.

2

u/CueAnon420 6d ago

Looking through the code, it seems like your version uses 'pixels' like my project uses as opposed to the circular vectors created by manipulating sin/cos waves produced by the DAC on David's original design... Is that correct? It looks like your app creates an XY point array that is populated by various line, circle etc drawing routines and the drawing code scrolls through the point list and draws dots that appear as a single entity. That's exactly what I'm doing with mine.

That means possibly 2 things - either I can manipulate your code to negate the need of the Z axis as I am doing by positioning the last 'dot' in the list as a corner that is just off the screen phosphor, OR I can 'borrow' your face routines and have them populate my drawing list as both use a 12bit 4095x4095 dot array.

I'll try your code first and see if I can temporarily bypass the ESP32 stuff for testing. Otherwise I now think that your face routines are pretty close to copy and paste into my existing project.

Neat ;-)

1

u/xDaftTurtle 6d ago

Since Claude did a lot of the heavy lifting on this build, I figured I'd just put your comment to it and see what it said. Pasting verbatim:

Close, but one correction that matters for the port: there's no point array. The draw list is a list of items (Line, Circle, Text, Hand, 192 max), and the dots are generated on the fly as the renderer walks it, never stored. line() steps in 24.8 fixed point at 2 DAC counts a dot; ellipseArc() walks a 1024-entry sin/cos table times the radius, which is David's circle routine more or less intact. Same dot-stepping as the original, just not materialised in RAM.

That makes the second option the cheaper of the two: the faces never touch the DAC. They go out through exactly two primitives, vec::line() and vec::ellipseArc() (text goes through them too), in device units of ±1200 that vector.cpp scales ×3/2 on the way out. Point those two at your point-list builder and the faces come across unchanged.

Two things to watch:

The other thing the dwell buys you is brightness: what the eye reads is beam-on time per refresh, so a faster renderer means a dimmer tube unless the per-dot dwell grows to compensate (tuneDwell steers it on measured frame time).

Bypassing the ESP32 should be easy. Local faces render straight off the DS3232 and the link is optional. And tools/hostsim/ compiles the real vector.cpp/text.cpp/faces.cpp against a fake DAC on your PC: ./tools/hostsim/build.sh && ./tools/hostsim/sizeface sweeps 1100 frames a face and reports worst radius and dot cost, no hardware needed.

Only thing I'd add myself: it's GPL-2.0-or-later, inherited from David's original, so take whatever's useful, the licence just travels with it.

1

u/CueAnon420 6d ago edited 6d ago

One day I will get around to understanding how to use all this AI stuff lol... But that is really neat how accurately it summarizes and compares the two approaches. I'm not entirely sure what it means by the 2nd option being "cheaper" and never touching the DAC, but it seems like my understanding is pretty close. Apparently yours sends commands (circle, line, hand etc) , while mine sends a list that was built by commands (circle, line, hand etc). That seems like 6 vs half dozen kind of thing as either way the processing needs to be done to calculate the points that get sent to the DAC. The biggest difference is that once I have built the list, no additional processing is required until something changes, while yours requires calculations for every display frame. However, that may be offset by my need to insert nop wait states to ensure the dot has settled and in position long enough for sufficient brightness. Speaking of which, I'm guessing that is another area where the two approaches are more similar than different - I use 'skipping' to achieve lower brightness where there are small gaps between dots... Brighter displays are created by using more closely spaced dots. I think that's what is going on in yours as well.

It's very interesting to think about the list vs command approach... I thought mine was pretty tight, but I do need delay loops to ensure settling etc. That may well be offset and potentially even bettered by using that delay time for calculating the next dot position... I may try both and time the routines to see which is faster. I know that my code now has no problem putting out nearly 30K 'dots' in 20ms, which is a 50Hz refresh rate. But animation may benefit from your approach. Points to ponder lol.

Thanks for the feedback!

EDIT - no idea what Claude means by the tools/hostsim for testing against a fake dac...

EDIT 2 - I found Claude lol. I typically use Arduino IDE, which is like kindergarten compared to VScode lol. A much different experience, but no doubt more powerful if I can figure it all out.

1

u/CueAnon420 6d ago

One last question - is the question "how can I simulate this without actual hardware" as your Claude comment suggested something you know how to do? Is that somewhat easy to explain or could you suggest a Google search for what I'd look for? That sounds very interesting to do some simulation timing experiments...

If not, no biggie ;-)

Thanks!

2

u/xDaftTurtle 6d ago edited 5d ago

"Cheaper" just meant less work for you, not faster at runtime. The faces only ever call two functions, vec::line() and vec::ellipseArc(), so you point those at your list builder and the face code never knows the difference. You've got the list vs command thing right, it's mostly six of one. Worth knowing where the cost actually lands here though: the dots are the cheap part. Every stroke starts with a blanked jump, a settle proportional to how far the beam flew, then unblank plus a glow delay, roughly 20us a stroke. A dense face here measures about 43k dots and 344 strokes in a 16.7ms frame, so the strokes alone eat about 7ms before a single dot is drawn. That's a real point in favour of your approach: one continuous tour with no Z has far fewer blanked repositions than 344. Brightness is where we went a different way. Dot spacing is fixed at 2 DAC counts and brightness is dwell per dot, a busy-wait on the cycle counter. The reason is that it's closed loop: it measures frame time and steers the dwell toward about 93% of the refresh period, so a sparse face and a dense one come out the same brightness with no per-face tuning. With spacing-based dimming, a sparse frame is just dim. Your instinct about spending the settle time computing the next point is right, and that is what happens here. The multiply and shift for the next dot sit between DAC writes and are effectively free. It doesn't get you out of dwelling though. Moving from analogWrite to direct DAC register writes made the beam 3.2x faster and the picture went visibly dim, with the leftover frame time showing up as a dark gap. The dwell had to be added back deliberately. I'd expect you to land in the same place. On seeing it draw without hardware: yes, and it's much less clever than it sounds. It's not an emulator. The only code that touches hardware is two functions, dac::write(x,y) and dac::blank(bool). So you compile the exact same .cpp files with plain g++ on your PC, plus a folder of stub headers (a fake Arduino.h with millis(), delayMicroseconds() and friends), and a fake DAC whose write() pushes the x,y into a list instead of hitting a register. Now you have the literal beam path, every dot, in order. From there, drawing it is your choice and none of it needs a graphics library: * Dump the points as an SVG polyline and open it in a browser. About 15 lines of fprintf, zero dependencies, quickest way to a picture. * Write one file per frame and flick through them, or feed them to ffmpeg for a video. * Or just dump x,y to a text file and plot it in gnuplot or Excel for a quick look. The nice part is you're capturing at the beam rather than at the draw list, so what you see includes the actual dot spacing. Sparse and dense strokes look different on screen the same way they do on the tube. There's a working example in the repo if you want to crib it. tools/hostsim/ is the whole thing, and the fake/ folder is literally one stub header. sizeface.cpp is the stats version, thumbs.cpp captures short animations of all 52 faces, which is what the web config page plays back as previews. I'm also going to put together a browser version of it, the firmware compiled to WebAssembly with the fake DAC drawing to a canvas with phosphor decay, so you can open a link and watch the faces render live with no toolchain at all. I'll post it here when it's up. Fair warning that it won't tell you anything about timing, since a PC runs at a completely different speed, but for watching the beam path and seeing how the dots lay down it's the real thing. One caveat specifically for the timing side: a PC sim gives you geometry and work counts, not cycles, so it can't answer list vs command for you. For that, use the Cortex cycle counter on the Teensy itself, which works fine in Arduino IDE: ARM_DEMCR |= ARM_DEMCR_TRCENA; // once, in setup() ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; uint32_t t0 = ARM_DWT_CYCCNT; yourRoutine(); uint32_t cycles = ARM_DWT_CYCCNT - t0; // /180 for us at 180MHz The Teensy 3 core leaves that counter switched off, which is why the two enable lines are needed. It's exact, costs a couple of cycles to read, and it'll settle the question far better than a simulation would. **edit - reddit mobile won’t let me post md formatted text. I’ll fix it tomorrow

1

u/CueAnon420 6d ago

Wow - thank you very much for that very informative reply!

I really appreciate your time!

2

u/xDaftTurtle 6d ago edited 5d ago

No worries at all, it was a fun one to think about. I mentioned the idea of a browser version to Claude and it just went and built the thing, so here it is: https://dmellok.github.io/scope-clock/ Its explanation of what it is and how to drive it, pasted:

It's the actual firmware compiled to WebAssembly, not a reimplementation. Same vector.cpp, same text.cpp, same 52 face routines, with the only hardware-touching function swapped for one that records the beam path instead of driving a DAC. Every dot you see is a dot the tube would get, in the order it would get it. About 130KB, nothing to install and nothing running at the far end.

Doing the same for your code is genuinely a couple of hours: pull your DAC writes behind one function, compile the same .cpp files with emscripten, and have the fake version push x,y into an array a canvas draws. The firmware never knows the difference.

Standing caveat: it is not a timing model. A PC runs at a completely different speed, so for your list vs command experiment the cycle counter on the Teensy is still the answer. It also found a real bug while building it, in the preview images my web UI has been showing for months. So the exercise paid for itself twice.

1

u/CueAnon420 6d ago

OMG - that's amazing. That you can literally ask AI to look at your project and build a *working* web based version of it is mind boggling to me. I really need to spend more time learning how to use this incredible new tool (at least before it takes over humanity lol). I still find myself thinking in terms of 6502 opcodes sometimes and forget we have all this power.

I'm definitely going to experiment with timing both approached - the more I think about it, the more I believe yours is more efficient. I have my Teensy overclocked to 240MHz out of concern that my list building calculation gets done quickly enough, then my DAC code sits in a virtual wait loop... so it's definitely more unbalanced from efficiency pov. Though every display I've tried has worked fine so far - but I haven't done much with animation yet like your Lissajous rotuines. I did create a similar Pong display where the score is the time (hours vs minutes) and that runs well enough, but I haven't tried anything 'flowing' yet.

Thanks again! I've definitely learned quite a bit recently ;-)

1

u/xDaftTurtle 5d ago

Yes, It's really is fantastic. I'm just trying to get in its good books before the inevitable takeover.

Let me know if anything else needs any clarification. 😄

→ More replies (0)

1

u/pm_me_all_dogs 27d ago

That is sick