The Main Board

I created the main board in the same pattern as the original. That made for quite an expensive prototype as there is a lot of empty space. This size is needed to fit the tactile switches in their proper places. Now that I have Revision 2 up and running, a write up of what I have learned along the way is over due.

The assembly was not without issues. There were some lessons to learn with KiCad and circuit design and layout as I did make some mistakes but I was able to identify the issue and make some corrections. Here are some of the things I picked up along the way

Check the pin outs

This might sound like an obvious thing and it hind-sight, it was. Complacency crept in on more than one occasion and I did not verify the pin allocations between the datasheet, symbol and footprint for the linear regulator. As it was a three pinned device, I only needed to reset it and run a bridge to ground.


I did not factor any indicator LEDs on the main board. While this is not a mistake, the addition of an LED to blink to show that something is happening is well worth the few seconds it takes to model it in the schematic and layout.

Don’t leave GPIO pins unconnected

This is just to say for any prototyping board, it would be worthwhile to expose any spare pins to headers, and or coupled with 0Ω resistors. When troubleshooting, you never know when you might need something. Of course in the production board, these would not be populated.

Getting Things up and Running

Heartbeat-Bodge-bOnce the power rails were reading the correct voltage, I connected in the RTC module. This fired up OK. I.e. Its LED lit up for a second. This is when I realised I was missing a heartbeat LED. I simply connected a piece of through hole lead to Port B0. This was the output that was configured as the heartbeat on the myAVR development board.


Using the procedure I used for the previous boards, I tested the connection between the PC and the AVRISP mkII using the Atmel Studio. If I could read the serial number of the micro, then I knew I was in good form.

Main Board and Rev1 of the Display Module

I flashed the program I was using on the myAVR Dev board. Straight away the heartbeat started pulsing. Another good sign. The display did not react, or when it did, it was with garbage.

The issue with the display module as due to a mismatch between the main board and the display module. Since communication was OK to the RTC, I could assume that the SPI was largely OK. The obvious place the issue would be was with the actual signalling and or timing.

This issue has kept me occupied for some time. The biggest help was the Salea Logic Analyzer. To be able to capture the signals and have the digital values interpreted is a huge advantage. I could read the values being sent to the clock and display to ensure they were correct. I was able to tweak the code so that I could match the SPI specifications described on the RTC datasheet. I used this as a base to then configure the display module. Everything started to fall into place then and the display was more stable.

I found that to get the flexibility out of BASCOM, I needed to set up the Master i.e. the main board using software controlled SPI. Whereas, I could simply rely on the hardware SPI for the slave (display board).

Main Board SPI Setup

Fir the main board, the software controlled SPI was preferred since I could then use the SS = None property on the configuration. I then had to allocate my own chip-select lines for each of the RTC and the display module.

Config Spi = Soft , Din = Pinb.4 , Dout = Portb.3 , Ss = None , Clock = Portb.5 , Setup = 40 , Mode = 1

Display_ss Alias Portb.2
Config Display_ss = Output : Display_ss = 1

Dcf_ss Alias Portb.1
Config Dcf_ss = Output : Dcf_ss = 1


Display Board SPI setup

The key to the display board setup was to use the Master = no to ensure that this would be configured as a slave. All pin allocations were as per the datasheet for the micro controller.

Config Pinb.4 = Output
Config Pinb.3 = Input                                       ' MISO
Config Spi = Hard , Interrupt = On , Data Order = Msb , Master = No , Polarity = Low , Phase = 0       ' , Clockrate = 128


On Spi Spi_isr                                              'Nosave

In principle, things were good. I know I can flash the display module and I know I can flash the main board. I also know that communication is happening between the main board and the RTC.However there is still a niggling problem between the controller board and the display unit. After a while, the data seems to get out of sync and the display starts to display wrong values. SignalToDisplay Examining the SPI signals, I could be satisfied that the data presented and received by the display module is correct. There is something else happening inside the display module that is causing the information to be gabled. This is where I am reaching another boundary on my tool-set. The myAVR and the AVRISP MkII do not support any debugger. This is a set of tools I have yet to expose myself to and learn. Thinking around the problem, I am sure that this is some type of synchronisation issue. The actual cause, I can’t be sure. One thought would be some interference with the interrupt service routines. Since the data presented to and received by the display module is correct, I am willing to exclude the actual controller from the equation, for the moment. The problem has lead to some optimisations on the display module. One of the first improvements was seen when removing the NOSAVE from the On spi Spi_isr statement. This reduced the Spi_isr down to the following

   Set Rbit
   Mosi = SPDR

