Silicon ChipMax’s Cool Beans cunning coding tips and tricks - June 2021 SILICON CHIP
  1. Outer Front Cover
  2. Contents
  3. Subscriptions: PE Subscription
  4. Subscriptions: PicoLog Cloud
  5. Back Issues: PICOLOG
  6. Publisher's Letter
  7. Feature: The Fox Report by Barry Fox
  8. Feature: Techno Talk by Mark Nelson
  9. Feature: Net Work by Alan Winstanley
  10. Project: Touchscreen Wide-range RCL Box by Tim Blythman
  11. Project: Roadies’ Test Signal Generator by John Clarke
  12. Project: CONCRETO Speaker System by Allan Linton-Smith
  13. Feature: KickStart by Mike Tooley
  14. Feature: IO Cricket by Khairul Alam
  15. Feature: AUDIO OUT by Jake Rothman
  16. Feature: Make it with Micromite by Phil Boyce
  17. Feature: Circuit Surgery by Ian Bell
  18. Feature: Max’s Cool Beans by Max the Magnificent
  19. Feature: Max’s Cool Beans cunning coding tips and tricks by Max the Magnificent
  20. PCB Order Form
  21. Advertising Index

This is only a preview of the June 2021 issue of Practical Electronics.

You can view 0 of the 72 pages in the full issue.

Articles in this series:
  • (November 2020)
  • Techno Talk (December 2020)
  • Techno Talk (January 2021)
  • Techno Talk (February 2021)
  • Techno Talk (March 2021)
  • Techno Talk (April 2021)
  • Techno Talk (May 2021)
  • Techno Talk (June 2021)
  • Techno Talk (July 2021)
  • Techno Talk (August 2021)
  • Techno Talk (September 2021)
  • Techno Talk (October 2021)
  • Techno Talk (November 2021)
  • Techno Talk (December 2021)
  • Communing with nature (January 2022)
  • Should we be worried? (February 2022)
  • How resilient is your lifeline? (March 2022)
  • Go eco, get ethical! (April 2022)
  • From nano to bio (May 2022)
  • Positivity follows the gloom (June 2022)
  • Mixed menu (July 2022)
  • Time for a total rethink? (August 2022)
  • What’s in a name? (September 2022)
  • Forget leaves on the line! (October 2022)
  • Giant Boost for Batteries (December 2022)
  • Raudive Voices Revisited (January 2023)
  • A thousand words (February 2023)
  • It’s handover time (March 2023)
  • AI, Robots, Horticulture and Agriculture (April 2023)
  • Prophecy can be perplexing (May 2023)
  • Technology comes in different shapes and sizes (June 2023)
  • AI and robots – what could possibly go wrong? (July 2023)
  • How long until we’re all out of work? (August 2023)
  • We both have truths, are mine the same as yours? (September 2023)
  • Holy Spheres, Batman! (October 2023)
  • Where’s my pneumatic car? (November 2023)
  • Good grief! (December 2023)
  • Cheeky chiplets (January 2024)
  • Cheeky chiplets (February 2024)
  • The Wibbly-Wobbly World of Quantum (March 2024)
  • Techno Talk - Wait! What? Really? (April 2024)
  • Techno Talk - One step closer to a dystopian abyss? (May 2024)
  • Techno Talk - Program that! (June 2024)
  • Techno Talk (July 2024)
  • Techno Talk - That makes so much sense! (August 2024)
  • Techno Talk - I don’t want to be a Norbert... (September 2024)
  • Techno Talk - Sticking the landing (October 2024)
  • Techno Talk (November 2024)
  • Techno Talk (December 2024)
  • Techno Talk (January 2025)
  • Techno Talk (February 2025)
  • Techno Talk (March 2025)
  • Techno Talk (April 2025)
  • Techno Talk (May 2025)
  • Techno Talk (June 2025)
