Our magazine ads, before they were typeset…

While going through some random disk images, I found some text files that seem to be the Sub-Etha Software ads, before we took them to the printshop to have them typeset by a professional.

First, this looks like the first ad we planned to run in Rainbow magazine, before we got a deal to do a quarter page inside. Note the company name was going to be Forty-Two Technology and the phone # listed was before I had a dedicated line.

Multi-Basic-- Ever wonder why, with 128K or 512K, you cannot use even 32K under RS-Dos?  Well now there's MultiBasic, making possible, without adding ANY commands, the use of ALL of your CoCo3's memory by basic.  Have several programs loaded in memory at once, able to call subroutines from each other, move between each other, even load other programs from disk, all without variable loss or interruption of program flow.

Shadow BBS-- Finally, a CoCo3 RS-Dos BBS with power, speed, and flair. Uses RS232 Pak or serial port. Features include full ANSI, X/Y Modem, 28 line 40/80 column support, 240 byte onscreen status window, software clock, up to 255 independently numbered message areas, borderlines, one-liner discussions, surveys, auto-messages, doors to external programs, user profiles, full sysop utilities, much, much more! See for yourself, call ShadowBBS HQ at (409)63-REALM. Order thru BBS or thru: Forty-Two Technology, PO Box 4242, Lufkin, TX 75901. (409)637-7604.

Next up is the prototype for the ad we did run, featuring MultiBASIC and SHADOW BBS by Terry Todd. We didn’t have a dedicated phone number yet, so the 632-4200 was just a made up one for the mockup.

 _____________________________________________________________
| |
| |
| |
| |
| |
| |
| MULTIBASIC - Use all 128K/512K of your CoCo 3 without |
| learning ANY new commands! Have several programs loaded |
| at once sharing subroutines and variables! Load programs |
| without losing variables, and more! INTRO. PRICE: $24.95 |
| |
| SHADOW BBS - An RS-Dos BBS with Power, Speed, and Flair! |
| ANSI, X/Y Modem, Clock, Surveys, AutoMessage, Up to 255 |
| Msg Areas, User Profiles, Doors, Borderlines, Full SysOp |
| Utilities, and Much, Much More! Runs on 128K CoCo 3 with |
| Disk Drive(s), Serial Port OR RS232 pak! Call and see |
| for yourself! (409) 63-REALM INTRO. PRICE: $34.95 |
| |
| Sub-Etha Software Call or write for information! |
| P.O. Box 152442 Add $2.00 S&H and $3.00 C.O.D. |
| Lufkin, TX 75901 Texas residents add 8.25% tax. |
| (409) 632-4200 "Don't Panic!" |
|___________________________________________________________|