The same routine as described in a previous blog entry also contained logic to arbitrate whether the incoming data was a register address or a value for the register. in fact, this was always a concern. How to reliably determine the name from the value. The very first entry after start-up is going to be an address. After that, if something happens to the timing, it is not so clear cut.

After trying several ways to analyse the problem and make changes that were not always successful, I have determined the most effective way would be to flag the address. This means the API to the display module has now changed such that the first byte send to it, as address, must have the most significant bit set. This is a major improvement on reliability, but still no solution!

   If Rbit = 1 Then
      Reset Rbit
      Spdr = Mosi

      If Mosi.7 = 1 Then
         Idx = Mosi And &B00001111
         Register(idx) = Mosi ' Assign the data to the register
         Select Case Idx      ' Based on the register/value, set the affected variables
            Case Hours_10:
               Digits(1) = Register(idx)

There are still some issues to solve with this. For the above change, the controller board was not considered. However, the problem now comes back to the controller board to understand what the interaction is between the RTC, the controller board and the display board really is. Only once in a while at the transition of a minute, the display will be corrupted for a second or two. This does not happen often. Perhaps three to four times in an hour. But it shows there is still some form of timing race condition happening.

Where to from here?

I am happy that the communication is happening but I can’t call the job complete as there are some odd issues still persisting. I could work around them by sending only one byte rather than two so that the high end nibble is the address and the low end nibble is the value to be set. This would work for most of my values, but no all. Besides – that would be a work around and not a solution. I need to find a way to better understand what is happening with the data between the RTC, main board and display module such that the display modules register address and values are being skewed. At least that is my current understanding of the issue.



Alternate Display Driver

The purpose of this entry is to describe the assembly,  programming and testing of the alternate Clock Display Module – whereby instead of a dedicated display driver chip, the module will be controlled by its own micro controller. This was created under a separate GitHub branch as UCtl_small. After the relative ease of getting the MAX7221 version of the display module working, it is easy to think that this version to go just as smoothly. This article will describe more about the approach that will be taken and the planning for the final API. Subsequent posts will document the execution and results.


In one of the latest modules of Contextual Electronics, the services of OSH-Stensils was introduced with the purpose of trying out reflow in an electric frying pan. I don’t consider myself at the stage to try it out (my work bench is just not big enough for another appliance), but the idea of using the stencil had me intrigued. Not long after submitting the board for fabrication, I also ordered the associated stencils, along with a jig to hold the work in place. The assembly went very smoothly! The stencils are a great help.


They also helped to demonstrate that you don’t need a lot of paste at all to get a good soldering job. The trickiest was the transistors. They would have to be the smallest parts I have soldered to date. I am very grateful to have been introduced to the stencil idea before attempting this board.



The board is now assembled and I am very satisfied with the result, now comes the testing. I think the is the most exciting oart of the development. All the previous work of sifting through data sheets and trawling through vendor sites looking for parts, creating the schematic and working through the layout puzzle all comes down to this monent! Will it work? Or will it sit there is stoney silence and do nothing? Now that I am at this point, I realise that this board, although functionally the same as the MAX7221 based display module, is significantly different in the way it is to be “brought up”. The MAX7221 based board has given me confidence with SPI interfacing. However, this board is still dumb. The processor has not yet been programmed. So there is my first challenge – onboard programming. In the design, I included a pin header for the programmer connector.

One Step at a Time

I have come to realise that I will need some type of systematic approach to the problem. In a similar vein with the MAX7221 based board, starting with a “Heartbeat” and building on that, I will need to start small and gain confidence that a section is working before proceeding with the next. I figure, I can tackle this with the following areas:

  • Programming interface
  • SPI Slave
  • Display Module API

Programming Interface

