decoding – Hackaday https://hackaday.com Fresh hacks every day Wed, 17 Jan 2024 23:16:54 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 156670177 Unraveling the Hackaday Podcast Hidden Message https://hackaday.com/2022/07/01/unraveling-the-hackaday-podcast-hidden-message/ https://hackaday.com/2022/07/01/unraveling-the-hackaday-podcast-hidden-message/#comments Fri, 01 Jul 2022 17:00:21 +0000 https://hackaday.com/?p=541934 When Elliot and I record the raw audio for the weekly podcast, it’s not unusual for us to spend the better part of two hours meandering from topic to topic. …read more]]>

When Elliot and I record the raw audio for the weekly podcast, it’s not unusual for us to spend the better part of two hours meandering from topic to topic. During one of these extended gab sessions, we wondered if it would be possible to embed a digital signal into the podcast in such a way that it could be decoded by the listener. Of course, storing and transmitting data via sound is nothing new — but the podcast format itself introduced some level of uncertainty.

Would the encoded sound survive the compression into MP3? Would the syndication service that distributes the file, or the various clients listeners will use to play it back, muddy the waters even further? Was it possible that the whole episode would get flagged somewhere along the line as malicious? After a bit of wild speculation, the conversation moved on to some other topic, and the idea was left to stew on one of our infinite number of back burners.

That is, until Elliot went on vacation a couple weeks back. In place of a regular episode, we agreed that I’d try my hand at putting together a special edition that consisted of pre-recorded segments from several of the Hackaday contributors. We reasoned this simplified approach would make it easier for me to edit, or to look at it another way, harder for me to screw up. For the first time, this gave me the chance to personally oversee the recording, production, and distribution of an episode. That, and the fact that my boss was out of town, made it the perfect opportunity to try and craft a hidden message for the Hackaday community to discover.

I’m now happy to announce that, eleven days after the EMF Camp Special Edition episode was released, ferryman became the first to figure out all the steps and get to the final message. As you read this, a coveted Hackaday Podcast t-shirt is already being dispatched to their location.

As there’s no longer any competition to see who gets there first, I thought it would be a good time to go over how the message was prepared, and document some interesting observations I made during the experiment.

Follow the Yellow Brick Road

Now as already mentioned, encoding digital data into audible sound is by no means a new technique. There was even a time when bog-standard audio cassettes were used to distribute commercial software. So rather than reinvent the wheel and come up with some new way of converting the first part of the message into audio, I went with a true classic: Kansas City standard (KCS).

In the late 1970s, KCS audio was even pressed onto vinyl records.

The product of a conference hosted by Byte magazine in 1975, KCS was intended to be a universal standard for storing digital data on audio cassettes. Initially designed to provide speeds of up to 300 bits per second, later variations managed to eke out slightly improved data rates at the cost of interoperability.

In the end KCS wasn’t much of a success, as individual companies seemed hell-bent on coming up with their own proprietary way of doing the same thing (sound familiar?), but it did lay important groundwork, and several encoder/decoder packages are still available today.

The initial 20 character message was encoded into a WAV file using py-kcs by David Beazley. As a spot check, I also ran the same message through a Perl implementation of KCS written by Martin Ward. Being more than a little worried that not many listeners would be familiar with a nearly 50-year-old audio format designed for cassette tapes, I added a little clue at the last minute in the form of Dorthy’s famous “Toto, I have a feeling we’re not in Kansas anymore” line from The Wizard of Oz. Finally, because secret messages always have to be played backwards, I reversed the whole thing and tacked it right onto the end of the edited episode before it went through Elliot’s final mastering script.

Note the very clear digital nature of the KCS data compared to the waveform of Dorthy’s speech. I was sure that anyone who opened this up in an audio editor would immediately recognize there was more than just noise here. But what would it look like after Elliot’s carefully crafted Podcast Perfection™ Bash script had at it?

Well, that’s different. Getting converted to stereo shouldn’t be a problem, but clearly the script came through and cleaned house during the MP3 encoding. Dorthy’s vocals are now much more prominent, which if you think about it, makes sense given the file was just run through a script designed to make podcasts sound better. But the data is now no longer a series of perfect square waves throughout, as it does a weird fade at the start. More importantly, we can now clearly see what appears to be the encoded data in the middle of the signal.

[Elliot: Compressor/limiter with a slow attack keeps our ever-changing volumes relatively constant for earbuds. And that digital audio section was waaay too loud originally.  If it had started out at the average loudness, it wouldn’t have been ducked at all.]