Next, another prototype… Much closer to what ended up being typeset and published – and even has the real phone number. These blank spots at the top where were the logo was going to go. I did these ASCII ones to show them exactly what we wanted.

 _____________________________________________________________
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| Ever wonder why, with a 128K or 512K CoCo 3 you cannot |
| even use 32K under RS-Dos? Well, now there's MultiBasic, |
| making possible without adding ANY commands the use of |
| your CoCo 3's "hidden" memory by Basic. Have several |
| programs loaded in memory at once able to call |
| subroutines from each other. Move between programs and |
| load other programs from disk without variable loss or |
| interruption of program flow. A "must-have" utility for |
| Basic programmers! |
| |
| INTRODUCTORY PRICE ............................... $24.95 |
| |
| |
| /) Shadow BBS (\ |
| Complete RS-Dos BBS with Low Hardware Requirements! |
| |
| Finally, an RS-Dos CoCo 3 BBS with power, speed, and |
| flair! Uses RS232 Pak OR serial port! Features include |
| ANSI, X/Y Modem file transfers, 28 line 40/80 column |
| support, 240 byte on-screen status window, software |
| clock, up to 255 independently numbered message areas, |
| borderlines, one-liner discussions, surveys, automessage, |
| doors to external programs, user profiles, full SysOp |
| utilities, and much, much more! And unlike most BBSs |
| you've seen, no hard drive, RS232 Pak, or memory upgrade |
| is required! Shadow BBS will run on a 128K CoCo 3 with |
| one disk drive and a modem, yet it is capable of taking |
| advantage of all the hardware your system includes. A |
| full appreciation of Shadow BBS comes not, however, from |
| it's many features or it's low hardware requirements, but |
| from the flair and smoothness of the program itself. We |
| want you to see what this incredible BBS can do. Call |
| The Shadow's Realm, the official Shadow BBS HQ system, at |
| (409) 63-REALM (300/1200 Baud, 24 Hrs.) and see for |
| yourself! |
| |
| INTRODUCTORY PRICE ............................... $34.95 |
| |
| |
| Sub-Etha Software Call or Write for Information! |
| P.O. Box 142442 Add $2.00 S&H and $2.50 C.O.D. |
| Lufkin, Texas 75915 Texas residents add 8.25% tax. |
| (409) 639-ETHA [3842] "Don't Panic!" |
|___________________________________________________________|

And this one, AD4.txt, is another variation:

_____________________________________________________________
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|___________________________________________________________|
|| ||
|| *: MultiBasic :* ||
|| More Memory for Basic without Learning New Commands! ||
|| ||
|| Ever wonder why, with a 128K or 512K CoCo 3 you cannot ||
|| even use 32K under RS-Dos? Well, now there's ||
|| MultiBasic, making possible without adding ANY commands ||
|| the use of your CoCo 3's "hidden" memory by Basic. ||
|| Have several programs loaded in memory at once able to ||
|| call subroutines from each other. Move between ||
|| programs and load other programs from disk without ||
|| variable loss or interruption of program flow. A ||
|| "must-have" utility for Basic programmers! ||
|| ||
|| INTRODUCTORY PRICE ............................. $24.95 ||
|| ||
|| ||
|| *: Shadow BBS :* ||
|| Complete RS-Dos BBS with Low Hardware Requirements! ||
|| ||
|| Finally, an RS-Dos CoCo 3 BBS with power, speed, and ||
|| flair! Uses RS232 Pak OR serial port! Features include ||
|| ANSI, X/Y Modem file transfers, 28 line 40/80 column ||
|| support, 240 byte on-screen status window, software ||
|| clock, up to 255 independently numbered message areas, ||
|| borderlines (quotes), one-liner discussions, surveys, ||
|| automessage, doors to external programs, user profiles, ||
|| full SysOp utilities, and much, much more! And unlike ||
|| most BBSs you've seen, no hard drive, RS232 Pak, or ||
|| memory upgrade is required! Shadow BBS will run on a ||
|| 128K CoCo 3 with one disk drive and a modem, yet it is ||
|| capable of taking advantage of all the hardware your ||
|| system includes. A full appreciation of Shadow BBS ||
|| comes not, however, from it's many features or it's low ||
|| hardware requirements, but from the flair and ||
|| smoothness of the program itself. We want you to see ||
|| what this incredible BBS can do. Call The Shadow's ||
|| Realm, the official Shadow BBS HQ system, at (409) ||
|| 63-REALM (300/1200 Baud, 24 Hrs.) and see for yourself! ||
|| ||
|| INTRODUCTORY PRICE ............................. $34.95 ||
||_________________________________________________________||
| |
| Sub-Etha Software Call or Write for Information! |
| P.O. Box 152442 Add $2.50 S&H and $3.50 C.O.D. |
| Lufkin, Texas 75915 Texas residents add 8.25% tax. |
| (409) 639-ETHA [3842] "Don't Panic -- We Ship Fast!" |
|___________________________________________________________|

I guess by this next one we trusted the typesetting person, since it was just the raw text:

Happy Holidays From...

SUB-ETHA SOFTWARE

"In Support of the CoCo"

Thanks to those who stopped by our booth at the CoCo Fest!

*: MiniBanners :*
Multiple Line Banners on ANY Printer!

NEW! Create single or multiple line banners with adjustable heights and
widths. Up to 16 lines of text with independently sized characters. Even
works with daisy wheel and non-graphic printers! Includes over 30 fonts!

INTRODUCTORY PRICE ................................................ $14.95

*: MultiBasic :*
More Memory for Basic without Learning New Commands!

PRETTY NEW! Tired of being limited to 22K for Basic? We were too, so we
created MultiBasic, a utility which allows you to use the "hidden" memory of
your CoCo 3 without learning ANY new commands. Load multiple programs, disk
chain, share subroutines and variables, all without interrupting program flow.

HOLIDAY PRICE ..................................................... $24.95

*: Shadow BBS :*
Complete RS-Dos BBS with Low Hardware Requirements!

ALSO PRETTY NEW! Finally, an RS-Dos BBS with power, speed, and flair. Uses
RS232 Pak OR serial port. Does not require a hard drive or memory upgrade!
Features: SysOp Utilities, Up to 255 Msg Areas, X/Y Modem, ANSI, Status
Window, Clock, AutoMessage, User Surveys and Profiles, and too much more to
mention here! A full appreciation of Shadow BBS comes not, however, from it's
many features or low hardware requirements, but from the flair and smoothness
of the program itself. We want you to see what this BBS can do. Call the
Shadow's Realm, the official Shadow BBS HQ, at (409) 63-REALM (300-2400 Baud,
24 Hrs.) and see for yourself!

HOLIDAY PRICE ..................................................... $34.95

I wonder what else I will find as I go through these things…

The Hitchhiker Phenomenon (my late 1980s book report)

In the late 1980s, I had a writing assignment and decided to write about The Hitchhiker’s Guide to the Galaxy by Douglas Adams. I recently found this document and decided to share it. It was written in Deskmate for the Radio Shack Color Computer.

Today we know far, far more about Douglas Adams and his life and writings, so I am curious to see what we “thought we knew” back then.

R.I.P., Douglas Adams. You are still missed.


The Hitchhiker Phenomenon

This is the story of Douglas Adams’ now famous “Hitchhiker Trilogy.” It is a story of amazing success, and it all began very simply. It began with a field.