In this section, I need to prove I have everything connected correctly in oder to achieve processor start up plus inboard programming. To confirm this, as much as it seems extraneous work, I will bread-board a processor with the pin header and a LED just to conform the “Hello World” scenario. If this does not work on the bread-board with the same configuration of the display module, then I know I have something fundamentally wrong. “Hey, wait a minute”, I hear you say. “Shouldn’t this have already been done?”. Well, yes, it was but a while ago and I to just try it again to double checkand then I have a model that I can pull around, if required. Once I have the confidence with respect to the set up, then I can transfer the “Hello World” excercise to the display module board. It does not matter that it will not be displaying any digits, the main thins is that it blinks a LED or segment – any or perhaps a sequence. The idea here is that this will prove that the basic infrastructure is working. The programming interface and the IO lines to the LEDs.

SPI Interface

The next step after asserting the basic infrastructure is to start bullding the firmware for the display module proper. This means setting up the display module as a Slave.  The first response should be at least to react to a specific register-value pair. This could be considered the test mode for the module (see the API specification below) and could even reuse the test code in the previous test.

Display Module API

Once I have successfully reached this stage, everything is in place to start defining the actual API for the module.  An overview of the possible commands is shown in the following table. Some of these features are nice-to-have (*) and will be subject to further development once the basic features are implemented.

Basically it will work using eight bit register-value pairs. The resister will specify an operation or feature and the value will configure that operation or feature. Some of these operations and features will be mutually exclusive, so a priority will need to be fleshed out. Further refinement of the descriptions will be subject of further posts as the features mature.

Register Name Note
0x01 Hour 10s  The 10s digit for the hour part of the time

BCD value from 0-2

0x02 Hour units  The units digit for the hour part of the time

BCD value from 0-9

0x03 Minuts 10s  The 10s digit for the minutes part of the time

BCD value from 0-5

0x04 Minutes units  The units digit for the minutes part of the time.

BCD value from 0-9

0x05 Colon  The colon (between the hours and minutes)

0x00 – Colon Disabled
0x01 – Colon Enabled

0x06 Indicators  The indicator lamps that are featured on the display

0x00 – All indicators OFF
0x01 – Top indicator ON
0x02 – Bottom indicator ON
0x03 – Top and Bottom indicator ON

0x0A Intensity*  Controls the intensity of the display

0x00 –

0x0C Power mode  Enables the display unit

0x00 – Display unit OFF
0x01 – Display unit ON

0x0D Digit Blink*  Defines which digit or display element should blink. The data value of the register is a set of bit-wise flags for each element. OR-ing the various bit enables the digits to be selectively enabled for blocking, or not.

0x00 – No blink
0x02 – Digit 1
0x04 – Digit 2
0x08 – Digit 3
0x10 – Digit 4
0x11 – Colon
0x12 – Indicators
0x1F – All

0x0E Blink Rate*  Controls the blink rate of the digit

0x00 –

0x0F Test Lamp test

0x00 – Lamp test off
0x01 – All segments on
0x02 – Sequence run*

Serial Data Format

D15 D14 D13 D12 D11 D10 D9 D8   D7 D6 D5 D4 D3 D2 D1 D0
MSB     ADDRESS            LSB  MSB      DATA        LSB

Next Steps

The next steps are already described in the body of this post. Needless to say the board needs to be powered up and programmed with the basic “Hello World” example to prove the connections and basic infrastructure.

MAX7221 Driven Display Module

It is now time to put some theory into action. This entry will talk about the implementation of the clock display module driven by the MAX7221. This chip was selected for the first version of the display module as it provided a one-stop solution for driving seven segment displays. It also SPI compatible and provided some additional features like program selectable intensity.
The assembly of the board went without any issues. In a previous blog, I had calculated a Rset as 50KΩ in order to limit the segment current to 10mA. In the end, I only used what I had on-hand, so I used a 56KΩ. I was unsure about this and prepared to change the resistor if the intensity was not adequate.


Once assembled, the display module was connected to the myAVR development board that I am using. I used ATMega88-PinOutthe pre-defined pins for the SPI interface. From a previous test, the Real Time Clock (RTC) was connected with the I²C interface, also using the pre-defined pins. To keep thing simple for this test, I left this the way it was. Even though, in the final implementation, i will be using SPI for both the RTC and the display module.

The RTC is driven by 3.3V and therefore needs a couple of level shifters (shown in the photo) to convert the 5V signal to the 3.3V. I already had those on-hand from previous trials.