Despite my initial concerns, the MP3 version of the sound still decoded correctly by the tools mentioned previously, so long as it was first converted into the WAV file they were expecting. Confident that the message was intact, the episode was sent off to the syndication service for it to be pushed out the next morning.

Can You Hear Me Now?

Once the podcast was pushed out Friday morning, the real fun started. Would Spotify or Google Podcasts kick it back? Would some automatic trimming on their end cut out the signal because there was too much dead air in front of it? The short answer seems to be…nobody cares. I figure it’s a bit like the dinosaur erotica on the Kindle Store; once you’ve fully committed to letting folks upload whatever they want, you have to accept there’s going to be the occasional oddball.

As far as I can tell, the episode played as expected on all the different services out there. We had a couple people email us wondering if we knew about the “weird noise” at the end of the episode, and somebody in the Hackaday Discord wisely advised headphone wearers to steer clear of those last few seconds, but that was it.

But did the message survive, and how would users extract it? For the sake of argument let’s forget that we offer a direct download of the MP3 for each podcast, since obviously that would be the most direct route. I wanted to see if it was possible to pull the message out from the various podcast services. So I set Audacity up to record from a monitor of the system audio, opened the podcast in the web players for Spotify, Google, and TuneIn, and jumped right to the end of the track.

Sure enough, the audio captured directly from the web decoded properly using the KCS tools. Next I wondered if I could plug different podcast playing gadgets, such as my Pixel 4 or Echo Show into the computer, and record the audio from them directly.

Interestingly enough, this actually caused some issues. While the waveform looked the same in Audacity, py-kcs would routinely add garbage characters to the front of the intended string. Martin Ward’s Perl tool did slightly better, but would also run into the occasional error. Results were the same when recording from my Thinkpad T400 and Lenovo Chromebook. I’m not sure why this is, and would be interested in hearing from anyone who might have a theory.

Recording from AntennaPod on an Android device introduced unexpected errors.

That said, if you ignored the corrupt data, the appropriate message still got through. So I’m calling this one a partial win, since if you squint at the results just right, you can still move on to the next step.

The Truth is Out There

So now we have our answer. Not only is it absolutely possible to use an encoding scheme like Kansas City standard to put digital data into a podcast episode, but pulling the data back out on the receiving end is easily doable even if the listener doesn’t have access to the original MP3 file.

But what is the content of the decoded signal, and what do you do with it once you have it? Well, I never promised to tell you everything. Don’t worry though, this post should get you half-way there. After all, the intent was never to make this too difficult, it was only an experiment.

Of course, now that we know the concept is sound, the next time we hide a message in an episode of the podcast…expect to have your work cut out for you.

]]>
https://hackaday.com/2022/07/01/unraveling-the-hackaday-podcast-hidden-message/feed/ 7 541934 podcode_feat
PNG Image Decoding Library Does it With Minimal RAM https://hackaday.com/2021/07/17/png-image-decoding-library-does-it-with-minimal-ram/ https://hackaday.com/2021/07/17/png-image-decoding-library-does-it-with-minimal-ram/#comments Sun, 18 Jul 2021 02:00:21 +0000 https://hackaday.com/?p=487281 Want to display a PNG file on a display attached to an Arduino or other microcontroller board? You’ll want to look at [Larry Bank]’s PNGdec, the Arduino-friendly PNG decoder library …read more]]>

Want to display a PNG file on a display attached to an Arduino or other microcontroller board? You’ll want to look at [Larry Bank]’s PNGdec, the Arduino-friendly PNG decoder library which makes it much easier to work with PNG files on your chosen microcontroller.

The PNG image format supports useful features like lossless compression, and was generally developed as an improved (and non-patented) alternative to GIF files. So far so great, but it turns out that decoding PNG files on a microcontroller is a challenge due to the limited amount of memory compared to desktop machines. When the PNG specification was developed in the 90s, computers easily had megabytes of memory to work with, but microcontrollers tend to have memory measured in kilobytes, and lack high-level memory management. [Larry]’s library addresses these issues.

PNGdec is self-contained and free from external dependencies, and also has some features to make converting pixel formats for different display types easy. It will run on any microcontroller that can spare at least 48 K of RAM, so if that sounds useful then check out the GitHub repository for code and examples.

