Quick Take / TL;DR (Grumpy Edition)

“Somebody at Garmin decided to call this an eTrex again. I’m not sure whether to laugh, cry, or throw one of my 120 GPSes at the wall.”

  • Screen & Battery: 3.0″ touchscreen, finally legible? Maybe, if the sun cooperates. 130h battery claimed — realistic only if it’s tucked in a drawer and praying to the power gods. Still enough for a weekend hunt. If this thing actually reads in sunlight without squinting or battling reflections, I’ll be shocked.

  • Connectivity: USB 3? Wi-Fi that doesn’t wheeze? Don’t hold your breath. They’ll do something squirrelly like pair it with the round connector from the GPS III. If it’s USB 1.1 in 2025, someone at Garmin deserves a timeout.

  • Maps & GNSS: World-side GNSS story is solid — better than Oregon 700, which matters in a world with GPS’s original parents having a quarrel. Maps? $99/year for routing. That’s a ransom note masquerading as an update.

  • Accessories: Old mounts? Obsolete. Old clips? Gone. Planned obsolescence: Garmin’s longest-running product line.

  • Naming Chaos: SE, Solar, Touch — one name, three unrelated devices. Logic-free branding strikes again.

Verdict: A better Oregon 700 trapped in eTrex cosplay, with a price tag that will make you mutter at your screen. 


Thanx, @gpsblake, for posting this. I saw it earlier in the week but forgot about it. Tuesday was a long time ago. (I’m writing this on Friday.) Let me just kind of talk out loud here to think about the positioning of this thing.

A Little History

Back in the day, the eTrex was everywhere. The yellow banana was good for teaching classes in the park, but not much else. The Legend, Venture, Vista? Better, but they’d lose lock standing in tall grass. Everyone knew someone whose first unit was one of those. Garmin later tacked “HC” on the name and infused them with 60Cx mojo, but by then the Oregons and GPSMap units were eating their lunch. At events, it was touchscreens vs. d-pads everywhere, and the eTrex line quietly shuffled off the stage.

So why bring back the name now? Yes, it’s an eTrex again. No, it does not come with sense.

Screen and Battery

3.0″ diagonal, same size as an Oregon 700, resolution 240×400. That might actually make an eTrex readable — if they finally figured out sunlight visibility. If this one’s actually legible in daylight, that’ll be a first for the eTrex family. Maybe third time’s the charm… twenty years later.

On paper: 130 hours of battery. In practice? Sure, 130 hours — in an alternate dimension where the sun never shines and the device never touches a hand. Half of that in reality is still plenty for even the longest weekend of caching.

Connectivity (or Lack Thereof?)

USB 3? USB-C? Wi-Fi that doesn’t gasp like it’s 2005? No confirmation. I’d love to see USB-C with Superspeed, but I’m braced for a connector that looks like it was salvaged from a Palm Pilot.

Maybe they’re hiding behind Wi-Fi transfers — waterproof advantage, sure — but my money says “surplus ESP8266 wheezing at 11 Mbps.” If it’s USB 1.1 in 2025, someone at Garmin deserves a timeout.

GNSS and Maps

Receiver ahead of Oregon 700, right up there with GPSMap 67 — GPS, Galileo, BeiDou, QZSS, IRNSS: alphabet soup galore. Solid.

Maps? Still the same Garmin two-step: TopoActive isn’t routable in auto mode, so you pay $99/year for City Navigator. Not an upgrade — a ransom note. Following a straight-line arrow while driving is not “modern navigation.” Dumb from a GPS company that bought a map company yet relies on free OpenStreetMaps anyway. My dog could navigate better on a leash.

Accessories and Naming Chaos

Old mounts and powered cradles? Gone. Touch uses a different clip, seemingly without power pass-through. Of course the mounts don’t match. It’s Garmin. Planned obsolescence: their longest-running product line.

The names — SE, Solar, Touch — all called “eTrex” but not actually related. eTrex SE, Solar, and Touch: three devices sharing only a name and Garmin’s allergy to logic. Reminds me of Tandy: we had two completely different 1200s, different manufacturers, and different BIOS. “Five-slot or seven-slot?” Only then can we talk upgrades. Ugh.