With everything connected and double checked, it was time to start creating some code. This would  be my first attempt at programming the SPI so I was a bit unsure how it would go. The RTC and I²C was a known quantity so I decided to start with that first and create a heart-beat pulse. This would prove that the program is being written to the micro controller correctly and that the basic infrastructure was in place.

This was achieved by configuring the Pin Change Interrupt (PCINT) 16 and 17 for the one second pulse and the DFC complete signal respectively. The one second pulse enables the micro controller concentrate on orchestrating the information between the RTC and display module and does not have to implement any internal timers. This also means I don’t need any special crystal circuitry for additional accuracy. PCINT16 and PCINT17 are part of the Pin Change Mask Register 2 (PCMSK2) at bits 0 and 1 of the mask register. The set up for these is shown in BASCOM below. In this case, PORTB.0 is configured to be connected to the LED to provide the heart-beat.

On Pcint2 Pcint2_isr
Pcmsk2.0 = 1 ' PCINT16 - 1 Second pulse
Pcmsk2.1 = 1 ' PCINT17 - DCF message

Enable Pcint2
Enable Interrupts


Config Pind.0 = Input
Second_interrupt Alias Pind.0
Dim New_second As Bit

Config Pind.1 = Input
Dcf_interrupt Alias Pind.1

Config Portb.0 = Output
Heartbeat Alias Portb.0


Do ' Main control loop


 If Second_interrupt = 0 Then New_second = 1
 If Dcf_interrupt = 0 Then Time_dcf = 0

For the full source, see the GitHub repo for simpleCheck.bas

The MAX7221 was programmed first by setting up the SPI interface, using the config spi instruction. Before the main control loop, the initialisation subroutine is called. This sets the initial parameters for the MAX7221 and also runs a two second lamp check. The MAX7221 can drive up to 8 digits. I am technically only using four digits, so in order to avoid any flicker on the display, the duty cycle needs to be configured not drive the digits that are not needed. In actual fact,  from the original design, I am using 6 digits. The segments A and B of the fifth and sixth digits are used for the colon and indicators respectively.

Config Spi = Hard , Master = Yes , Data_order = Msb

' Display

Const Intensity_register = &H0A
Const Intensity_max = &H0F
Const Intensity_med = &H07
Const Intensity_min = &H00

Const Shutdown_register = &H0C
Const Normal_mode = &H01

Const Display_test_register = &H0F
Const Display_test_on = &H01
Const Display_test_off = &H00

' Scan Lmit 0xXB
Const Scan_limit_addr = &H0B
Const Scan_limit_value = &H05 ' Display digits 0 1 2 3 4 5

' Decode mode 0xX9
Const Decode_mode_addr = &H09
Const Decode_mode_value = &H0F ' Code B decode for digits 3-0 No decode for digits 7-4

Const Digit1_addr = &H01
Const Digit2_addr = &H02
Const Digit3_addr = &H03
Const Digit4_addr = &H04
Const Colon_addr = &H05
Const Signal_addr = &H06

Dim Spi_data(2) As Byte


Gosub Init_display


' Subroutines =================================================================


' Put the MAX7221 into normal operation mode.
   Spi_data(1) = Shutdown_register
   Spi_data(2) = Normal_mode
   Spiout Spi_data(1) , 2

' Run the test mode for 2 seconds.
   Spi_data(1) = Display_test_register
   Spi_data(2) = Display_test_on
   Spiout Spi_data(1) , 2

   Wait 2

   Spi_data(1) = Display_test_register
   Spi_data(2) = Display_test_off
   Spiout Spi_data(1) , 2

' Set the display intensity to maximum
   Spi_data(1) = Intensity_register
   Spi_data(2) = Intensity_max
   Spiout Spi_data(1) , 2

' Set the scan limit i.e. the number of digits to support
   Spi_data(1) = Scan_limit_addr
   Spi_data(2) = Scan_limit_value
   Spiout Spi_data(1) , 2

' Set the decode level - which digits to be treated as
' numbers and which will be custom driven
   Spi_data(1) = Decode_mode_addr
   Spi_data(2) = Decode_mode_value
   Spiout Spi_data(1) , 2

' Turn off the indicators
   Spi_data(1) = Signal_addr
   Spi_data(2) = 0
   Spiout Spi_data(1) , 2