We’ve seen [Larry]’s wonderful work before on optimizing GIF playback as well as rapid JPEG decoding, and these libraries have increasing relevance as hobbyists continue to see small LCD and OLED-based displays become ever more accessible and affordable.

[PNG logo: PNG Home Site]

]]>
https://hackaday.com/2021/07/17/png-image-decoding-library-does-it-with-minimal-ram/feed/ 11 487281 PNG with microcontroller-featured
The Seedy World of Message Serialization https://hackaday.com/2020/06/10/the-ceedy-world-of-message-serialization/ https://hackaday.com/2020/06/10/the-ceedy-world-of-message-serialization/#comments Wed, 10 Jun 2020 14:00:40 +0000 https://hackaday.com/?p=413701 Look, I’ve been there too. First the project just prints debug information for a human in nice descriptive strings that are easy to understand. Then some tool needs to log …read more]]>

Look, I’ve been there too. First the project just prints debug information for a human in nice descriptive strings that are easy to understand. Then some tool needs to log a sensor value so the simple debug messages gain structure. Now your debug messages {{look like : this}}. This is great until a second sensor is added that uses floats instead of ints. Now there are sprinklings of even more magic characters between the curly braces. A couple days later and things are starting to look Turing complete. At some point you look up and realize, “I need a messaging serialization strategy”. Well you’ve come to the right place!

Message Serialization?

Message serialization goes by a variety of names like “marshalling” or “packing” but all fall under the umbrella of declaring the structure by which messages are assembled. Message serialization is the way that data in a computer’s memory gets converted to a form in which it can be communicated, in the same way that language translates human thoughts into a form which can be shared. A thought is serialized into a message which can be sent, then deserialized when received to turn it back into a thought. Very philosophically pleasing.

Message serialization is the way that data in a computer’s memory gets converted to a form in which it can be communicated.

Serialization are useful in different places. It’s possible to write a raw data structure onto disk to save it, but if the programmer wants that data to be easily readable by other languages and operating systems in the future they may want to serialize it in some way to give it consistent formal structure. Passing messages between threads or processes probably involves some manner of serialization, though maybe more limited. Certainly an obvious application is sending messages between computers over a network or any other medium.

Let’s back off the philosophical rabbit hole and define some constraints. (This is Hackaday afterall, not Treatise-a-Day). For the purposes of this post we’re interested in a specific use case: exchanging messages from a microcontroller. Given how easy it is to connect a microcontroller to anything from a serial bus to the Internet, the next step is giving the messages to be sent some shape.

What to Look For in a Serialization Scheme

The endless supply of “best!”, “fastest!”, “smallest!”, “cheapest!” options can lead to a bit of decision paralysis. There are many parameters which might affect your selection of one serialization format versus another, but a few are consistently important.

The first question to answer first is: schemafull or schemaless? Both strategies specify the format of your data, that’s the point of the message serialization after all. But what goes inside each message can be structured differently. A schemafull serialization scheme specifies the structure – and in some ways the content – of your data as part of the protocol. In a schemafull protocol a SensorReading message always has the same set of fields, say, SensorID (uint32_t), Timestamp (uint32_t), and Reading (float). The exact way to encode these fields into bytes is specified, serialized according to a protocol, as well as their existence and type. If your firmware receives a SensorReading, it knows exactly what shape and size the contents will be.

Given that, describing a schemaless protocol is easy, it has no constraints at all! JSON is perhaps the most prevalent example but there are certainly many others. The data is still encoded in a predefined way but the exact contents of each message is not specified ahead of time. In such a schema there is no predefined contents for our SensorReading message. Maybe it has a single float? Maybe ten integers? The receiver needs to check if each field is present and attempt to decode it to get at the contents.

Byproducts of Schema and Non Schema

“But wait!” you ask, “don’t those two methods work the same way?”. Well, yes, sort of. In some ways it’s more of a formalization of the contractual agreement between participants. Obviously to decode a schemaful message you must attempt to decode each field individually, just like in a schemaless system. But if you assume the format is specified ahead of time then other decode strategies like casting directly into a data structure, or code generating an encoder and decoder, may become available.

If structure isn’t your thing then the flexibility of a schemaless protocol might be in order.

There are other byproducts as well. Often a schemaful solution will allow the developer to specify the protocol separately from the implementation, then use a code generator to produce the serialization and deserialization functions in whatever language is needed. This may produce more efficient purpose-built code, but more importantly it makes it clear to the developer what is being communicated and how.