In the early seventies, Douglas Adams was less than the successful writer he is today. A native of England, he was hitchhiking his way around Europe. One evening he found himself lying drunk in a field near Innsbruck. He had been carrying with him “The Hitchhiker’s Guide to Europe” by Ken Walsh, and as the world spun lightly around him, he thought someone should write a hitchhiker’s guide to the galaxy as well.

This idea stayed in the back of his mind for the next six years while he straightened himself up and got an education at Cambridge. After getting “educated,” he would soon find employment in such various fields as chicken shed cleaning, body guarding, and eventually a script writer for such BBC television programs as Monty Python and Dr. Who. His work on these shows displayed his ability for comedy and science fiction writing, which he would soon combine.

Adams was directing a Cambridge Footlights show when he met Geoffrey Perkins, who worked at BBC radio. The link between BBC and Adams now had been made. He had an idea, and he had an opportunity.

He originally wanted to do a series about “The Ends of the Earth” just to see how many ways of destruction he could devise. This would require a character to be there to explain what was going on. To explain why the character was there, Adams decided to make him a researcher for a book: The Hitchhiker’s Guide to the Galaxy. His idea had now evolved into something useful. Now all that had to be done was to get it approved by the BBC Radio Light Entertainment Department.

His idea was submitted, and approved. “…The script was commissioned in the first place not out of a burning desire to do a sci-fi comedy but because the Chief Producer at the time was rather taken with a sketch Douglas had written…about a Kamikaze pilot being briefed for his ninteenth mission.” (Scripts/P.32) Now all Adams had to do was make it.

Radio series at that time were still primitive. Adams knew exactly what he wanted from the start. He wanted Hitchhiker’s to sound like a rock ablum. “I wanted the voices and the effects and the music to be so seamlessly orchestrated as to create a coherent picture of a whole other world…” (Scripts/P.14) he recalls. Even the theme was planned. He wanted an electronic tune with a banjo in it, so the choice of the Eagles “Journey of the Sorcerer” seemed perfect

Sound effects produced for the series are still some of the greatest ever created. (The radio crew spent more time making sounds than other shows spent on their whole program!) Finally, after all of the sounds, music, and actors had been assembled, the story was ready to be told. On March 8, 1978 the first episode was aired.

The story followed the adventures of Arthur Dent. He is rescued by his friend Ford Prefect when the Earth is destroyed to make way for an interstellar bypass, and Arthur begins his cosmic journey. They meet up with Zaphod Beeblebrox, ex-president of the Galaxy, and his companian Trillian, a sexy space-cadet originally from Earth, as well as Marvin, a depressed robot.

This newly assembled crew sets out on a fantastic adventure which reveals the ultimate answer to life, the universe, and everything, which is fourty-two, and the ancient quest to discover what the actual question is. The question was to be calculated by a giant computer called the Earth, which was built and ran for mice.

Zaphod was also on a mission that he didn’t know about. He was going to find the man who rulled the Universe. Detours along the way take them to the legendary planet of Magrathea, The Restaurant at the End of the Universe, and the evil planet Frogstar.

This exciting adventure is hampered and assisted by amazing plot twists. Adams would decide to have his characters flushed out unprotected into space just to see what would happen. Many of his throw-away jokes, such as a robot with personality disorders, were so popular that he kept them. In fact, the whole story soon gained tremendous following in England, and the BBC had to fight to win back the rights for merchandising.

Suprisingly, many of the subjects written about were not as far-fetched as they might seem. “I…find things that…are self-defeating are funny,” (Zest/P.28) Adams recalls. For instance, a wasteland planet which is encountered in the series was a victim of an economic phenomen known as the Shoe Event Horizon. The whole economy mutated into nothing but shoe shops causing a total colapse. Adams claims to have gotten this concept from Oxford Street in London where he once spent three days trying to buy a pair of shoes. “You cannont hurl a brick…without hitting half a dozen shoe shops,” (Scripts/P.227) Adams claims. He says that “shop after shop, all virtually next to each other, carried exactly the same range, and were all out of stock of exactly the same styles and sizes.” (Scripts/P.227)

On this same planet, a delayed spaship in encountered. It is delayed by over nine-hundred years because it couldn’t take off until the supplies of lemon-soaked paper napkins were loaded. Again, this came from a real Adams experience. He was trying to make an important journey from London to Leeds, which he would have made by train if time were not important. Due to the bar not being loaded, the plane sat doing nothing for a half-hour, making the journey take more time than by train, and thus defeating the whole point of taking it. Adams reasons that in order for a plane to fly, it has to have “a pilot,…a couple of wings,…enough fuel,…coffee and biscuits.” (Zest/P.28)

The original radio series projected Adams into a spotlight. He was asked to write a book version. Adams never thought he “would have have the sheer tenacity or bloody-mindedness required to sit down and write a full length novel,” (Zest/P.22) but he did and the books all became instant best-sellers. A seven episode television show followed, and then a two-record album. The Hitchhiker Phenomenon was rolling.

Each form it took was slightly different. Some major events were drastically altered by Adams, but the basic story line manages to end up the same. This made Hitchhiker’s new to old fans each time they experienced a different telling. When the long rumored movie is produced, Adams plans to tell the story once again from a different perspective.