' Turn off the colon
   Spi_data(1) = Colon_addr
   Spi_data(2) = 0
   Spiout Spi_data(1) , 2


Setting the device into normal operation was the real trick. Before I did that, it remained in an off state. So by default, it is configured to be in a shutdown mode. I had mentioned I was concerned about the resistor and the intensity of the display. It turns out that the 56KΩ is more than adequate, in fact, I can imagine that in the final implementation, a lower intensity will be required.

With the heart-beat functioning and the correct initial values being displayed, then it was only a matter of waiting for the RTC to receive its DCF77 signal for the correct time to be displayed. This eventually occurred after a minute or so. Then I started with the enhancements such as driving the colon also from the heart-beat pulse.


In conclusion, since the assembly and testing went largely without any issues, I can only sing the praises for the MAX7221. Though it is quite pricey, it certainly saves time and space for any other type of display driver. I am now curious about the next driver I intend to trial where I have to create my own firmware.

One extra thought I have is regarding the layout of the board. For this board the SPI pin header is in the bottom right hand corner. For the next board I will be working on, for no good reason, the SPI pin header is in the middle. It would have made more sense to make them compatible so that I could also be working on the main board and then interchange the display modules as needed. Hind-sight is a wonderful thing.

Display Revisited

While waiting for the display board to return from OSHPark, I was also interested in an alternative module. I had mentioned this idea before and it was time to start taking a closer look. For the purpose, I created another branch in GitHub rather than creating a whole new project.

The key feature of this implementation is that it does not use a dedicated display driver. The idea is to “roll my own” so to speak. This would incorporate the 7 segment display, but using a micro controller to drive them. Aside from the complexity of setting this up, there are a number of advantages, such as, having control over the API to drive the display.

digitDriver The setup for the controller basically stays the same as for implementation with the MAX7221. But instead, a 74LS138 will be used as a 3 bit to 8 bit decoder/demultiplexer. In other words, this will take a binary coded decimal value from 0-7 and use that to drive up to eight lines. In my case, I have six. Four digits and one line for the indicators (auto-time and alarm enabled), and one for the colon. In addition to the 74LS138, there is a 74HC4511 Binary Coded Decimal to 7 segment driver. These two components together could drive up to 8, 7 segment displays.


On the previous board, I had used a 4 layer model. Routing was quite challenging all the same where the network of traces for the seven segment displays clash with those for the controller. For this new, alternative approach, I decided to try two separate boards. One for the controller/driver circuit and the other for the display only. The idea is to then plug one board onto the other and solder the pins.


Further work is needed to program this device. I will be using SMD controllers so this means I will have to program them on-board. So there is more stuff to learn there.

The controller I have decided on is will be the ATMega88. I was going to use the ATMega8 but the 88 was easier to source at the time. No other technical grounds apart from convenience.

I am still waiting on delivery of the boards for the MAX7221 based display so in the mean time, the next stage will be to start looking at the actual controller board. There will be some mechanical aspects to that problem.

  • The board must fit into the existing housing
  • The buttons on the base of the housing must still be usable and have the same function
  • The board should not be the same size as the original as this will add to the overall cost (though two versions of the display have already blown the budget).
  • Provision is needed to plug the RCF77 module into the new main board.

Back to the Drawing Board

Well, not exactly back to the drawing board for everything… What has developed since doing the actual schematic is that the display module was treated as a black box. Now it is time to open this up and understand how this is to work. The beauty of this approach is that not knowing anything about the display module has not held me up on the other, simpler aspects of the project. This module is possibly going to be the most challenging. There are several dynamic elements to it and it is also going to be the module that will draw the most current. So far I have indicated that this module will be supplied by Vbb i.e. +5V and will be interfaced with the controller via a SPI bus.

The first challenge is which direction to take this. I find myself at a bit of a cross roads. Searching the internet for a suitable example as a starting point, I see there are already 7-segment display driver from Maxim i.e. Display module - MaximMAX7221. The advantage here is that it provides many features that make the implementation of a clock display relatively simple.  I have quickly put together the block diagram that shows the intended implementation. It seems I could use the fourth and fifth digits to drive the colon and auto-time and alarm enabled indicators. The implications on the driving current need to be ratified.