If structure isn’t your thing, then the flexibility of a schemaless protocol might be in order. If incoming data is to be treated as a whitelist, with an application only accepting exactly the fields it’s looking for, then the overhead of authoring and maintaining a schema may be more work than is warranted. Just make sure everyone is on the same page about what is sent and how.

When choosing libraries for microcontrollers, the other constraint to be aware of is what type of memory allocation is required. Sometimes there is a preference to entirely avoid the potential hassles of dynamic allocation altogether, which can constrain choices significantly. Requiring static allocation may force the developer to contort their code to deal with variable length messages, or force constraints like a fixed maximum size. But more than forcing a serialization scheme the memory management requirements constrain which libraries are available to use.

Let’s take a moment for an aside about libraries. It’s obviously possible to hand craft both the protocol and the library to decode it, avoiding most of the concerns mentioned above and producing exactly the code needed for any constraints. Sometimes this makes sense! But if you expect to extend the schema more than once or twice, and need it work with multiple languages or systems, than a standard serialization protocol and off the shelf libraries are the way to go. A common schema will give many options for languages and tooling across operating systems and platforms, all of which can literally speak the same language. So you can choose the library with a small memory footprint and static allocation for the tiny microcontroller, and the big dynamic fully featured one for the backend.

Favorite Serialization Schemes and Libraries

Here are some serialization schemes I’ve happily used in the past which I think are worth considering. Note, these recommendations are based on work I’ve done with microcontrollers in the past, so they are written in pure C for maximum compatibility and support static allocation.

JSON

The JSON specification is primarily composed of these excellent diagrams

JSON has become a sort of lingua franca of the API-driven Internet. Originally used as the serialization format for communicating the contents of JavaScript objects it now appears more or less everywhere, just like JavaScript. JSON is encoded to human readable and writable text, making it easy to inspect or edit in a pinch. It is schemaless and fundamentally allows storage of objects and arrays of objects which consist of typed key value pairs. If you can speak JSON, you can communicate with just about anything.

A side effect of JSON’s human-friendliness is a reliance on strings, which can make it a bit of a pain to deal with in C, especially when avoiding the use of dynamic allocation. One strategy to cope with this is a heavy reliance on flat buffers to hold the strings, and pointers to point in at various objects and fields without allocating memory for them. I’ve happily used jsmn to handle this when parsing JSON.

Jsmn is simple enough to be completely contained in a single header file and is a very, very thin thin wrapper around the pointer-based technique mentioned above. It validates that JSON objects are properly formatted, and allows the developer to get pointers to the various keys and values contained withing. It’s up to the developer to figure out how to interpret the strings therein, though it gives you their type. It’s a little like strtok on steroids.

MessagePack/msgpack

MessagePack is an interesting medium between human friendly JSON and a maximally efficient binary packed protocol. The homepage literally bills it as “It’s like JSON. But fast and small.” (Ouch, sorry JSON.) Like JSON, it’s schemaless, and is fundamentally composed of key/value pairs. Unlike JSON, it isn’t designed to be human readable, and the typing feels a little more explicit. See the figure below for a comparison of one message in JSON and MessagePack. It pretty much sells itself. MessagePack is fairly common, so finding libraries to read and write it is easy. I’ve used it in Rust and C, but there are at least one or two options for most major and many minor languages and platforms: the project claims support for at least 50. If you’re interested in a little more detail, [Al Willaims] wrote about it recently.

A message in JSON and MessagePack

When speaking MessagePack from a microcontroller, I’ve used CWPack. Documentation can be a little thin but the code is easy to trace through and is broken down very nicely into small functional blocks. In fact, that’s my favorite feature. CWPack is very easy to understand and use. Serializing and deserializing a message is a breeze with small, self contained functions. The biggest thing to watch out for is that it can sometimes be more manual than expected. For instance when sending a map, you must encode the start of the map, and number of elements, then for each element separately encode the key name then value. Once you get used to the CWPack way of doing things it produces some of the easiest to understand code posible.

Protocol Buffers/protobuf

Protocol Buffers are a heavy hitter in the schemeful messaging world. Originally built by Google it can, and probably has, been used to encode data for every kind of data link and application imaginable. Protobuf is specified by separate files in a dialect called proto, proto2, or proto3. These define messages, the basic hierarchical unit, and all the various fields and relationships between them. These .proto files are the absolute specification of what can and cannot be consumed by the encoders and decoders that are produced by code generation from the proto specification.