Recent updates to the Hitchhiker series include a fourth book, and the original radio series and TV shows are being broadcast on public radio and television stations all over America. A computer game has also been created, and another is planned. A fifth book has been publically denied by Adams, which means he’s working on one.

The Hitchhiker Phenomenon has been around for almost ten years and shows no sign of slowing. Fans all over the world appear at standing-room-only autograph sessions sporting their Hitchhiker towels and Don’t Panic buttons. The devoted fans are out there, and his following will continue to grow. Douglas Adams didn’t create a simple story – he created an incredible phenomenon.

winget – like apt-get for Linux and brew for Mac?

I was today years old when I learned that winget is a thing for windows.

I powered up my ancient Lenovo ideapad FLEX 4 (so old, it cannot run Windows 11) today, and looked to see what updates where waiting. There were plenty in the Microsoft Store plus some in Windows Update. I only use this machine for running my vinyl cutter and laser engraver, so there is not much on it.

Due to the tiny SSD hard drive, I do have WinDirStat installed. It is a nice tool that will show you what is using up all your hard drive space.

I went to the WinDirStat website to look for updates:

WinDirStat – Downloads

My version was quite behind, so I was abouty to download the installer then I noticed this:

You may also install it with:

  • 📦 winget install -e –id WinDirStat.WinDirStat (or use winget upgrade subsequently)
  • 📦 scoop install extras/windirstat (requires scoop bucket add extras)
WinDirStat – Downloads

I am pretty sure I have used winget before to install some developer thing, but was unaware that it was used by other apps.

Typing “winget upgrade” showed me that it recognized several things on my PC:

C:\Users\alspl>winget upgrade
Name Id Version Available Source
-----------------------------------------------------------------------------------------------------------------------
WinMerge 2.16.18.0 x64 WinMerge.WinMerge 2.16.18.0 2.16.44.0 winget
Windows PC Health Check Microsoft.WindowsPCHealthCheck 3.6.2204.08001 3.7.2204.15001 winget
Microsoft ODBC Driver 17 for SQL Server Microsoft.msodbcsql.17 17.7.2.1 17.10.6.1 winget
Microsoft Visual Studio Code Microsoft.VisualStudioCode 1.91.1 1.96.4 winget
Visual Studio Community 2022 Microsoft.VisualStudio.2022.Community 17.4.1 17.12.3 winget
Dropbox Dropbox.Dropbox 216.4.4420 217.3.4243 winget
Google Chrome Google.Chrome.EXE 131.0.6778.267 132.0.6834.111 winget
Microsoft Visual C++ 2015-2022 Redistributa… Microsoft.VCRedist.2015+.x86 14.31.31103.0 14.42.34433.0 winget
Microsoft Visual C++ 2015-2022 Redistributa… Microsoft.VCRedist.2015+.x64 14.40.33810.0 14.42.34433.0 winget
Slack SlackTechnologies.Slack 4.39.93 4.42.115 winget
Lenovo Service Bridge Lenovo.ServiceBridge 5.0.2.9 5.0.2.17 winget
App Installer Microsoft.AppInstaller 1.23.1911.0 1.24.25200.0 winget
Dev Home Microsoft.DevHome 0.1900.687.0 0.1901.687.0 winget
13 upgrades available.

I tried “winget upgrade WinMerge.WinMerge” and saw it kick off and download the installer, then launch it. Very cool! It even has a spinning cursor while downloading :)

There is a “winget upgrade – all” option that should do all of them. The installers may pop up an authorization box you have to click on, so they are not fully automated, but still neat.

Did I do something on this computer years ago to install winget, or is it on any Windows 10/11 system just waiting to be used? Give “winget upgrade” a try on your PC and let me know if it works…

I have some upgrading to do.

Until next time…

Early 1980s BBSes and spinning cursors.

There is a whole generation that has no idea how much cool stuff folks did with text and backspace.

One of my favorites was the “spinning cursor.” Thanks to slow speeds of 300 baud modems, you could get some interesting effects by printing a letter, then printing a character like a slash (“/”), then a backspace, then a dash (“-“), then a backspace, then a backslash (“\”), then a backspace, then a vertical bar (“|”) or exclamation mark (“!”) if your system did not have the vertical bar. Then a backspace and the next letter of the message.

Apparently I got nostalgic about this effect some time ago. I just found this “Spinning Cursor” C project I wrote on the Online GDB compiler:

https://onlinegdb.com/56zozL_gRp

Go there and you can RUN the project and see it in all its glory…

Copy files to/from Insta360 app on iPhone/iPad

This topic seems to come up often, which is maybe it shouldn’t since Insta360 even documents these steps. Here is the background…

If you have an Insta360 360 camera such as the ONE X, ONE X2, X3 or X4, you can run the Insta360 App and download photos/videos from the camera for editing on your phone or tablet. You can then export them out and share them as normal photos, reframed videos or even 360 photos/videos.

