FSK modem: bit/timing recovery

Started by DSP-Newbie January 23, 2007
Hi group,

This is probably a stupid question, but here goes...
I'm currently working on a software FSK-modem for decoding shortwave 
data transmissions. ( RTTY, SITOR-A, SITOR-B, etc)
( OS: Win-XP Pro, coding: Borland Delphi)

I have connected the receiver sound output to the soundcard, and have 
come this far, mostly by reading this NG:

I have implemented the bandpassfilters, the envelope detectors, and the 
decision circuit, and have even managed a FFT-transform to visualize 
the tone spectrum - note: I'm an experienced programmer, but definitely 
*not* a mathematician :-(

Screenshot: <http://users.pandora.be/dirk.claessens2/DSP/screen.jpg>

The sound card is configured to sample at 10240Hz, and the datablock 
size is set to 1024 (8 bit) samples. After filtering etc..., I end up 
with consecutive chunks of 1024 samples representing the data pattern 
of ones & zeroes.

Now here's my problem: how do I reconstruct/extract the actual data 
characters/bytes, timing etc...?? I know that RTTY starts with a start 
bit etc..., but how should this be extracted out of an array that looks 
like    11111111111100000001111111110000111110001111??

Thanks for any advice...

Dirk.


DSP-Newbie wrote:
> Hi group, > > This is probably a stupid question, but here goes... > I'm currently working on a software FSK-modem for decoding shortwave > data transmissions. ( RTTY, SITOR-A, SITOR-B, etc) > ( OS: Win-XP Pro, coding: Borland Delphi) > > I have connected the receiver sound output to the soundcard, and have > come this far, mostly by reading this NG: > > I have implemented the bandpassfilters, the envelope detectors, and the > decision circuit, and have even managed a FFT-transform to visualize the > tone spectrum - note: I'm an experienced programmer, but definitely > *not* a mathematician :-( > > Screenshot: <http://users.pandora.be/dirk.claessens2/DSP/screen.jpg> > > The sound card is configured to sample at 10240Hz, and the datablock > size is set to 1024 (8 bit) samples. After filtering etc..., I end up > with consecutive chunks of 1024 samples representing the data pattern of > ones & zeroes. > > Now here's my problem: how do I reconstruct/extract the actual data > characters/bytes, timing etc...?? I know that RTTY starts with a start > bit etc..., but how should this be extracted out of an array that looks > like 11111111111100000001111111110000111110001111?? > > Thanks for any advice... > > Dirk.
You've come a long way. Congratulations! The basic RTTY demodulated signal is just like any other TTY signal. To make sense of it, you need to know the polarity out of the decoder (inverted or not) and the code used (Probably ASCII, maybe Baudot), and the "framing". The framing may be synchronous (probably not) or asynchronous with stop and start bits in the data stream. (You also need to knw the bit rate, but to get this far, you evidently do.) A piece of hardware called a UART handles the details, and software UARTs are abundant. http://tinyurl.com/2al6av explains a lot. Come back with more questions if you need to. Jerry -- Engineering is the art of making what you want from things you can get. ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Jerry Avins wrote:
> DSP-Newbie wrote:
>> >> Now here's my problem: how do I reconstruct/extract the actual data >> characters/bytes, timing etc...?? I know that RTTY starts with a start bit >> etc..., but how should this be extracted out of an array that looks like >> 11111111111100000001111111110000111110001111?? >> >> Thanks for any advice... >> >> Dirk. > > You've come a long way. Congratulations! The basic RTTY demodulated signal > is just like any other TTY signal. To make sense of it, you need to know the > polarity out of the decoder (inverted or not) and the code used (Probably > ASCII, maybe Baudot), and the "framing". The framing may be synchronous > (probably not) or asynchronous with stop and start bits in the data stream. > (You also need to knw the bit rate, but to get this far, you evidently do.) > > A piece of hardware called a UART handles the details, and software UARTs are > abundant. http://tinyurl.com/2al6av explains a lot. Come back with more > questions if you need to. > > Jerry
Thanks for the reply Jerry, Are you suggesting I should send the bit stream to the soundcard output, and connect it to the PC's serial port? This might work for RTTY, but not for SITOR-A/B signals, since these are synchronous. I know it can be done without using the serial port, many programs exist that do it. Don't ask why then I'm not using one of them :0) I guess I have not stated my problem clearly enough. =The soundcard sends chunks of 1024 samples at a rate of 10 chunks/sec, sampled at 10240Hz. = If we assume a 100 baud signal, 1 bit time = 10msec. = Since the sampling frequence is 10240Hz, I see roughly 100 identical samples at the output of the decision circuit for each 1/0 present in the original data stream. (101 becomes 111111111111111000000000000000000011111111111111 ) Should I "compress" the data by a factor samplefreq./baud or some such?
On 2007-01-23, DSP-Newbie  wrote:
> > Screenshot: <http://users.pandora.be/dirk.claessens2/DSP/screen.jpg>
Neat!
> Now here's my problem: how do I reconstruct/extract the actual data > characters/bytes, timing etc...?? I know that RTTY starts with a start > bit etc..., but how should this be extracted out of an array that looks > like 11111111111100000001111111110000111110001111??
Look at some UARTs. You should be able to find some software or Verilog versions with some googling. Most work by oversampling the data by 16x (looks like I trimmed it, but I think you did 10x?). Then it looks for an edge, counts halfway into the bit time and then samples the data. Fancier ones might vote on 3 middle-of-bit samples. Then it just counts off another bit time and resamples. I'm not familiar with RTTY, but if every byte has a 'stop' bit, then you just restart this over and over, so slight rate changes never accumulate and should not affect you over the course of one byte. To demodulate PWM from WWV, where I had sampled 100 times for every bit and needed to find the phase of the bits so I could measure the pulsewidths, first I edge detected my binary stream by subtracting each sample from the next sample. That left me with an array of the positive- going edges. Then I created a histogram of their offsets mod 100 (my oversample factor). The peak (or even the average) gives you the phase offset (mod 100) and then you can count the 1s in each bin. -- Ben Jackson AD7GD http://www.ben.com/
"DSP-Newbie"  wrote in message 
news:mn.bcf37d719f5c170d.59994@way.invalid...
> I guess I have not stated my problem clearly enough. > =The soundcard sends chunks of 1024 samples at a rate of 10 chunks/sec, > sampled at 10240Hz. > = If we assume a 100 baud signal, 1 bit time = 10msec. > = Since the sampling frequence is 10240Hz, I see roughly 100 identical > samples at the output of the decision circuit for each 1/0 present in the > original data stream. > (101 becomes 111111111111111000000000000000000011111111111111 ) > > > Should I "compress" the data by a factor samplefreq./baud or some such?
I don't think you should bother feeding it back into the serial port - emulating a UART in software is simpicity itself compared to what you've already achieved. Here's the way UARTs do it. You need to generate a clock, and the really simple way to do this (but certainly not recommended for production strength for low SNR RTTY - see later) is by simply detecting edge changes. You know how many samples per bit there are (100), so you reset a counter when you see either a state change, or expect that the clock should change (100 samples later): note there will of course not always be a state change. Your bit value is taken half a bit time later (counter = 50 samples). Note that the counter is incremented each sample time. For RTTY there will always be a state change within six bits because it's a five bit code plus a start and a stop bit. The Start bit is a space (0) and the stop bit is a mark (1). The LSB is sent first. Your software should look for a combination of Space - x - x - x - x - x - Mark sequence to get in character (or 'frame') sync. With five bits, it's obviously not ASCII - it's called Baudot although back in my five hole paper tape days here in the UK it was known as Murray code. To get ASCII you'll need two lookup tables - one for Figure shift mode and one for Letter shift mode. Two unique codes switch between Letter shift and Figure shift. http://en.wikipedia.org/wiki/Baudot_code To generate a better clock when SNR isn't so good, it is common to use Costas loop. With the scheme above, a bit of noise will quite easily disrupt the clock by resetting it too often. To get a better data sample, it is common to take an aggregate, that can be weighted, of samples over the entire bit period. There are several other ways to demodulate too. Cheers, Howard
DSP-Newbie wrote:
> Jerry Avins wrote: >> DSP-Newbie wrote: > >>> >>> Now here's my problem: how do I reconstruct/extract the actual data >>> characters/bytes, timing etc...?? I know that RTTY starts with a >>> start bit etc..., but how should this be extracted out of an array >>> that looks like 11111111111100000001111111110000111110001111?? >>> >>> Thanks for any advice... >>> >>> Dirk. >> >> You've come a long way. Congratulations! The basic RTTY demodulated >> signal is just like any other TTY signal. To make sense of it, you >> need to know the polarity out of the decoder (inverted or not) and the >> code used (Probably ASCII, maybe Baudot), and the "framing". The >> framing may be synchronous (probably not) or asynchronous with stop >> and start bits in the data stream. (You also need to knw the bit rate, >> but to get this far, you evidently do.) >> >> A piece of hardware called a UART handles the details, and software >> UARTs are abundant. http://tinyurl.com/2al6av explains a lot. Come >> back with more questions if you need to. >> >> Jerry > > Thanks for the reply Jerry, > > Are you suggesting I should send the bit stream to the soundcard output, > and connect it to the PC's serial port? This might work for RTTY, but > not for SITOR-A/B signals, since these are synchronous.
Not at all. I wouldn't know how to make that work since tones aren't bits. Synchronous signaling dispenses with framing bits, but you have to know where a character starts. There's a character called "SYN" that is sent repeatedly for long enough so that the receiver can lock up. Nine is usually enough. The receiver starts anywhere and decodes 8 bits to form a character. If that is not SYN, it slips a bit and does it again. When the decoded character is SYN, the receiver adjusts its clock rate to match the transmitted clock and continues doing that throughout the transmission. The transmitter sends SYNs whenever it has no data.
> I know it can be done without using the serial port, many programs > exist that do it. Don't ask why then I'm not using one of them :0)
Of course. If you understand what the UART (or USART) does, it's not difficult to write software to simulate it.
> I guess I have not stated my problem clearly enough. > =The soundcard sends chunks of 1024 samples at a rate of 10 chunks/sec, > sampled at 10240Hz. > = If we assume a 100 baud signal, 1 bit time = 10msec.
That leaves no time for framing bits with asynchronous transmission. A Model 33 KSR runs at 110 bits.second, there being 11 bits per character. Since the receiver restarts its clock at the beginning of every character and the stop bits can be mistimed without problem, the receiver clock must match the transmitter clock within half a bit out of nine. Five percent accuracy would be adequate in the absence of jitter. Usually, one percent is specifies for each clock, so the timing mismatch doesn't exceed two percent.
> = Since the sampling frequence is 10240Hz, I see roughly 100 identical > samples at the output of the decision circuit for each 1/0 present in > the original data stream. > (101 becomes 111111111111111000000000000000000011111111111111 ) > > > Should I "compress" the data by a factor samplefreq./baud or some such?
You should extract the actual bits, yielding 101, and work with them. 111111111111111000000000000000000011111111111111 is an ideal case. you can tolerate 111011111101111000000000001110000011111101111111 and still extract the bit pattern if you have a rough idea where the edges of the bits really are. Jerry -- Engineering is the art of making what you want from things you can get. ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
DSP-Newbie wrote:
> Jerry Avins wrote: >> DSP-Newbie wrote: > >>> >>> Now here's my problem: how do I reconstruct/extract the actual data >>> characters/bytes, timing etc...?? I know that RTTY starts with a start bit >>> etc..., but how should this be extracted out of an array that looks like >>> 11111111111100000001111111110000111110001111??
Jerry, Howard, Ben, Thanks for the tips, it looks like I'll have to do it the hard way... Edge detection + sample counting & some bookkeeping between samples should do it. Back to the drawing board :0) Thanks - Dirk
Ben Jackson wrote:

> > Look at some UARTs. You should be able to find some software or Verilog > versions with some googling. Most work by oversampling the data by 16x > (looks like I trimmed it, but I think you did 10x?). Then it looks for > an edge, counts halfway into the bit time and then samples the data. > Fancier ones might vote on 3 middle-of-bit samples. Then it just counts > off another bit time and resamples.
I get the picture...
> I'm not familiar with RTTY, but if > every byte has a 'stop' bit, then you just restart this over and over, > so slight rate changes never accumulate and should not affect you over > the course of one byte. >
RTTY mostly uses Baudot 5 bit code, + 1.5 start & 1 stop bit. SITOR-B ( and many others ) use a 7-bit FEC code but are synchronous, so there I must jump on the bit stream and look for special sync characters to find the frame sync.
> To demodulate PWM from WWV, where I had sampled 100 times for every bit > and needed to find the phase of the bits so I could measure the > pulsewidths, first I edge detected my binary stream by subtracting each > sample from the next sample. That left me with an array of the positive- > going edges. Then I created a histogram of their offsets mod 100 (my > oversample factor). The peak (or even the average) gives you the > phase offset (mod 100) and then you can count the 1s in each bin.
Interesting tip! Thanks - Dirk
"DSP-Newbie"  wrote in message 
news:mn.c2ab7d715664af75.59994@way.invalid...
> > RTTY mostly uses Baudot 5 bit code, + 1.5 start & 1 stop bit.
Now you've got my memory working, I believe it's 1 start and 1.5 stop. I must admit I'd forgotten about using 1.5 bit times for a stop for RTTY. The baud rate for RTTY by the way is 45.45 baud. This will almost certainly mean you'll have a non-integer number of samples which very slightly complicates things. If you're using a PC to decode, an easy option is to use floating point for your clock and when you reset without a state change, subtract the floating point number of samples per bit from the counter rather than zeroing it. Howard
Howard Long wrote:
> "DSP-Newbie" wrote in message > news:mn.c2ab7d715664af75.59994@way.invalid... >> RTTY mostly uses Baudot 5 bit code, + 1.5 start & 1 stop bit. > > Now you've got my memory working, I believe it's 1 start and 1.5 stop. I > must admit I'd forgotten about using 1.5 bit times for a stop for RTTY.
Never count stop bits except to open a gate. When you get to the last data bit, wait some reasonable time and then start looking for a start bit. A stop bit is MARK and the signaling code is MARK idle. the stop-bit time is an approximate minimum -- approximate because receive and send clocks might be a few percent apart. There is no maximum time. Stuttering is allowed.
> The baud rate for RTTY by the way is 45.45 baud. This will almost certainly > mean you'll have a non-integer number of samples which very slightly > complicates things. If you're using a PC to decode, an easy option is to use > floating point for your clock and when you reset without a state change, > subtract the floating point number of samples per bit from the counter > rather than zeroing it.
I take it you've been there! :-) Jerry -- Engineering is the art of making what you want from things you can get. ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Hello Glen

> Well, the easiest way is that floating point should be > used for quantities that have a relative uncertainty, and fixed > point for ones that have an absolute uncertainty. > > Many physical measurements have a relative uncertainty, that is > the uncertainty in measuring increases as the quantity increases, > or at least that is all that is needed. This is often true of > length and time measurements over many orders of magnitude. > > For others the uncertainty stays constant, or only varies over > a small number of orders of magnitude. This is usually true > for money. I expect my checking account balance to the cent, > even if I have tens of thousands of dollars. It does surprise > me sometimes to see a house priced at $499,999, where $500,000 > is only 0.0002% more, though they could do $499,999.99.
Sadly, against my recommendations over more than twenty years, I know of many financial applications that use IEEE floats to represent money, and of course to this day I repeatedly spend hours each year explaining rounding errors away.
> Baud rate generation is usually done by taking a crystal oscillator > and dividing it down using a programmable counter.
But that assumes your timebase is going to be able derive the precise baud rate from integral division. Sometimes that's not the case. Certainly I'd agree it's the preferred scenario to be able to use an integral division. Cheers, Howard
Howard Long wrote:

(snip)

>>Since there is a few percent tolerance on the clock, you might as >>well assume there is always an non-integer number of samples. >>The UART will resync. on each start bit.
> Well, you are totally right, assuming we do, as I am sure we do in this > case, few symbols/frame and plenty of samples/symbol.
(snip)
>>There are a lot of problems that should not be done in floating >>point, and I would add this one.
Well, the easiest way is that floating point should be used for quantities that have a relative uncertainty, and fixed point for ones that have an absolute uncertainty. Many physical measurements have a relative uncertainty, that is the uncertainty in measuring increases as the quantity increases, or at least that is all that is needed. This is often true of length and time measurements over many orders of magnitude. For others the uncertainty stays constant, or only varies over a small number of orders of magnitude. This is usually true for money. I expect my checking account balance to the cent, even if I have tens of thousands of dollars. It does surprise me sometimes to see a house priced at $499,999, where $500,000 is only 0.0002% more, though they could do $499,999.99. Baud rate generation is usually done by taking a crystal oscillator and dividing it down using a programmable counter. -- glen
Hello Glen

"glen herrmannsfeldt"  wrote in message 
news:n6SdnU5oTc9Z6STYnZ2dnUVZ_sCinZ2d@comcast.com...
> Jerry Avins wrote: > > (snip) > >> stop-bit time is an approximate minimum -- approximate because receive >> and send clocks might be a few percent apart. There is no maximum time. >> Stuttering is allowed. > >>> The baud rate for RTTY by the way is 45.45 baud. This will almost >>> certainly mean you'll have a non-integer number of samples which very >>> slightly complicates things. > > Since there is a few percent tolerance on the clock, you might as > well assume there is always an non-integer number of samples. > The UART will resync. on each start bit. >
Well, you are totally right, assuming we do, as I am sure we do in this case, few symbols/frame and plenty of samples/symbol.
>>> If you're using a PC to decode, an easy option is to use floating point >>> for your clock and when you reset without a state change, subtract the >>> floating point number of samples per bit from the counter rather than >>> zeroing it. > > There are a lot of problems that should not be done in floating > point, and I would add this one. > > -- glen >
Glen, I respect your comment, but could you expand as to why not? Not a flame - a technical Q that could change the way I am doing things on a project right now. Thanks. Cheers, Howard
glen herrmannsfeldt wrote:
> John Monro wrote: > > (snip regarding fractional baud rates and such) > >> My guess is that it may have originated from the gearing of the >> mechanical decoding mechanism, relative to the speed of a 50 or 60 Hz >> synchronous motor driving the teleprinter. I am not really confident >> of this explanation though, because the only teleprinter I have >> examined closely used an AC universal motor with an centrifugal speed >> regulator that could be adjusted over a range of at least ten per cent. > > I do wonder some about the mechanical systems like the ASR33, if you > run them at just slightly slower than full speed such that the clutch > is just releasing and then pulls in again how well it works. I don't > believe the 2741 works the same way, though I am not so sure about it.
I believe that the ASR33 and 35 used synchronous motors. Jerry -- Engineering is the art of making what you want from things you can get. ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
John Monro wrote:

(snip regarding fractional baud rates and such)

> My guess is that it may have originated from the gearing of the > mechanical decoding mechanism, relative to the speed of a 50 or 60 Hz > synchronous motor driving the teleprinter. I am not really confident of > this explanation though, because the only teleprinter I have examined > closely used an AC universal motor with an centrifugal speed regulator > that could be adjusted over a range of at least ten per cent.
I do wonder some about the mechanical systems like the ASR33, if you run them at just slightly slower than full speed such that the clutch is just releasing and then pulls in again how well it works. I don't believe the 2741 works the same way, though I am not so sure about it. -- glen
glen herrmannsfeldt wrote:
> John Monro wrote: > > (snip regarding fractional baud rates and floating point) > >> With only 5 data bits and a stop bit the maximum timing allowed is >> around 8 per cent. Clocking for 45.0 Baud introduces 1 per cent error >> which will have a negligible effect on the error rate. > > One percent should be fine. I wonder why they quote them accurately. >
My guess is that it may have originated from the gearing of the mechanical decoding mechanism, relative to the speed of a 50 or 60 Hz synchronous motor driving the teleprinter. I am not really confident of this explanation though, because the only teleprinter I have examined closely used an AC universal motor with an centrifugal speed regulator that could be adjusted over a range of at least ten per cent. Regards, John
> The IBM 2741 runs at something close to 134.5 baud, which is not a > convenient fraction for any baud rate generator, but close enough in > any case. The character rate is supposed to be close to 14.8, > full speed for the selectric typewriter printing mechanism. > > -- glen >
John Monro wrote:

(snip regarding fractional baud rates and floating point)

> With only 5 data bits and a stop bit the maximum timing allowed is > around 8 per cent. Clocking for 45.0 Baud introduces 1 per cent error > which will have a negligible effect on the error rate.
One percent should be fine. I wonder why they quote them accurately. The IBM 2741 runs at something close to 134.5 baud, which is not a convenient fraction for any baud rate generator, but close enough in any case. The character rate is supposed to be close to 14.8, full speed for the selectric typewriter printing mechanism. -- glen
Howard Long wrote:
> "DSP-Newbie" wrote in message > news:mn.c2ab7d715664af75.59994@way.invalid... >> RTTY mostly uses Baudot 5 bit code, + 1.5 start & 1 stop bit. > > Now you've got my memory working, I believe it's 1 start and 1.5 stop. I > must admit I'd forgotten about using 1.5 bit times for a stop for RTTY. >
Yes, the 1.5 (or even 2) stop bits allowed time for a clutch to drop out and then pull in again on the early mechanically-decoded machines.
> The baud rate for RTTY by the way is 45.45 baud. This will almost certainly > mean you'll have a non-integer number of samples which very slightly > complicates things. If you're using a PC to decode, an easy option is to use > floating point for your clock and when you reset without a state change, > subtract the floating point number of samples per bit from the counter > rather than zeroing it. > > Howard > >
With only 5 data bits and a stop bit the maximum timing allowed is around 8 per cent. Clocking for 45.0 Baud introduces 1 per cent error which will have a negligible effect on the error rate. Regards, John
Howard Long wrote:
> "DSP-Newbie" wrote in message > news:mn.c2ab7d715664af75.59994@way.invalid... >> >> RTTY mostly uses Baudot 5 bit code, + 1.5 start & 1 stop bit. > > Now you've got my memory working, I believe it's 1 start and 1.5 stop. I must > admit I'd forgotten about using 1.5 bit times for a stop for RTTY. >
Hmmm... you're absolutely right!
> The baud rate for RTTY by the way is 45.45 baud. This will almost certainly > mean you'll have a non-integer number of samples which very slightly > complicates things. If you're using a PC to decode, an easy option is to use > floating point for your clock and when you reset without a state change, > subtract the floating point number of samples per bit from the counter rather > than zeroing it.
Actually, 50/75/100 baud are also common. 45.45 is mostly used by radioamateurs.
Howard Long wrote:
> "DSP-Newbie" wrote in message > news:mn.c2ab7d715664af75.59994@way.invalid... >> RTTY mostly uses Baudot 5 bit code, + 1.5 start & 1 stop bit. > > Now you've got my memory working, I believe it's 1 start and 1.5 stop. I > must admit I'd forgotten about using 1.5 bit times for a stop for RTTY. > > The baud rate for RTTY by the way is 45.45 baud. This will almost certainly > mean you'll have a non-integer number of samples which very slightly > complicates things. If you're using a PC to decode, an easy option is to use > floating point for your clock and when you reset without a state change, > subtract the floating point number of samples per bit from the counter > rather than zeroing it.
That's pretty close to 1KHz/22, not very hard to get with most clocks. For simplicity's sake, I usually clock at 16x, but 11 or 22 is also alright. A 1KHz clock will divide each transmitted bit into 22 parts. If that's too busy, sample the signal every 2 ms, using 2 0f three samples at the presumed middle of the bit, counting from the start bit. That will be pretty robust. Jerry -- Engineering is the art of making what you want from things you can get. ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