So What’s the Pitch?

Call it Oregon 720, and it’d make sense: bigger battery, modern GNSS, touchscreen. Instead, an eTrex at $449 in 2025. Maybe it targets phone defectors who still want a dedicated GPS — a defensible, shrinking market. Maybe Garmin’s “bridge device” before the handheld market collapses. I’d call it a bridge device, except the bridge is falling apart.

The Cynical Wrap-Up

For long-timers, it’s familiar: Garmin finally gave the eTrex the screen it always needed — and the price nobody asked for. Better than Oregon 700, but at a cost that will make you mutter at your screen.

I’ll believe the 130h battery when I see it, squint at the screen in sunlight, and wait for firmware bugs. Firmware updates: a guessing game where the customer always loses.

“But hey — at least they didn’t glue a camera in this one. One less thing to blame for battery death and glare.”

 

I just finished watching Fast and Small C++ on YouTube. The title was a tad misleading for my taste, as it was a case study on a few cases instead of a guide on creating the same, but here we are.

The speaker delivers a (very) few examples but does a case study on three implementations of the Small String Optimization in MSVC, GNU Libg++, and Clang’s libc++. I started writing this as a comment on YouTube but figured it was better to write it here (where nobody will read it) instead of a long post on YouTube (where nobody will read it).

The questioners touched on an interesting topic that probably doesn’t get enough attention. Implementations of systems software, probably more than application software, almost always have the ability to make tradeoffs where you can negotiate.

If you KNOW what generations of hardware you run on (perhaps you don’t care about 36-bit, middle-endian, context switching on an RCA 1802, output to clay marble tablets, or whatever), **and** you’re willing to throw in some static_asserts and a run-time test suite, it’s often OK to just plain not care if your pointer address == your SSO string length (or whatever example the questioner called out) because you’re literally writing the rule book, and you can just declare that to not be a case you care about.

* Unaligned accesses are slow? Don’t care.
* Unaligned accesses crashing? Don’t care.
* Your memory bits count from zero, up, and your data bits count from 64, down? Don’t care.

Repeat this pattern. It might be long. You might get a bonus for documenting them, asserting them, etc., so that the next person that is trying to move this from a data center to a $0.09 CH32V003 can at least know there are dragons ahead. That team, operating under different constraints, is then free/encouraged/required to revisit those decisions. It’s centralizing those decisions that’s the key.

If you’re writing code that runs inside a data center on hardware you control, you have incredible control over where that code runs and what compromises you have to make. Yes, it’d be polite if you could give an unfortunate time-traveler the courtesy of a failed compile-time assertion for such failures, but if you can save Google, Facebook, OpenAI, or whomever 5% of a runtime (which may correspond to the electricity bill of a small city, and that’s not even much of an exaggeration), architectural purity for compatibility with mercury tube memory RAM cells may not matter when you can change one line in a config file and say, “Software built with flags X doesn’t run in data center nodes Y and Z. Don’t bother me if you try,” because you walked down the (virtual) halls and blessed it with the compiler team, the hardware team, the OS team, the CPU team, etc. That’s actually often OK. I’m guessing that if you’re the Microsoft STL team, it’s within your right to not care much if your floating point library screams on an Arduino that’s emulating IEEE754 in software anyway, for example. The team implementing STL for a Google data center may not care about SSO in the way that a similar-sounding team implementing STL for ChromeOS may have to.

Some of these bit-tweaking decisions can have HUGE ripple impacts through modern large systems. If your SSO can hold 23 bytes instead of 7 but costs you 8% compute overhead but saves you $$$$ in VM/paging overhead because you’ve profiled your last zillion transactions and you KNOW that 89% of your strings are 19 bytes long or less, you can look like a hero. Maybe your cores penalize you heavily for branches but make speculation free. Maybe that all falls apart when your loops get automatically vectorized to completely different packages and not just different execution units within the same core. These things can all lead to wildly different core data structures and implementations.