If you want to backup the original files your phone/tablet downloaded, you can do that too by plugging the phone/tablet up to your computer via the USB sync cable.

On macOS, when you plug in the device and allow it to connect, it will show up under the Finder. You can select it and get a series of “tabs” in the Finder on what you want to look at. By selecting Files you have access to the file system of the device:

Look for the “Insta360” app and expand it:

If you want to copy .insv/.insp files TO the phone app, you can drag them over to the “IMPORT” folder. They will be copied via USB and placed into the location where the app will recognize them and you can edit them on your device.

If you want to copy files OUT of the phone, you cannot pick and choose, but you can drag the entire DCIM folder out from this window to wherever you want it copied and all the raw .insv/.insp/etc. files that have been imported into the Insta360 app will be copied there, likely much faster over USB than they would over WiFi from the camera in the first place. You will then be able to backup these files, or drag them into the desktop Insat360 app for editing.

It would be nice to have some kinda of automated script to do this (perhaps one that monitors for the phone/tablet to be connected then runs, backing up all the DCIM files automatically). If there is interest, I can look into trying to create one.

And if you want to read these instructions direct from Insat360, they are found in the manual. Here is the entry from the online X3 manual:

https://onlinemanual.insta360.com/x3/en-us/camera/filetransfer

We could do better…

That said… What would really be nice would be for Insta360 just to support the built-in Files system on iOS/iPadOS. Most of the apps I use allow me to export a file to anything mounted in my Files app. If you have installed Dropbox, OneDrive, Google Drive, etc., they show up and apps can just save a file there. If it is a cloud service, they will automatically sync to the cloud via that app. There are also FTP clients that look like drives, so you can export to a location and have it FTP to your own server. Likewise, most apps I use allow me to open from the Files app, so I can import files I have saved on Dropbox or whatever.

This also allows access to external USB hard disks or memory cards attached to the Lightning or USB-C port of the device using the appropriate adapter.

Insta360 may not be doing this because they knew they were planning to bring out their own cloud service they charge for. If they had allowed support for the native Files system, you’d be able to do all of this “for free” with any cloud service you were already using and there would be very little reason to subscribe to their subscription cloud service

But who knows… Maybe if enough of us ask them for it, we might see it. You can contact Insta360 and ask them here:

https://www.insta360.com/support

Until next time…

C program build date and time.

This one is just for fun, though I suppose I might not be the only one on the planet that ever needed to do this…

At my day job, I have a board that had a realtime clock, but no battery backup to retain the time. During startup, the system sends the current PC date and time (actually, it sends it in GMT, I believe, so looking at logs captured in different parts of the world will be easier — GMT is GMT anywhere on the planet ;-)

On startup, the board wants to log some things, but does not yet know the time. It had been using a hard-coded default time (like 1/1/2000). I wondered if the C compiler build date and time could be used to at least set the time based on when the firmware-in-use was compiled.

A quick chat with Bing’s AI (ChatGPT) and some experiments to make what it gave me far less bulky provided me with this:

int main()
{
    // Initialize time to when this firmware was built.
    const char *c_months = "JanFebMarAprMayJunJulAugSepOctNovDec";
    char monthStr[4];
    int year = 0;
    int month = 0;
    int day = 0;
    int hour = 0;
    int minute = 0;
    int second = 0;

    // “Mmm dd yyyy”
    strncpy(monthStr, __DATE__, 3);
    monthStr[3] = '\0';
    month = (strstr(c_months, monthStr) - c_months) / 3 + 1;

    day = atoi (&__DATE__[4]);
    year = atoi (&__DATE__[7]);

    printf ("%04d-%02d-%02d\n", year, month, day);

    // “hh:mm:ss”
    hour = atoi (&__TIME__[0]);
    minute = atoi (&__TIME__[3]);
    second = atoi (&__TIME__[6]);

    printf ("%02d:%02d:%02d\n", hour, minute, second);

    return 0;
}

This works by taking the compiler-generated macros of “__DATE__” and “__TIME__” and parsing out the values we want so they can be passed to a realtime clock routine or whatever.

In my case, this is not the code I am using since our embedded compiler handled __DATE__ in a different format. (It uses “dd-Mmm-yy” for some reason, while the standard C formatting appears to be “Mmm dd yyyy”.) But, the concept is similar.

Of course, as soon as I tested this, I found another issue. My board would power up and set to the build date (which is central standard time) and then when the system is connected, a new date/time is sent in GMT, which is currently 5 (or is it 6?) hours different, setting the clock back in time.

This makes log entries a bit odd ;-) but that’s a problem for another day.

Until then…

When a+b+c is not the same as b+a+c plus the Barr coding standard

DISCLAIMER: All compilers are not created equal. Different compilers may achieve the same result, but may take different steps to achieve that result. Optimizers and code generators can do wonderful things. Thus, if you want to leave a comment and say “compiler XYZ does not do that,” that is fine, but that is not the point of this. This is for those “other” compilers you don’t use, that do not behave that way…