The down side is the cost and the power consumption. It would mean rethinking my use of the MCP1703T-5002E/CB as the main regulator since this is limited to 250mA only. In reality, for practical purposes, even 250mA is to high for an appliance that is expected to be running 24×7 such as a digital alarm clock.

The alternative to using the display driver is to implement this myself. The advantage there is I am free to introduce what behaviour I need for the module to work within this project. The disadvantage is additional complexity in firmware updates. There will be two micro-controllers to contend with. At this stage, I have not done any calculations to see if there would be a saving in cost or power drawn by going the home-made route.

Display module - Controller

The block diagram for the micro controller based display module is very similar. The micro controller is used to replace the behaviour of the display driver chip. Although an ATMega88 is depicted here, any suitable i.e. low powered micro controller would suffice. As long as the duty cycle on the LED segments and indicator lamps is enough to provide a clear display.

Where to now?

Since I am at a cross road, the best way forward is to try things out. This is probably not good SysML practice since the design is not actually complete. But prototyping must be considered a part of design. I don’t have enough information to make a sensible decision as to the direction. The best way forward is to implement a prototype of the two possibilities and make the best choice from there. In this case I will be able to measure physical performance and power consumption and not relay on theoretical calculations.

Wired for Action – almost

In the last post, I presented the initial ideas for powering the project. Now it is time to move on and start looking into the individual modules. I was impressed as to how quickly this part progressed since I had done the up-front thinking of the pin and port allocation. So much so, that before I knew it I had most of the schematic done making it unnecessary to span the development over several blog posts.

sch-top-02The high level diagram is now looking more complete with the use of hierarchical sheet pins to connect the respective module. This clearly demonstrates the communication between the modules and again, looks very similar to the initial block diagram. It should be iterated that the up-front work of the block diagram contributed significantly to the creation of this section of the schematic. Since I had previously thought out the pin and port allocation, it was a simple matter of aligning the labels on the sheets so that it is concise and descriptive.


The controller chosen for this project is the ATMega88p. I have to admit for no good reason other than I have a development board for this processor and have used the ATMega8 before. Unless there is a significant reason to re-think this decision, I will be staying with the ATMega.


The controller diagram, at this stage, describes the connection of the Serial Peripheral Interface (SPI) bus and interrupts using hierarchical labels. I have also added a pin header for on-board programming. I do need to clarify this further to be sure that this is the correct connection/mechanism for programming the chip on-board.

RTC Module

It has been mentioned often enough that a pre-fabricated module will be used for the Real-Time-Clock (RTC). This is the RTC-DCF from ELV. This module implements a RTC with built in calendar and has also a module to receive the DCF77 signal. When all things are working, then there is no need to set the time on the final clock appliance. It is envisaged that there will be a manual mode for the clock in cases where the signal is not received.

IMG_1054The symbol for the RTC in KiCad is a custom symbol for this module. Though the original kit is mounted in an Arduino shield type form factor, the module itself can be punched out and either soldered onto the application board or, as I envisage, connect it to the application board via a set of 2×6 pole pin headers.


This schematic implements the level shifter mechanism to shift the +5V signal from the controller to a 3V3 signal that the RTC requires. The RTC supports a couple of different mechanisms for communication. In this case, I am opting for SPI. The usage of the signal lines look to double up. This is only because when one communication mechanism is chosen (programmed via a DIP switch on the module) the other lines are used to support the extra interrupt features of the module. For the implementation and features I require, not all connections are necessary. The Tx line, for instance will not be required in this case.

Thinking back on the SysML block diagram, the level-shifter was not clearly visible on the block diagram. It was certainly defined in the model and was specified as the type of port on the 3V3 SPI bus. What is also not clear not the SysML model is that the SPI 3V3 bus requires both Vbb and Vcc to operate since it has to convert the signal between the two.

What’s next

I am quite satisfied with the schematic so far. More needs to be done on the controller. The interface buttons and switches need to be added. Also some thought needs to go into the housing since four buttons and a switch are already available. What I am proposing requires some additional buttons for the extra features. I am sure my refurbishment of this appliance can include some modifications. At this stage, I don’t see it a major problem to add these at the back of the housing.

The next significant module is the display module. I have some initial thoughts on this but will save that for a future post.