Because your Protobuf is separate from the implementation, referring to a “library” in this context really refers to the code generator used to produce the sources that get compiled into the final application. “protoc” is the generator provided by Google and for proto2 can produce implementations in Java, Python, Objective-C, and C++. The implementation for proto3 adds support for Dart, Go, Ruby, and C#. But that’s just Google’s official tooling, and there are many, many more options available. Remember that Protobuf specifies the bytes on the wire, not the API to interact with individual messages, so each code generator may produce radically different code to interact with the same messages.

From [Martin Kleppmann]’s excellent blog post
Protobufs can be extremely powerful, but it’s important to carefully consider what your message supports. Proto definitions specify if fields are required or optional, what their types are, and more. Typically a decoder verifies that all the metadata for each field exactly matches what it expects and will unable to decode anything else. If your system needs to support a heterogeneous mixture of software versions it’s possible to end up in a state where newer encoders and decoders will refuse to interact with messages encoded to a different version of your protocol.

All that said, especially for a large project, Protocol Buffers do an excellent job forcing all participants to agree on exactly what data is sent, and how. For microcontrollers, I typically turn to nanopb as my code generator of choice. The compact size of the generated code and support for static allocation make it easy to integrate into almost any project. Ultimately you hand it structs to encode and buffers to encode into, or visa-versa.

Go Forth and Encode

No matter your constraints, there is a message serialization format for every need. These are some of those which I have found useful but there are obviously many more options. Have a favorite format or library you use all the time? Chime in in the comments; I’d love to hear what to try next!

]]>
https://hackaday.com/2020/06/10/the-ceedy-world-of-message-serialization/feed/ 26 413701 MessageSerialization
Drone Gives Up Its Wireless Secrets To Zigbee Sniffer https://hackaday.com/2019/02/08/drone-gives-up-its-wireless-secrets-to-zigbee-sniffer/ https://hackaday.com/2019/02/08/drone-gives-up-its-wireless-secrets-to-zigbee-sniffer/#comments Sat, 09 Feb 2019 00:00:56 +0000 http://hackaday.com/?p=344539 There’s something thrilling about decoding an unknown communications protocol. You start with a few clues, poke at the problem with some simple tools, and eventually work your way up to …read more]]>

There’s something thrilling about decoding an unknown communications protocol. You start with a few clues, poke at the problem with some simple tools, and eventually work your way up to that first breakthrough that lets you crack the code. It can be frustrating, but when you eventually win, it can be very rewarding.

It seems that [Jason] learned this while decoding the wireless conversation between his mass-market quad and its controller. The quad in question, a Yuneec Q500, is one of those mid-range, ready-to-fly drones that’s targeted at those looking to get in the air easily and take some cool pictures. Unsure how the drone and controller were talking, [Jason] popped the covers and found a Zigbee chipset within. With the help of a $14 Zigbee USB dongle and some packet sniffing software from TI, [Jason] was able to see packets flowing, but decoding them was laborious. Luckily, the sniffer app can be set up to stream packets to another device, so [Jason] wrote a program to receive and display packets. He used that to completely characterize each controller input and the data coming back from the drone. It’s a long and strange toolchain, but the upshot is that he’s now able to create KML in real time and track the drone on Google Earth as it flies. The video below shows the build and a few backyard test flights.

Congratulations to [Jason] for breaking the protocol and opening up drones like this for other hackers. If you’re interested in learning more about Zigbee sniffing, you can actually hack a few smarthome gadgets into useful sniffers.

 

]]>
https://hackaday.com/2019/02/08/drone-gives-up-its-wireless-secrets-to-zigbee-sniffer/feed/ 2 344539 Yuneec Q500 Zigbee Protocol Decoded 6-7 screenshot
Cryptanalyse Your Air Con https://hackaday.com/2017/12/17/cryptanalyse-your-air-con/ https://hackaday.com/2017/12/17/cryptanalyse-your-air-con/#comments Sun, 17 Dec 2017 18:00:00 +0000 http://hackaday.com/?p=285936 Infrared remote controls are simple and ubiquitous. Emulating them with the aid of a microcontroller is a common project that hackers use to control equipment as diverse as televisions, cable …read more]]>

Infrared remote controls are simple and ubiquitous. Emulating them with the aid of a microcontroller is a common project that hackers use to control equipment as diverse as televisions, cable boxes, and home stereos. Some air conditioners can be a little more complicated, however, but [Ken]’s here to help.