During my embedded C programming career, there are some interesting optimizations I have been taught. Most of these are things I would never consider on a modern C compiler running on a system that has ample memory and CPU resources. But when you are on a microcontroller with 4K or RAM or 16K of program storage, sometimes you have to do things oddly to make it fit, or, if the CPU is slow, make it run fast enough.

True, False, or Not True or Not False?

Consider this:

bool flag = false;

if (flag)
{
// Do something
}

And “if” like this will be looking for a true result. Now, one compiler I work with has its own “TRUE” and “FALSE”, in uppercase, which all their code uses. Why? Maybe because they originated before the stdbool.h header file was added to the C standard and defined an official “true” and “false” in lowercase. Fortunately, they currently provide a stdbool which will undefine the uppercase ones (if the compiler is set to NON-case sensative — yep, by default “foo” and “FOO” and “else” and “Else” are processed the same) and define lowercase ones:

#if !getenv("CASE")
// remove TRUE and FALSE added by CCS's device .h file, only if
// compiler has case sensitivty off.

#if defined(TRUE)
#undef TRUE
#endif

#if defined(FALSE)
#undef FALSE
#endif
#endif

typedef int1 bool;
#define true 1
#define false 0
#define __bool_true_false_are_defined

With 0 representing false, and 1 representing true, the “if” works — anything that is not 0 will be processed. In a normal compiler:

if (0)
{
printf ("This will not print.\n");
}

if (1)
{
printf ("This will print\n");
}

if (42)
{
printf ("This will print\n");
}

On my Radio Shack Color Computer’s 6809 microprocessor, I expect such an “if” test compiles into assemble code that represents something like “branch if not zero”. I would expect every CPU has a similar instruction.

So checking for true (not 0) should be as fast as checking for false (0), assuming there is a similar instruction for “branch if zero.”

However, what if the CPU uses a different number of instruction cycles for a “branch if zero” versus “branch if not zero”? If that were the case, these might have different execution speeds:

if (flag == true)
{
// Do something...
}

if (flag == false)
{
// Do something...
}

But that seems unlikely, and is not the point of this post. (If you are aware of any CPU where this would be the case, please leave a comment.)

Some company coding standards I have used said to never use just “if (x)” but instead write out what it actually means. While you and I are experts and clearly know what the “if (x)” does, as should any programmer who knows programming, what if they don’t? In that case “if (x == true)” and “if (x == false)” are impossible to misunderstand, and should generate the same code as “if (x)” and “if (!x)”.

Right?

But suppose you used a crappy “C-like” compiler, and it had a “test for zero” which is used for “if (flag == false)” but used something dumb like “compare against a number” when you did “if (flag == true)” or “if (flag)”… Like, the compiler saw a check for 0 and knew it could efficiently do that… but if it was not zero, it did a compare against a number, resulting in something like…

load #1 in to some accumulator
compare register holding "flag" against accumulator
branch if equal (or if not equal)

That can generate some extra code each and every time you check for “true”, so checking for “not false” might save a few bytes every time.

Because of that, I often just default to doing this:

if (flag != false)
{
// Do something...
}

And this looks stupid. But might save enough bytes to make something compile that otherwise would not fit.

Hopefully you have never had to work in such a constrained environment with such a crappy C-like compiler.

The good news is, by changing to doing this, it works the same on “real” compilers but “might” make smaller or faster code on bad compilers.

But I digress…

Adding it all up…

I really wanted to write this about something I had never considered:

#define HEADER_LENGTH 5
#define CRC_LENGH 2

unsigned int messageSize = HEADER_LENGTH + payloadLength + CRC_LENGTH;

If the message protocol uses a format like “[HEADER][PAYLOAD][CRC]”, writing out the C code like that makes it easy to visualize what the message bytes look like.

The compiler would be seeing that code as:

unsigned int messageSize = 5 + payloadLength + 2;

A compiler might be doing…

  • Set messageSize to 5
  • Add payloadLength to messageSize
  • Add 2 to messageSize

But if you grouped the #define values together:

unsigned int messageSize = HEADER_LENGTH + CRC_LENGTH + payloadLength;

A good compiler might be changing that to:

unsigned int messageSize = 5 + 2 + payloadLength;
...
unsigned int messageSize = 7 + payloadLength;

…which results in:

  • Set messageSize to 7
  • Add payloadLength to messageSize

And if you deal with hundreds of messages where this might be calculated, that savings can really add up.

I would hope a real/smart compiler might be able to detect this and optimize the constants together … but I know this is not guaranteed to be the case.

The best thing about standards…

And as a bonus, earlier I posted asking about C coding standards trying to find one my employer could adopt, instead of rolling our own. Bing CoPilot led me to a few, including this one specifically for embedded C:

Embedded C Coding Standard | Barr Group

This “Barr C” standard has many things I have already forced myself to start doing, and does look promising. You can but a paperback book for the standard for $6 on Amazon, or download the book free as a PDF. I plan to go through it and see what all it discusses.

One thing I like about the approach is gives a reason for each of the coding standard things is presents. For example, braces:

Rules:

a. Braces shall always surround the blocks of code (a.k.a., compound
statements), following if, else, switch, while, do, and for statements; single statements and empty statements following these keywords shall also always be surrounded by braces.

