Silicon ChipMax’s Cool Beans - 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 By Max the Magnificent Flashing LEDs and drooling engineers – Part 16 W ell, hello there. It’s so nice to see you again. I don’t know about you, but I find it hard to believe that we’re already a third of the way through 2021. When I graduated from high school in 1975, the new millennium was still a quarter of a century in the future. I just realised that, in only four years’ time, we will be 25 percent of the way through the 21st Century and the year 2000 will be a quarter of a century in the rear-view mirror of my life. Stop the world – I want to get off – I’m too young for all this excitement! Mind the jerks! In my previous column, we used my 12×12 array of ping-pong balls – each boasting its own tricolour LED – to realise a firstpass implementation of Conway’s Game of Life (GOL). To be honest, I’m amazed when any hardware I build works when power is applied for the first-time (interesting sparks and puffs of smoke don’t count), and I’m well-nigh speechless when any software I write deigns to run at all. Thus, I was more than pleasantly surprised that our first-pass GOL worked as well as it did. (If you want to refresh your memory as to our original GOL sketch (program), you might want to mosey on over to take a look at file CB-May21-01.txt, which is available on the May 2021 page of the PE website at https://bit.ly/3oouhbl). Having said this, it has to be acknowledged that our method for transitioning from one generation to the next lacked a certain refinement. All we did to display each new generation was to turn any dying cells hard-off (black) and to turn any living cells hard-on (green). As a result, our intergenerational transitions were somewhat jerky (Fig.1a). (You can remind yourself as to how this looked in the real-world by perusing and pondering the video that accompanied last month’s issue – https://bit.ly/3bMZbGQ) Slip slidin’ away Just the other night, as I pen these words, I was reading an interesting article about what essentially became a life-long feud between Paul Simon and Art Garfunkel. I hadn’t realised that they met each other in 1953 as 11-year-old schoolboys at 62 Parsons High School in Queens, which is the easternmost and largest in area of the five boroughs of New York City. They recorded their first single Hey Schoolgirl under the uninspired stage name of Tom & Jerry on 16 October 1957, which was three days before Simon’s 16th birthday, five months after I made my own debut on this planet, and just a couple of months before everything started to go pear-shaped between them. It’s sad that things ended up the way they did because – although Simon is an extremely gifted musician, singer, songwriter, and actor in his own right – the SimonGarfunkel combo created musical magic the like of which is rarely seen (or heard). The only reason I mention any of this here is that the thought of our secondpass GOL incarnation smoothly transitioning (‘sliding’) from one generation to the next has caused Simon’s 1977 song Slip Slidin’ Away to start rattling around my poor old noggin. The way I realised this new implementation was to keep dead cells black and living cells green; also, to gradually fade dying cells from green to black while, at the same time, fade cells that were coming to life from black to green (Fig.1b). The first time we implemented a fade effect of this type was when we were experimenting with virtual raindrops (PE, October 2020; you can see that sketch by downloading file CB-Oct20-01.txt, which is available on the October 2020 page of the PE website). Remember that our colours are represented as 32-bit values that contain 8-bit red, green, and blue colour channels (that is, 3 × 8 = 24 bits, leaving 8 bits going spare). In order to implement a fade effect, we have to perform the fade on each of the colour channels individually. Thus, we created three low-level functions called GetRed(), GetGreen(), and GetBlue(), each of which accepts a 32-bit colour value and returns its associated 8-bit colour channel. We also created a BuildColor() function that accepts three 8-bit colour channels and returns a 32-bit colour. Next, a CrossFadeColor() function was implemented that accepts four arguments: a 32-bit start colour, a 32-bit end colour, the total number of steps in the fade, and the current fade step. It’s T ime D ead Liv e (a) J erk y G eneration 0 G eneration 1 D ead Liv e / Staying A liv e (b) Smooth D ying / C oming A liv e G eneration 0 0 to 1 G eneration 1 D ead Liv e (c) C olorf ul Staying A liv e C oming A liv e D ying G eneration 0 0 to 1 G eneration 1 Fig.1. Alternative ways to represent inter-generational transitions. Practical Electronics | June | 2021 worth noting that the start and end colours can be any colour, including black. They can even be the same colour if needs be, although fading from a colour to the same colour will be perceived as no fade at all. You will see all of these functions appear in our new sketch. The point is, when we created the raindrop effect, we decided to perform the fade on a per-pixel (ping-pong ball) basis. This was because our virtual raindrops were arriving at random times, which meant we had to treat them as individual entities. By comparison, in the case of this implementation of our GOL, we really have only two fades to worry about: the fade associated with a living cell dying and the fade associated with a dead cell coming to life. Let’s start with a dying cell. As opposed to performing the fade over and over again for each dying cell on an individual basis, if we calculate the current hue associated with a particular fade step, we can apply that hue to all of the dying cells. A similar circumstance applies to all of the cells that are coming to life. So, what we are going to do is to take our first-pass GOL sketch from last month and modify it to perform the required fades (you can follow along by downloading file CB-Jun21-01.txt, which is available on the June 2021 page of the PE website). As usual, we aren’t going to go through the entire program here. Instead, we will concentrate on a couple of key elements. First, we declare the two-dimensional (2D) array called StateColors[][] shown below: uint32_t StateColors [NUM_XGEN_STATES][NUM_TRANSITIONS + 1] = { {COLOR_GREEN, COLOR_GREEN}, // Staying Alive {COLOR_GREEN, COLOR_BLACK}, // Dying {COLOR_BLACK, COLOR_BLACK}, // Staying Dead {COLOR_BLACK, COLOR_GREEN} // Coming Alive }; Note that NUM_XGEN_STATES (the number of possible states – staying alive, dying… – associated with the intermediate generation) has been defined as 4, while NUM_TRANSITIONS (the number of transitions from one colour to another; eg, black to green) has been defined as 1. We can think of these as the start and end colours associated with the fade. In the case of a cell that’s already alive and is staying alive, both its start and end colours will be green. Similarly, in the case of a cell that’s already dead and is staying that way, its start and end colours will be black. In the case of a cell that’s dying, its start colour will be green and its end colour will be black. Contra wise, in the case of a cell that’s coming to life, its start colour will be black and its end colour will be green. In this new incarnation of our program, our loop() function is as follows, where START_STATE and END_STATE have been defined as 0 and 1, respectively: void loop () { EvaluateNextGeneration(); FadeFromStateToState(START_STATE, END_STATE); UpdateCurrentGeneration(); delay(InterGenerationDelay); } The EvaluateNextGeneration() and UpdateCurrentCeneration() functions are unchanged from our original program. The former cycles through each cell looking at that cell’s state and the states of its neighbours to determine the cell’s future (staying alive, dying…), while the latter uses this information to update the state of the array. The newcomer is the FadeFromStateToState() function. Since we currently have only two Practical Electronics | June | 2021 states, having the START_STATE and END_STATE arguments may seem superfluous to requirements, but their time to shine will become apparent in the next incarnation of our program. Based on what is heading our way (be afraid, be very afraid), I think it’s worth taking the time to consider this new function in a little detail. Before we do so, however, let’s remind ourselves that we introduced the concepts of typedef (type definitions), enum (enumerated types), and struct (structures) in Tips and Tricks, PE, December 2020. Also, in the original incarnation of our GOL program, as discussed in my previous column, we defined a structure called CellData and then we declared a 2D array called Cells[][]. typedef struct CellData { nGenOptions nGenState; xGenOptions xGenState; int numNeigh; }; CellData Cells[NUM_Y][NUM_X]; Each element of the array is a copy of our structure as follows:  nGenState is the state of the cells in the current generation, and can be assigned values of ALIVE or DEAD  xGenState is what we are going to use to define the state in the next generation and can be assigned values of STAYING_ALIVE, DYING, STAYING_DEAD, or COMING_ALIVE  numNeigh is the number of live neighbours. Rather than hit you with a big block of code, let’s disassemble things somewhat. The outer part of the function call is as follows: void FadeFromStateToState (int fromState, int toState) { int iNeo; uint32_t tmpFadeColors[NUM_XGEN_STATES]; uint32_t tmpColor; // Do stuff here } The 4-element tmpFadeColors[] array is where we are going to store the four hues associated with each step of the fade. The main element in our // Do stuff here area is a for() loop as follows (where NUM_FADE_STEPS has been defined as 20): for (int iStep = 1; iStep <= NUM_FADE_STEPS; iStep++) { // Calculate colors // Display state } Our first task for each step in the fade is to calculate the hues of the four colours associated with this step. We achieve this by calling our CrossFadeColor()function as follows: // Calculate the colors for the current step for (int iColor = 0; iColor < NUM_XGEN_STATES; iColor++) { tmpFadeColors[iColor] = CrossFadeColor ( StateColors[iColor][fromState], StateColors[iColor][toState], NUM_FADE_STEPS, iStep ); } 63 Fig.2. 21-Segment Victorian display circuit board designed by Steve Manley. by downloading file CB-Jun21-02.txt. We start by changing the definition of NUM_TRANSITIONS from 1 to 2. Next, we modify our StateColors[][] array to reflect our new colour transitions as follows: uint32_t StateColors NUM_XGEN_STATES][NUM_TRANSITIONS + 1] = { {COLOR_GREEN, COLOR_CYAN, COLOR_GREEN}, // Staying Alive {COLOR_GREEN, COLOR_RED, COLOR_BLACK}, // Dying {COLOR_BLACK, COLOR_BLACK, COLOR_BLACK}, // Staying Dead {COLOR_BLACK, COLOR_YELLOW,COLOR_GREEN} // Coming Alive }; Our second task, is to display the current state of play, which we do as follows: // Display current state of play for (int yInd = 0; yInd < NUM_XY; yInd++) { for (int xInd = 0; xInd < NUM_XY; xInd++) { int iNeo = GetNeoNum(xInd, yInd); tmpColor = tmpFadeColors [Cells[yInd][xInd].xGenState]; Neos.setPixelColor(iNeo, tmpColor); } } Neos.show(); delay(InterFadeStepDelay); The clever part here (well, I think it’s clever) is where we use the value of Cells[yInd][xInd].xGenState as an index into our tmpFadeColors[] array. Since xGenState is an enumerated type, the values that can be assigned to it (STAYING_ALIVE, DYING, STAYING_DEAD, or COMING_ALIVE) are automatically associated with integer values of 0, 1, 2, and 3, respectively, which is what we need to index into our array. More colour! The problem with restricting ourselves to just two colours (green and black for alive and dead, respectively), and to use fades of these colours to reflect those cells that are coming to life or dying, is that we aren’t conveying quite as much information as we would perhaps like to see. Suppose we were to increase our colour palette to include cyan for cells that are currently alive and plan on staying that way, yellow for cells that were dead but are coming to life, and red for cells that were alive but are poised to shrug off this mortal coil (Fig.1c). It’s important to note that we’re going to employ two colour transitions. For a cell that is currently alive and planning on staying that way, it will first transition from green to cyan, and then transition from cyan back to green again. By comparison, a cell that is currently alive but is sadly no longer for this world will first transition from green to red, and then from red to black. Meanwhile, in the case of a cell that was dead but is coming to life, it will transition from black to yellow, and then from yellow to green. Now, you may be thinking that we’ve got a lot of work ahead of us, but the way we’ve created our code means our lives are going to be easy-peasy lemon-squeezy (I’m sorry, I’ve been living in the US for longer than is good for a true-born Yorkshireman). As usual, you can follow along 64 Also, although we maintain our START_STATE definition of 0, we change our END_STATE definition from 1 to 2 and we add an INTERMEDIATE_STATE defined as 1. Now, the only thing remaining is to modify our main loop() function to read as follows (the modifications are shown in bold): void loop () { EvaluateNextGeneration(); FadeFromStateToState(START_STATE, INTERMEDIATE_STATE); delay(HOLD); FadeFromStateToState(INTERMEDIATE_STATE, END_STATE); UpdateCurrentGeneration(); delay(InterGenerationDelay); } This is a good time to note that you can see a comparison of our original GOL implementation, this ‘smooth’ implementation, and the ‘colourful’ implementation in a video I just captured for your delectation and delight – see: https://bit.ly/3sXsHPr 21-Segment Victorian displays Way back in January 2021, I mentioned that your humble narrator and a small group of his LED co-conspirators are working on a modern incarnation of 21-segment Victorian displays. The original displays, whose patent was applied for in 1898, involved 21 small incandescent bulbs along with a complicated electromechanical rotary switch that was used to activate the appropriate segments required to display characters, numbers and symbols. Three of our number – Paul Parry of Bad Dog Designs (https:// bit.ly/3a50mjT), Steve Manley, and yours truly – are building 10-character versions of these little beauties using circuit boards designed by Steve (Fig.2). These bodacious beauties, which are 50mm wide by 64mm tall, each boast 35 tricolour LEDs in the form of WS2812B devices (a.k.a. NeoPixels). I’m showing you this here only as a tempting teaser for what is to come. What I’d like you to be thinking of is – in addition to displaying alphanumeric characters and punctuation symbols, and remembering that we will have ten characters presented side-by-side – how might we control our 10 × 35 = 350 pixels to provide stunning effects? As always, I welcome your comments, questions and suggestions. Cool bean Max Maxfield (Hawaiian shirt, on the right) is emperor of all he surveys at CliveMaxfield.com – the go-to site for the latest and greatest in technological geekdom. Comments or questions? Email Max at: max<at>CliveMaxfield.com Practical Electronics | June | 2021