The root of the problem is that the air conditioner remote was using a non-obvious checksum to verify if commands received were valid. To determine the function generating the checksum, [Ken] decided to bust out the tools of differential cryptanalysis. This involves carefully varying the input to a cryptographic function and comparing it to the differences in the output.

With 35 signals collected from the remote, a program was written to find input data that varied by just one bit. The checksum outputs were then compared to eventually put together the checksum function.

[Ken] notes that the function may not be 100% accurate, as they’re only using a limited sample of data in which not all the bytes change significantly. However, it shows that a methodical approach is valuable when approaching such projects.

Thirsty for more checksum-busting action? Check out this hacked weather station.

]]>
https://hackaday.com/2017/12/17/cryptanalyse-your-air-con/feed/ 19 285936 main4501_bg
Squoze Your Data https://hackaday.com/2016/11/22/squoze-your-data/ https://hackaday.com/2016/11/22/squoze-your-data/#comments Tue, 22 Nov 2016 15:01:44 +0000 http://hackaday.com/?p=230808 I have a confession to make. I enjoy the challenge of squeezing software into a tiny space or trying to cut a few more cycles out of a loop. It …read more]]>

I have a confession to make. I enjoy the challenge of squeezing software into a tiny space or trying to cut a few more cycles out of a loop. It is like an intricate puzzle. Today, of course, there isn’t nearly as much call for that as there used to be. Today even a “small” microcontroller has a ton of memory and resources.

Even so, there’s still a few cases where you need to squeeze those last few bytes out of memory. Maybe you are trying to maximize memory available for some purpose. Maybe you are anticipating mass production and you are using the smallest microcontroller you can find. Or maybe you’re doing the 1 kB Challenge and just want some advice.

One way to find techniques to maximize resources is to look at what people did “in the old days.” Digital Equipment computers once had a special character set called Squoze (or sometimes DEC Radix-50). This technique can be useful when you need to get a lot of strings into memory. The good news is that you can reliably get 3 characters into 2 bytes (or, as DEC did, 6 characters into 4 bytes). The bad news is that you have to pick a limited character set that you can use. However, that’s not always a big problem.

The Big Blue Connection

The key to Squoze is that you have to pick 40 characters that you want to encode. That’s enough for 26 letters, 10 digits, and 4 punctuation marks (a space plus whatever else you want). Notice that 26 letters means you have to pick upper case or lower case, but not both.

You might wonder why it was called DEC Radix-50 if you can only have 40 characters. The 50 is octal (base 8) which is 40 decimal. The Squoze name was actually used both by DEC and IBM. In the IBM scheme, though, a 36-bit word held two flags and 6 characters from a set of 50 (decimal 50, this time). Historically, the use of Squoze for symbol tables is why a lot of old compilers used 6 character symbols with only certain allowed characters (if you ever wondered about that).

How it Works

Once you have 40 characters in mind, you can treat them each as a digit in a base 40 number. Hold that thought and think about a regular decimal number. If you have a string of digits from 0 to 9 coming in, you can build a decimal value like this:

value=0

while not end of digits

   value=value * 10

   value = value + digit

end while

If you have the digits “643” then the value will progress from 0 to 6 to 64 to 643.

If you generalize to base 40, the “digits” are numbers from 0 to 39 (representing a character) and the *10 becomes *40 in the above pseudo code. If you prefer, you can think of it mathematically as the first digit is multiplied by 40 squared (1600), the second digit by 40 (40 to the first power), and the final digit by 1 (40 to the zero power).