Max’s Cool Beans cunning coding tips and tricks I hope you’re familiar with the American comic strip called Dilbert, which is written and illustrated by Scott Adams. Have you ever noticed that there seems to be a Dilbert strip suitable for every occasion? In my previous Tips and Tricks (PE, April 2021) we discussed the Arduino’s random() function. Whenever I hear the term ‘random,’ I never fail to think of the Tour of Accounting strip from Thursday, 25 October 2001 (https://bit.ly/3uwjfnr) in which Dilbert is introduced to a junior accounting demon who is described as being a random-number generator. The junior demon is saying ‘Nine nine nine nine nine nine...’, which prompts Dilbert to ask, ‘Are you sure that’s random?’ The accounting manager replies, ‘That’s the problem with randomness – you can never be sure.’ Truer words were never spoken. So many recipes and flavours When you are first introduced to the concept of random numbers, everything seems to sort of make sense. It’s only later that you come to discover that there are many different ‘recipes and flavors,’ as it were. For example, your knee-jerk reaction to being told ‘here is a set of xxx random numbers in the range yyy to zzz’ might be to expect a ‘uniform distribution’ across the total allowable number space. In some cases, however, you might actually wish to see a ‘normal distribution’ a.k.a. ‘Gaussian distribution’ (https://bit. ly/2PNdtPz) or even a ‘custom distribution’ (https://bit.ly/3g3UqeT). Another consideration is how to implement a random number generator as part of a computer programming language. Part of this is the format of the statement you use to invoke the generator and the way in which it returns any results. In the case of the Arduino, for example, successive calls to random(-3, 3) will return random integer values selected from the set comprising −3, −2, −1, 0, 1, and 2. That is, the minimum value, which can be negative, 0, or positive, is ‘inclusive’ while the maximum value is ‘exclusive.’ In some languages, the minimum value is always 0 and/or the maximum value is inclusive. Also, the Arduino’s random() function is non-volatile, which means that – unless we take steps to prevent it – every time we power-up or reset the processor and re-run the program, we will receive the same sequence of pseudo-random values. By comparison, consider the RAND() function in Microsoft’s Excel spreadsheet Practical Electronics | June | 2021 d ata_ in d clock d ata_ out q Fig.3. D-type flip-flop. application. This function returns a real value between 0 and 1. I just opened Excel, placed my cursor in one of the cells, entered =RAND(), pressed the <Enter> key, and received the value 0.657414199. In this case, the function is volatile, because when I saved and subsequently reopened my spreadsheet, the new value displayed was 0.980944837. It’s up to us to take these values and manipulate them as we will. For example, if we wished to generate random integer values between 0 and 100, we would use =ROUND(RAND() * 100, 0). What this does is to take the real value between 0 and 1, multiply it by 100, and then round it to the nearest integer (ie, 0 decimal places). How about if we wanted to generate integer values between −50 and +50? No problemo! All we would have to do would be to modify our previous statement to read =(ROUND(RAND() * 100, 0)) - 50 From software to hardware OK, we’re poised to leap from topic-totopic with the agility of young mountain goats, so may I recommend you don suitable attire. Let’s start with the fact that the term ‘D-type flip-flop’ refers to a memory element called a register that can store a single bit (binary digit) of data in the form of a 0 or 1 (Fig.3). As indicated by the symbol (to those of us who can read the arcane ‘language of symbols’), this is an edge-triggered device. A rising (0 to 1) transition (edge) on the clock input will load whatever 0 or 1 value is present on the data_in input into the register. After a short delay, this new value will work its way through the logic gates forming the register to appear on the data_out output. The register’s internal delay is important, because it allows us to daisychain a string of registers to form a more Reg 2 d 2 d Reg 1 q ck (a) SISO 2 1 0 (b) SIP O 2 1 0 ck q 2 d Reg 0 q q 1 ck clock Fig.4. 3-bit SISO shift register. d q ck q 0 Fig.5. Simplified symbols for 3-bit SISO and SIPO shift registers. sophisticated function called a shift register. For example, consider a 3-bit serialin, serial-out (SISO) shift register (Fig.4). When we clock this register, each element will load the value it currently sees on its input. Suppose we start off with the three registers containing 0, 1, 0, respectively (let’s simplify this to 010), and that we present input d2 with a logic 1. When we clock the register, it will end up containing 101. If we leave the input at 1 and clock the register again, it will end up containing 110. One more clock will leave the register containing 111. If we now set the d2 input to 0 and clock the register again, it will end up containing 011, and so it goes. Since we are going to be drawing a few of these registers, and as we know they share a common clock, for the purposes of these discussions we could simplify our 3-bit SISO shift register symbol by removing the clock (Fig.5a). Also, while we’re at this point in our discussions, if we wish, we could make a slight modification that allows us to access all of the register bits simultaneously, resulting in what we call a serial-in, parallel out (SIPO) shift register (Fig.5b). Now, just for giggles and grins, suppose we take the output from our 3-bit SISO shift register and feed it back to the input (Fig.6a). Let’s also assume we have some way of pre-loading this register to have an initial (seed) value of 001. Following the first clock, the register will contain 100. The next clock will result in 010. And one more clock will return us to our original value of 001. Ouroboros and the LFSR I’m sure I don’t need to make mention of the fact that the Ouroboros is an ancient symbol of a serpent or dragon swallowing its own tail, thereby forming a circle. This symbol has been used by cultures around the world to depict eternity or renewal. (This is not to be confused with the Amphisbaena, which is a serpent in classical mythology having a head at both ends and capable of moving in either direction – much like some managers I’ve met.) 65 ^ 2 (a) SISO XOR (b) LFSR 1 0 ^ 2 1 0 a b y 0 0 1 1 0 1 1 0 0 1 0 1 (c) XOR truth table 7 ^ ^ 6 5 4 3 2 1 0 1 0 (a) Many-to-One implementation 7 6 ^ 5 ^ 4 ^ 3 2 (b) One-to-Many implementation Fig.6. Simplified symbols for 3-bit SISO and LFSR shift registers. I always think that the equivalent to the Ouroboros in the world of digital electronics is the linear-feedback shift register (LFSR). One of the more common ways to create a LFSR is to start with a regular shift register and add feedback from two or more points, called ‘taps,’ in the register chain. These taps are fed into an XOR function, whose output is used to drive the input of the register chain. For example, consider a simple 3-input LFSR with two taps from register bits 2 and 0, which we could represent as [2,0] (Fig.6b). As for the regular SISO, let’s assume we seed our LFSR with 001. Using the truth table for the XOR (Fig.6c), we see that a series of clocks will result in the sequence 100, 110, 111, 011, 101 and 010. One more clock will return us to 001, which was our original starting point. In decimal, this sequence would be 1, 4, 6, 7, 3, 5, 2... Since we have three (n) bits, we have 2n = 23 = 8 possible combinations of 0s and 1s. In a nutshell, our LFSR has pseudo-randomly cycled through all of the possible combinations except 000; that is, (2n − 1) = (23 − 1) = (8 − 1) = 7 values. Note that we could have used an XNOR instead of an XOR, in which case our LFSR would have taken a different path to sequence through all of the possible combinations except 111. Also, instead of taps at [2,0], we could have used taps at [1,0]. Once again, this would cause the LFSR to follow a different sequence as it worked its way through the various values. Now suppose we determine to create an 8-bit LFSR. One combination of taps that will result in a maximum length sequence is [6,5,4,0] (Fig.7a). Taking all of these taps and feeding them into a 4-input XOR function that generates a single feedback value is known as a ‘many-to-one’ implementation. Note that there are no such beasts as 3-input or 4-input XOR gates – only 2-input XOR gates – which means we have to implement our 4-input XOR function using three 2-input XOR gates, as illustrated in the figure. This means we have two levels of logic in our feedback path. The more levels of logic, the greater the delay, and the lower the frequency with which we can clock the LFSR. An alternative is to create a ‘one-tomany’ implementation (Fig.7b). In this case, the tap at bit 0 is fed directly back 66 Fig.7. Many-to-one and one-to-many 8-bit LFSR shift registers. into the input of bit 7, and it is also individually XORed with the other original tap bits (those at [6,5,4] in this example). Although the order of the generated values will be different, both implementations will result in maximal-length sequences. From hardware to software On the basis that this portion of the Cool Beans column is called, cunning coding tips and tricks, you may be wondering about our foray into the hardware domain. Well, the thing is, hardware and software are two sides of the same coin, which means we can also create software implementations of LFSRs. Furthermore, as we shall see, the one-to-many LFSR flavour is the easiest for us to transpose into the software realm. We introduced the & (AND) and | (OR) bitwise operators in an earlier column (PE, March 2021). As part of this, we discussed using these operators to test the state of bits, to set or clear bits, and to act as masks. In the case of the & operator, for example, this accepts two integer values as inputs and performs an AND on each pair of corresponding bits (this is actually implemented using a bunch of physical 2-input AND gates in the computer’s central processing unit (CPU)). The point is, there’s also a bitwise ^ (XOR) operator that we can use to implement our LFSR function. One thing we have to consider before we start is when to perform the XOR operation. Do we execute the XOR and then implement the shift, or would it be more efficacious to perform the shift followed by the XOR? The answer is ‘yes’ or ‘no’ or ‘maybe’ depending on ‘stuff’ (I hope I’ve made myself clear). If we are working at the assembly language level, for example, in which we have access to the contents of the carry flag in the CPU’s status register – along with a bunch of low-level shift and rotate operators – then it may be easier to perform the XOR followed by the shift. However, since we are using the C programming language, performing the shift followed by the XOR is probably the better way to go. Suppose we define SEED and MASK values and declare our LFSR as an 8-bit unsigned integer as follows (we introduced the concept of declaring fixedwidth values in PE, September 2020): #define SEED 0x01 // 0000 0001 #define MASK 0xB8 // 1011 1000 uint8_t LFSR = SEED; When we wish to ‘clock’ our LFSR to generate the next value in the sequence, the way we are going to do this is to check the state of the least-significant bit (LSB), bit 0, to see if it contains a 0 or a 1. If it’s a 0, all we have to do is to shift our LFSR one bit to the right, which will automatically insert a 0 into the most-significant bit (MSB). Alternatively, if the LSB is a 1, we again shift our LFSR one bit to the right, but we then use the bitwise ^ operator to XOR this new value with the contents of our MASK: if ((LFSR & 0x01) == 0) { LFSR = LFSR >> 1; } else { LFSR = LFSR >> 1; LFSR = LFSR ^ MASK; } I know this takes a bit of wrapping your brain around, but this is the software equivalent of the one-to-many hardware implementation presented in Fig.7b. If you download and run the sketch I just threw together (file CB-Jun21-03.txt) and display the results in the Arduino IDE’s Serial Monitor, you’ll see that our LFSR pseudo-randomly cycles through (28 − 1) = 255 different values (excluding 0x00 or 00000000 in binary) before returning to its initial value. Is this the best pseudo-random number generator going? No! On the other hand, this is a great technique to have available to you in your tips and tricks toolchest for those times when you are working with a low-powered 8-bit microcontroller with limited memory and clock cycles at your disposal. And, of course, you could easily extend this approach to implement 16-bit, 24-bit, or 32-bit LFSRs if you wish (taps for maximal length LFSRs from 2 to 32 bits are given in my book Bebop to the Boolean Boogie, https://amzn.to/3a0Qojz). We will continue to dip our toes in the LFSR waters in our next Tips and Tricks. Until then, as always, I welcome your comments, questions, and suggestions. Practical Electronics | June | 2021