If you’re implementing the std::string that goes with a specific compiler for a specific class of computing environments (STM32 just has different rules than z/OS). This is OK.) It’s fine to declare that the rules you need to play by are different. As a courtesy, document or at least announce those compromises in a test suite or at compile time.

Don’t go nuts with this liberty. If you make a web server on an ESP32 for an air quality device running in a single home and can save a clock cycle and make it fail silently, working on an ESP32-H2 when it works on an ESP32-C3 [1] (in a way that nobody actually cares), you’re just a psychopath and deserve to have no friends. Don’t do that. You need to be able to justify such decisions on a really large scale, IMO. I worked on the URL parser in GPSBabel that probably parses many hundreds of URLs a year, scattered across many different computers. I also made some changes to the URL parser at Google.com. They have very, very different constraints.

I was in systems software for a long time, and I’d like one of the key takeaways from this talk to be that even if your goal is to make something as “simple” as a std::string be 24 bytes long [2], there are different approaches with different tradeoffs and different cliffs when the constraints are violated. (For example, there’s a LOT of value in having the SSO buffer start at offset zero of the structure. The equivalent of an unprototyped call to puts() on a std::string (eek!) has some chance of having at least some of the string be recognizable.

Large companies these days have access to total systems measurements we dreamed of in the past. “Let’s build the top 1000 GitHub projects on a toolchain implemented to measure X and see what the average string size is” is incredibly powerful for helping decide if the SSO length should be 7, 8, 15, 23, or (gasp) more. We have the tools these days to measure this stuff (before AND after) and to constrain the worlds where the code runs to fit those resulting decisions. Maybe the SSO values can be different for a Z80 and a Google Datacenter, where every opcode from boot to recycling is controlled by one software stack.

Signed,
Worked in really large companies.

[1] I’m not even totally sure that such a thing is possible. My point is that it’s probably not wise. There should be mountains of hair saved when shaving such yaks, not individual hairs. You should be able to point to receipts of shipping those bales of hair and include projections of shipping costs for future generations of yak hair.

[2] It’s not defended that “24” was even the best choice, though it was the choice of all three implementations. “As small as possible” has strong merit, but there are a lot of apps that deal in strings that don’t quite fit into SSO buffers. There’s also a large number of programs that won’t possibly care about the difference between SSO breaking points being 7 or 28. This is probably not why your CRUD app is slow. If you’re going to care about this, be sure it’s defensible.

I was recently reading https://wp.josh.com/2020/01/22/wtf-sonoson-the-evil-companies-do-and-good-people-coming-together-to-stand-up-to-them/ where the author expressed an unpopular opinion on what was then the early problem of hardware becoming unusable when the companies lost interest. This is a bit off-brand for my posts here, but by definition, it’s my stage,   and I’ll write what I want.

(I’ll also come back to this article and link it up a little more than the original format of a response to a blog post would allow.)

It’s easy to seem smug here in the future of 2024, four years after this was written, but it’s a bit funny that one particular example was given:

Someday Spotify might kill an API and then you will not be able to Spotify with your old Sonos anymore. Disrupted access to services and overall functionality? Yes. But not bricking.

Since this article was written Spotify DID built a hardware thing (Literally named, “The Spotify Car Thing”), reliant upon an API, and DID kill software support and thus, that product. They probably learned from the noise and smoke around this and just offered refund prices to purchasers who were then free to dispose of theme.

“But wait! I am mad h4x0r! I’ll port ${SOFTWARE} to it and it shall regain former glory!”

Knock yourself out. There was even a burst of such reverse engineering effort. The reality is that a 4-core, underpowered, undocumented ARM SOC was underpowered in 2018 and would have been on part with a humble phone from about 2013, but with half the RAM. Talented people would rather work on a NEW $9 SBC that’s WAY more powerful and better documented.

The result was that a few of them surely landed in hacker junk drawers, but it’s likely that most of them went to that same landfill.

Google did something very similar with Stadia and Q, too. They couldn’t keep the required services up, so they just refunded them wholescale. They actually released new firmware to make joysticks and headsets turn into plain old Bluetooth versions of the same. Lots of people were grumpy, but it was hard to see it as a financial loss.

For every company that offers a refund, an apology that it didn’t work out, and a recommendation to recycle the product we have a dozen IOT and Smart Home product-makers that disappear in the night and silently DO brick the product. If it’s your thermostat, you probably notice. How long can your camera or security system be offline without you noticing? It happened to thousands of people. In some cases it’s wishful that the companies could have prolonged the device’s life *to some users* by providing enough source code and doc that hackers could, say, keep the security cams streaming to a local NAS, but even providing that may require resources a company facing an abrupt end may be unable to provide.

This week, Fisker Auto is in bankruptcy and liquidating. What happens to firmware that routes the vehicles, monitors safety, and may need changes to comply with laws or safety changes when the server running ‘secretserver.fiskerauto.com’ gets recycled itself? (A Tesla would be WAY less awesome without Tesla’s servers being around for traffic and charging updates. Certainly FSD, such as it is, relies heavily on the presence of the company being interested in providing the service. We certainly have nightmares of a Fisker-like ending. I think I remember Peloton facing a similar fate.

Insteon took a lot of heat for this, bricking Every Product they ever shipped. A group of Insteon customers actually purchased the remaining rights and all the rights to domains and servers to bring the lights back on – literally! This is a very rare instance.

Amazon is pulling support for the business edition of their robots, leaving 10-month-old $2400 robots useless. https://www.theverge.com/2024/7/3/24190410/amazon-astro-business-robot-discontinued-refunds That’s not very awesome. Amazon didn’t shutter; they could do better.

Its a relatively new era of physical devices outlasting the online services that they depend on. As consumers, we all want our purchases to last as long as possible, so there’s some natural disappointment. Some companies handle this well and some aren’t.

KInd of by definition, if you’re reading anything I wrote, you’re probably one to take things apart, look for JTAG pins, look for schematics, and see if you can go on your own. That’s fine for a $35 camera whose demise merely made you sad. But what’s your expectation when you have a lot invested in that product or company, such as this guy that had invested thousands in Insteon products?

Companies able to issue full refunds are pretty clearly hard to get too mad at, but that clearly doesn’t work in every case, such as products sold through retails or like Peloton, where the company just folds.

I don’t have great suggestions either. It’s messy, and it’s a fairly new problem for us in technology. I think the lifetime subscription for our 1st Gen Tivo was about my earliest encounter with a device that actually relied on an online presence.

What are your expectations?

One of the nifty things about common open source software is that lots of people write down answers to their own problems. (Like I’m doing now.) The problem is that commands change, software gets moved between packages, etc. and it’s realy hard to figure out what actually applies to anything. PHP seems particularly problem to this problem because it’s old (in web-years) and because it’s popular in the blogging community, so it gets blogged about a lot. (Like I’m doing now.)

I have Pi 3 running DietPi for some internal IoT/network monitoring duty. DietPi works really well on a headless configuration, so I’ve used it forever.

I also have an internal page that has some super-simple PHP that cranks off CURL calls to build connections to other pages. After finally finding where logs are THIS month (/var/log/apache2/error.log), I was getting:

PHP Fatal error: Uncaught Error: Call to undefined function curl_init() in /var/www/index.php:81\nStack trace:\n#0 /var/www/index.php(101): checkOnline()\n#1 /var/www/index.php(194): checkAlive()\n#2 {main}\n thrown in /var/www/index.php on line 81

php.ini definitely had extension=curl (not libcurl, not libcurl.so, not php8.3-curl, not the hundred other suggestions) and it was definitely being recognized because I could change the spelling of it and get different errors in the log. But whas I wasn’t getting was … curl.

Fast-forward about three hours.

dietpi@DietPi:~$ sudo apt-get install php8.3-curl php 8.2-curl
(and I notice now that it even fixed my typo. What a rare act of kindness from Linux CLI administration. 🙂

This is a total act of desparation because I can absolutely see the curl.so object in the /usr/lib/php/20220829/ extension_dir that’s helpfully provided by phpinfo(). But let’s try….

Reading package lists… Done
Building dependency tree… Done
Reading state information… Done
Note, selecting ‘php8.2-curl’ for regex ‘8.2-curl’
Note, selecting ‘php8.2-curl-dbgsym’ for regex ‘8.2-curl’
php8.3-curl is already the newest version (8.3.3-1+0~20240216.17+debian11~1.gbp87e37b).
php8.3-curl set to manually installed.
The following NEW packages will be installed:
php php8.2-curl php8.2-curl-dbgsym php8.3
0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded.
Need to get 223 kB of archives.
After this operation, 370 kB of additional disk space will be used.
Get:1 https://packages.sury.org/php bullseye/main armhf php8.3 all 8.3.3-1+0~20240216.17+debian11~1.gbp87e37b [27.6 kB]
Get:2 https://packages.sury.org/php bullseye/main armhf php all 2:8.3+94+0~20240205.51+debian11~1.gbp6faa2e [7,404 B]
Get:3 https://packages.sury.org/php bullseye/main armhf php8.2-curl armhf 8.2.16-1+0~20240216.40+debian11~1.gbp6cbea3 [31.3 kB]
Get:4 https://packages.sury.org/php bullseye/main armhf php8.2-curl-dbgsym armhf 8.2.16-1+0~20240216.40+debian11~1.gbp6cbea3 [157 kB]
Fetched 223 kB in 2s (146 kB/s)
Selecting previously unselected package php8.3.
(Reading database … 65559 files and directories currently installed.)
Preparing to unpack …/php8.3_8.3.3-1+0~20240216.17+debian11~1.gbp87e37b_all.deb …
Unpacking php8.3 (8.3.3-1+0~20240216.17+debian11~1.gbp87e37b) …
Selecting previously unselected package php.
Preparing to unpack …/php_2%3a8.3+94+0~20240205.51+debian11~1.gbp6faa2e_all.deb …
Unpacking php (2:8.3+94+0~20240205.51+debian11~1.gbp6faa2e) …
Selecting previously unselected package php8.2-curl.
Preparing to unpack …/php8.2-curl_8.2.16-1+0~20240216.40+debian11~1.gbp6cbea3_armhf.deb …
Unpacking php8.2-curl (8.2.16-1+0~20240216.40+debian11~1.gbp6cbea3) …
Selecting previously unselected package php8.2-curl-dbgsym.
Preparing to unpack …/php8.2-curl-dbgsym_8.2.16-1+0~20240216.40+debian11~1.gbp6cbea3_armhf.deb …
Unpacking php8.2-curl-dbgsym (8.2.16-1+0~20240216.40+debian11~1.gbp6cbea3) …
Setting up php8.2-curl (8.2.16-1+0~20240216.40+debian11~1.gbp6cbea3) …

Creating config file /etc/php/8.2/mods-available/curl.ini with new version
Setting up php8.3 (8.3.3-1+0~20240216.17+debian11~1.gbp87e37b) …
Setting up php (2:8.3+94+0~20240205.51+debian11~1.gbp6faa2e) …
Setting up php8.2-curl-dbgsym (8.2.16-1+0~20240216.40+debian11~1.gbp6cbea3) …
Processing triggers for libapache2-mod-php8.2 (8.2.16-1+0~20240216.40+debian11~1.gbp6cbea3) …
Processing triggers for php8.2-cli (8.2.16-1+0~20240216.40+debian11~1.gbp6cbea3) …
dietpi@DietPi:~$ sudo systemctl restart apache2

Viola! Sucess.

35+ years of administering UNIX-y systems and the darned things can still stump me some times. In this case, it’s actually distracting just how much documentation there is for queries like “dietpi Call to undefined function curl_init()” but the problem is the answers are for distros that no longer exist and PHP versions ranging from 7 to 5 to even 4 and, of course, the names of everything changing alont the way, the preferred web server changing from Nginx back to Apache, etc.

So here’s my attempt to litter the web with yet more search results, but hopefully this helps the next “me” that’s trying to get an updated system working again at 3am.