Suppose, then, that we select 0 to represent a space, 1 to represent an A, 2 for a B, and so on. The string “A B” (that is a space in the center” would be 1, 0, 2. Running through the algorithm, the result would be 1602.

b40enc

Decoding is just the reverse. Starting with 1602, for example, you do an integer division by 1600 to get a 1 (A). Take that away leaving 2. Dividing by 40 gives you a space (0). Then there’s 2 left–a B–so the string is “A B” as you’d hope.

b40dec

Why Forty?

Why go through all this trouble? Why use 40 and not, say, 41 or 50? Think about the largest number you can represent with three base 40 characters. 39*1600+39*40+39 = 63999. That fits in a 16-bit word. If you went with base 41, the largest possible number is 68920. That’s too big for a 16-bit number.

The point is, using this scheme you can pack 3 characters (from your set of 40) into two bytes. Compared to normal ASCII characters, that’s a savings of 33%. Not much, but compared to other compression schemes it is simple to implement and it always saves 33%. Well, at least, roughly. If your text length isn’t evenly divisible by 3 you may have a padded character or two which reduces a little efficiency depending on the total text length.

Imagine a bunch of LCD menu entries stored in EPROM. Saving 33% could leave you some room for more strings or more unrelated features. Of course, you also need to factor in the size of the code and the character table. Frequently, you don’t need both encoding and decoding at run time, but there’s still some overhead to consider. You have to evaluate your needs and decide appropriately.

Enhancements

If you chafe at the 40 character limitation, you can pull a few stunts to get more at the expense of possible efficiency loss. For example, for some applications, you can assume the first letter of a string is uppercase and the rest are lower case. Or select your 39 most common characters, use one more as an escape character and then pick 40 more for a total of 79 characters. You could use the escape character as a “shift” character, too, if that works better for you.

Implementation

You can find a simple C-language implementation on GitHub. The make file generates two executables, one for encoding and one for decoding. You can define a symbol to avoid building the executables if you want to experiment with the code as a library.

The encoder and decoder will use a default character set if you like. You can also provide one yourself. The code is hardly optimized so if your application shares code and data space, you probably want to spend some time paring the code size down. However, for a demo or if your code space is separate and plentiful, it is probably good enough as it is.

The code is set up so you can run the encode and feed its output to the decoder:

$ ./encode | ./decode
Hello Hackaday. A man, a plan, a canal, Panama.
Characters in=48
(13012) HEL
(19800) LO 
(12843) HAC
(17644) KAD
(2637) AY.
(40) A 
(20854) MAN
(60801) , A
(652) PL
(2198) AN,
(40) A 
(4854) CAN
(2118) AL,
(641) PA
(22453) NAM
(3080) A. 
Bytes out=32
Full String (length=48):
HELLO HACKADAY. A MAN, A PLAN, A CANAL, PANAMA. 
$

Note that the characters are shifted to upper case by the encoder.

Worth It?

This is just one more trick to put in your toolbox. It isn’t for every project. You need to be able to live with the limitations. You also have to be able to accept the additional code and the runtime overhead. Depending on the data you have, there may be better options. For example, a data logger might store floating point numbers or some other scheme.

Huffman encoding, run length encoding, and other methods might do better–it depends on your application. However, I do think it is interesting to mine some of the old techniques and apply them to new solutions.

If you had fun with this, you should throw your hat in the ring with the 1 kB Challenge I mentioned before. Hackaday wants to see what you can do with a 1 kB compiled binary limit for a microcontroller-based project. Give it a shot and learn the space-saving techniques of old along the way.

]]>
https://hackaday.com/2016/11/22/squoze-your-data/feed/ 44 230808 b40 b40enc b40dec
Crack Mike Tyson’s Punch Out Bang Bang Passwords https://hackaday.com/2016/11/11/crack-mike-tysons-punch-out-bang-bang-passwords/ https://hackaday.com/2016/11/11/crack-mike-tysons-punch-out-bang-bang-passwords/#comments Fri, 11 Nov 2016 09:01:51 +0000 http://hackaday.com/?p=230755 [Bisqwit] has feelings about games that use exclamation points in his idiosyncratic walkthrough of all the nuances of the passwords in the famous Punch Out Bang Bang. As he states in …read more]]>

[Bisqwit] has feelings about games that use exclamation points in his idiosyncratic walkthrough of all the nuances of the passwords in the famous Punch Out Bang Bang.

As he states in his deeply weird (though in no way wrong) channel intro, when he’s not driving a bus or teaching Israeli dance, he works hard to understand the things around him. Naturally, a mysterious phone number shaped set of digits in a favorite game was a secret worth extracting.

The digits can represent every possible state in the game.  It uses a pretty simple decoding and encoding scheme, which he walks through. As he says, it all becomes clear when you can see the source code.

After working through all the quirks he is able to arbitrarily generate any state in the game and handle the exceptions (such as Nintendo USA’s phone number). You can see all his code here and try it out for yourself. Video after the break.

We’ve grown to respect [Bisqwit] as the explainer of all things console games. You will like his explanation of how to write a code emulator for an NES CPU.

]]>
https://hackaday.com/2016/11/11/crack-mike-tysons-punch-out-bang-bang-passwords/feed/ 5 230755 tyson_feat