b. Each left brace ({) shall appear by itself on the line below the start of the block it opens. The corresponding right brace (}) shall appear by itself in the same position the appropriate number of lines later in the file.

Reasoning:

There is considerable risk associated with the presence of empty
statements and single statements that are not surrounded by braces. Code constructs like this are often associated with bugs when nearby code is changed or commented out. This risk is entirely eliminated by the consistent use of braces. The placement of the left brace on the following line allows for easy visual checking for the corresponding right brace.

barr_c_coding_standard_2018.pdf

When I started learning C back in the late 1980s, it was the pre-ANSI K&R C. Thus, I learned C the way the books I had showed it:

if (something) {
// Do something
} else {
// Do something else
}

The placement of the “{” on the first line seems to be referred to as “line saver” in some of the code editors I use. It was at a job where their standard says “line them up so you can see what goes to what” that I had to change my style:

if (something)
{
// Do something
}
else
{
// Do something else
}

Now the start of each code block has the start brace and end brace on the same column, making it much easier to spot rather than having to look at the ends of lines or some characters in to a line.

I hated that at first, but now I am used to it.

I also used to do things like this:

if (something)
DoSomething();
else
DoSomethingElse();

Somewhere on this site, I have written about this at least once or twice. This breaks when someone adds something without thinking about the braces:

if (something)
DoSomething();
WriteToLog(); // added this
else
DoSomethingElse();

Without the braces, trying to compile this would at least give an error:

main.c: In function ‘main’:
main.c:31:5: error: ‘else’ without a previous ‘if’
31 | else
| ^~~~

BUT, if you did not have the else…

if (something)
DoSomething();
WriteToLog();

That code might “look” good, but running it would do something if the case was true, but would then ALWAYS write to the log… Because C is seeing it like this:

if (something)
{
DoSomething();
}

WriteToLog();

And I have now seen a modern programmer, brought up on scripting languages that made use of tabs rather than braces, make this mistake working on C code they were not really familiar with.

But I digress. Again.

More to come when my book arrives and I start reading through it. Unless someone presents me a better alternative, I think this one may suffice. The book is cheap, it can be downloaded free (so it is searchable) and the items I have spot checked seemed reasonable.

If you have ever worked with the Barr-C coding standard, I’d love to hear your thoughts in the comments.

Until then…

C has its limits. If you know where to look.

Thank you, Bing Copilot (ChatGPT), for giving me another “thing I just learned” to blog about.

In the early days of “K&R C”, things were quite a bit different. C was not nearly as portable as it is today. While the ANSI-C standard helped quite a bit, once it became a standard, there were still issues when moving C code from machines of different architectures — for example:

int x;

What is x? According to the C standard, and “int” is “at least 16 bits.” On my Radio Shack Color Computer, and int was 16-bits (0-65535). I expect on my friend’s Commodore Amiga, the int was 32-bits, though I really don’t know. And even when you “know”, assuming that to be the case is a “bad thing.”

I used a K&R C compiler on my CoCo, and later on my 68000-based MM/1 computer. That is when I became aware that an “int” was different. Code that worked on my CoCo would port fine to the MM/1, since it was written assuming an int was 16-bits. But trying to port anything from the MM/1 to the CoCo was problematic if the code had assumed an int was 32-bits.

When I got a job at Microware in 1995, I saw my first ANSI-C compiler: Ultra C. To deal with “what size is an int” issues, Microware created their own header file, types.h, which included their definitions for variables of specific sizes:

u_int32 x;
int32 y;

All the OS library calls were prototyped to use these special types, though if you know an “unsigned long” was the same as an “u_int32” or a “short” was the same as an “int16” you could still use those.

But probably shouldn’t.

In those years, I saw other compilers do similar things, such as “U32 x;” and “I16 y”. I expect there were many variations of folks trying to solve this problem.

Some years later, I used the GCC compiler for the first time and learned that the ANSI-C specification now had it’s own types.h — called stdint.h. That gave us things like:

uint32_t x;
int32_t y;

It was easy to adopt these new standard definitions, and I have tried to use them ever since.

I was also introduced in to the defines that specified the largest value that would fit in an “int” or “long” on a system – limits.h:

...
#define CHAR_MAX 255 /*unsigned integer maximum*/
#define CHAR_MIN 0 /*unsigned integer minimum*/

/* signed int properties */
#define INT_MAX 32767 /* signed integer minimum*/
#define INT_MIN (-32767-_C2) /*signed integer maximum*/

/* signed long properties */
#define LONG_MAX 2147483647 /* signed long maximum*/
#define LONG_MIN (-2147483647-_C2) /* signed long minimum*/
...

The values would vary based on if your system was 16-bits, 32-bits or 64-bits. It allowed you to do this:

int x = INT_MAX;
unsigned int y = UINT_MAX;

…and have code that would compile on a 16-bit or 64-bit system. If you had tried something like this:

unsigned int y = 4294967295; // Max 32-bit value.

…that code would NOT work as expected when compiled on a 16-bit system (like my old CoCo, or an Arduino UNO or the PIC24 processors I use at work).

I learned to use limits.h.

But this week, I was working on code that needed to find the highest and lowest values in a 32-bit number range. I had code like this:

uint32_t EarliestSequenceNumber = 4294967295;
uint32_t LatestSequenceNumber = 0;

And that works fine, and should work fine on any system where an int can hold a 32-bit value. (Though I used hex, since I know 0xffffffff is the max value, and always have to look up or use a calculator to find out the decimal version.)

Had I been using signed integers, I would be doing this:

int32_t LargestSignedInt = 2147483647;

Or I’d use 0x7fffffff.

As I looked at my code, I wondered if C provided similar defines for the stdint.h types.

stdint.h also has stdsizes!

And it does! Since all of this changed/happened after I already “learned” C, I never got the memo about new features being added. Inside stdint.h are also defines like this:

#define INT8_MAX  (127)
#define INT8_MIN (-128)
#define UINT8_MAX (255)

#define INT16_MAX (32767)
#define INT16_MIN (-32768)
#define UINT16_MAX (65535)

#define INT32_MAX (2147483647)
#define INT32_MIN (-2147483648)
#define UINT32_MAX (4294967295)

#define INT64_MAX (9223372036854775807)
#define INT64_MIN (-9223372036854775808)
#define UINT64_MAX (18446744073709551615)

…very similar to what limits.h offers for standard ints, etc. Neat!

Now modern code can do:

uint32_t EarliestSequenceNumber = UINT32_MAX;
uint32_t LatestSequenceNumber = 0;

…and that’s the new C thing I learned today.

And it may have even been there when I first learned about stdint.h and I just did not know.

And knowing is half the battle.

DJI Mic Mini and iPhone

Last month, DJI released the DJI Mic Mini. This tiny bluetooth microphone is about the size of a quarter, and as thick as maybe five quarters. It joins two big brothers – the DJI Mic ($249 for 2 TX + 1 RX + charging case, or $159 for 1 TX + 1 RX) and DJI Mic 2 ($349 for 2 TX + 1 RX + charging case, $219 for 1 TX + 1 RX, or $99 for just the microphone). The Mini is priced at only $169 for 2 microphones, a receiver and charging case making it $80 less than the Mic 2. You can also buy just a microphone and received for $89 or just the micrphone for $59. There are a few other options that include phone adapters for USB-C or Apple Lightning ports.

The Mic Mini claims up to 48 hours of battery life, giving is substantially longer use than the two older and larger models. But, it also has far less features. There is no built in memory so you cannot record and download audio files later — it is merely a bluetooth transmitting microphone.

With the DJI Mic 2 I have, I only have the microphone. After I received it, I quickly learned you couldn’t change any settings without owning the receiver as well! Whatever mode the DJI Mic 2 is shipped in is how you will forever use it. At least you can firmware update by plugging the Mic 2 up to a computer via USB and copying a downloaded firmware update file over to it like a flash drive.

Mic Mini and Firmware Updates

Without internal storage and no USB port, I wondered how firmware updates would be done on the Mini — if at all. It turns out, there is an app for that: DJI Mimo. It is available for both Android and iOS phones.

The app, currently at version V2.1.8, appears to have been mostly for connecting to DJI pocket cameras like the Osmo. Although the app lists DJI Mic and DJI Mic 2 as supported, it does not appear to actually connect with either of them. Instead, those microphones would connect with the Osmo (or other) DJI camera and then that connects to the phone and app.

But the Mic Mini is different. It is natively supported by DJI Mimo even without a DJI camera. Connecting the microphone via bluetooth to the phone will allow the mic to show up inside the DJI Mimo “Device Management” section. For here, you can download firmware updates for the Mini.

When I first connected my Mini to the app I was greeted with a firmware update. This update was download by the app then installed on the Mic Mini via the bluetooth connection. Very nice.

There are also a few configuration options:

  • Auto Off – “When enabled, transmitter will be automatically powered off in 15 min if not being connected to save power”
  • Power Button for Noise Cancellation – When enabled, press power button on transmitter to reduce noise”
  • Mic LED – on and off.

You can also access “About Devices” to see the Device Name (“DJI Mic Mini TX”, apparently not changeable) as well as its Device Serial Number and Firmware Version (currently 01.01.00.39).

Unfortunately, there does not seem to be much more you can do with the app. There is a microphone button on the screen, but that just brings up the Device Settings. I had expected to find some kind of recording capability, like a camera app and audio recorder. Perhaps in the future? It does seem this may be the first time they have had microphone support directly in the app.

Moving the ball forward…

Since there would have been no other way to do firmware updates on the Mic Mini, having this capability added to an app makes sense. Being able to customize a few settings is a nice bonus.

Hopefully, DJI is able to do something similar in the app for Mic and Mic 2 users that do not have the receiver and are unable to change any settings. (And uploading firmware via the app would be a much easier process than requiring access to a computer to download the update and transfer it to the Mic/Mic 2 over a USB cable.)

When I have time to work with the Mic Mini I will do a proper “review.” Until this, this is what I know…