
A few surprises today:
- I still have my iPhone 4S.
- It still charges and boots!
- It’s so tiny! The picture doesn’t do it justice.
A few surprises today:
Thanks to Whisper and this awesome port, the tree is responding to spoken words. 🗣🎄
Since the tree itself only has a low-powered MCU, we need another machine to act as a listener.
The architecture is:
For now I’m running it from iOS and macOS, so I wrote the current implementation in Swift. The code is currently still in “hack” status, but working well!
Now it’s time to test it when talking to coworkers at Automattic.
Thanks to this repo you can fire up Windows 3.11 painlessly and even connect to the Internet! Lots of goodies are already installed so it’s a fun virtual trip.
To get it going on my Mac all I had to do was:
brew install qemu
qemu-system-i386 -nic user,ipv6=off,model=ne2k_pci -device sb16 -vga cirrus -snapshot -no-shutdown hda.img
There were some graphical glitches (restarting or dropping down into DOS and back helps) and it crashes when running Netscape, but Microsoft Bob seemed to work fine!
After configuring the network’s gateway and DNS servers, I had to visit one of my favorite test sites for old browsers:
Something I should’ve done long ago – enabling OTA (Over The Air) firmware updates so I don’t have to disassemble the project box and move the tree every time I want to change its code.
To add a touch of UX, the pixels represent the upload progress. 😎
Here’s the prompt I gave ChatGPT:
Draw a Christmas tree using SwiftUI
Here’s the code I got:
struct ChristmasTree: View {
var body: some View {
ZStack {
// draw the tree trunk
Rectangle()
.fill(Color.brown)
.frame(width: 20, height: 100)
// draw the tree branches
ForEach(0..<5) { i in
HStack(spacing: 5) {
ForEach(0..<5-i) { j in
Triangle()
.fill(Color.green)
.frame(width: 10, height: 10)
}
}
.offset(x: 0, y: -10 * CGFloat(i))
}
// draw the star on top of the tree
Circle()
.fill(Color.yellow)
.frame(width: 10, height: 10)
.offset(x: 0, y: -50)
}
}
}
The only major issue syntax-wise is that Triangle() isn’t defined – where did it get that?
A quick visit to Hacking with Swift had this nice snippet, which I dropped in.
struct Triangle: Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to: CGPoint(x: rect.midX, y: rect.minY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.midX, y: rect.minY))
return path
}
}
Now we can compile and…. tada!
Not great, but darn impressive! 🎄🤯
It has been zero days since opening this classic.
This weekend the NeoPixel tree got many much-needed updates!
Though I have more ideas to implement, the basics of what I wanted to do are complete, like sending commands remotely.
What we can currently do:
I also threw together a really quick iOS app to set the color with SwiftUI’s built-in ColorPicker view. Thanks to the Rover project (another one that’s been neglected), I had some UDP client code I could borrow to speed up development.
I’m finally taking the time to make the NeoPixel Christmas tree smarter this year.
My current plan is to:
It’s fun to design UX for limited hardware. In this case, the tree starts with an orange pattern that rotates until a WiFi connection is successful. If it fails the tree will go red, otherwise the tree briefly goes green to let the end user know all is well before starting its first sequence.
Nifty! 🎄
I have lots to post about related to my recent vintage / retro computing adventures, but in the meantime here’s iPadOS on a CRT.
It’s actually kind of nice! The biggest downside, however, is that the CRT only ran at 1280×1024@60Hz. The resolution is fine, but the refresh rate is quite low for a CRT – my eyes wouldn’t be able to handle it very long. I’ve always been sensitive to rates lower than 85Hz on CRTs.
The hardware to make it work:
I have two GPUs on my desk right now. On the left is my Voodoo3 3000 that I’ve had for ~20 years. On the right is my GTX 1060 6GB from 2017.
Due to the retro computing market, the Voodoo3 sells for more. 😳