program to interface bbc microbit to a MCP79410 RTCC module

Dependencies:   microbit

Fork of microbit-hello-world by micro:bit

This program uses the BBC microbit to display a clock. The program scrolls the time across the microbit 25 led display. The user can set the hours with button A and minutes with button B. The seconds can also be displayed but cannot be set on this version of the program.

main.cpp

Committer:
euxton
Date:
2018-01-11
Revision:
2:92208e3aae5a
Parent:
1:75322449b2fd

File content as of revision 2:92208e3aae5a:

/*
The MIT License (MIT)

Copyright (c) 2016 British Broadcasting Corporation.
This software is provided by Lancaster University by arrangement with the BBC.

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/* This Microbit program for RTCC MCP7941X demonstrates use of: 
   the I2C interface, 
   button events to set the clock,
   scrolling to display the time,
   author phil.holifield@gmail.com
   any comments welcome
*/

#include "MicroBit.h"

MicroBit uBit;

// for MCP7941X I2C control byte – 0xDE for RTCC 
const int addr = 0xDE;  // 8 bit addressing
char config_t[10];
char tim_read[8];
char disp_time[8];
char MSN, LSN, ch_hrs, ch_mins;
int secs, mins, hrs;
int inc_hr, inc_mins;  
    
MicroBitI2C i2c(I2C_SDA0, I2C_SCL0); 

void onButton(MicroBitEvent e)
{
    if ((e.source == MICROBIT_ID_BUTTON_A) and (e.value == MICROBIT_BUTTON_EVT_DOWN)) { 
        inc_hr = inc_hr + 1;  //increment by 1 for each press - hours
      } 
    if ((e.source == MICROBIT_ID_BUTTON_B) and (e.value == MICROBIT_BUTTON_EVT_DOWN)) { 
        inc_mins = inc_mins + 1;  //increment by 1 for each press - mins
      } 
} 
   
// helper functions to manipulate BCD and binary to integers
int bcd2dec(char r_char)
{
    MSN = (r_char & 0xF0)/16;
    LSN = r_char & 0x0F;
    return(10*MSN + LSN);   
}
char msn(char tim)
{
    return (tim & 0xF0)/16;
}
char lsn(char tim)
{
    return (tim & 0x0F);
}

// Ensure RTCC is counting using the internal clk with ext xtal
void setConfig(void)
{
    config_t[0] = 0x00;
    config_t[1] = tim_read[0] | 0x80;  // bitwise OR sets Start osc bit = 1
    config_t[2] = tim_read[1];
    config_t[3] = tim_read[2];
    config_t[4] = tim_read[3];
    config_t[5] = tim_read[4];
    config_t[6] = tim_read[5];
    config_t[7] = tim_read[6]; 
    config_t[8] = 0x00;     // control b3 - extosc = 0
}
int main() 
{
// Initialise the micro:bit runtime.
uBit.init();
inc_hr = 0;      
inc_mins = 0;

// Register to receive events when any buttons are clicked, including the A+B virtual button (both buttons at once).
uBit.messageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_EVT_ANY, onButton);
uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_EVT_ANY, onButton);
    
 // Initialise microbit by reading the time from the RTCC module and adding control bits
 // ST bit must be 1 Ext Osc must be 0
 // Write this once for set up if backup has battery
 //i2c.write(addr, config_t, 9); //send time info only to set up
    
    // read stored time data
    config_t[0] = 0x00; //reset pointer reg to '00'
    
    //  Set up config to read the time and set the control bits
    i2c.write(addr, config_t, 1); // write address 00
    i2c.read(addr, tim_read, 7); //read time ss mm hh  from r1, r2, r3
    setConfig();                 //puts RTCC data into config array from tim_read array
    // write the config data
    i2c.write(addr, config_t, 9);  // write the config data back to the RTCC module
    
    while(1) {
        // continuous loop to get time and display 
        // First Get the time
        config_t[0] = 0x00; //reset pointer reg to '00'
        i2c.write(addr, config_t, 1); 
        i2c.read(addr, tim_read, 3); //read time
       
       // display routine for seconds
       secs = bcd2dec(tim_read[0]);
       // Commented out seconds display as cannot set this
       //disp_time[7] = 48+LSN;
       //disp_time[6] = 48+MSN;
       //disp_time[5] = 58;   
       disp_time[7] = 20;
       disp_time[6] = 20;
       disp_time[5] = 20;   
           
       //Display and set mins
       mins = bcd2dec(tim_read[1]);
       disp_time[4] = 48+LSN;
       disp_time[3] = 48+MSN;
       disp_time[2] = 58;  
       // re-calculate mins section if button B is pressed  
       if (inc_mins > 0)  {
          mins = mins + inc_mins;
          mins = mins%60;
          ch_mins = 16*(mins/10) + mins%10;
          MSN = msn(ch_mins);
          LSN = lsn(ch_mins);
          disp_time[4] = 48+LSN;
          disp_time[3] = 48+MSN; 
          tim_read[1] = ch_mins;
          inc_mins = 0;
          //write the data back to RTCC
          setConfig();
          i2c.write(addr, config_t, 9);
          }
       
       //Display and set hours
       hrs = bcd2dec(tim_read[2]);
       disp_time[1] = 48+LSN;
       disp_time[0] = 48+MSN; 
       // re-calculate hrs section if button A is pressed
       if (inc_hr > 0)  {
          hrs = hrs + inc_hr;
          hrs = hrs%24;
          ch_hrs = 16*(hrs/10) + hrs%10;
          MSN = msn(ch_hrs);
          LSN = lsn(ch_hrs);
          disp_time[1] = 48+LSN;
          disp_time[0] = 48+MSN; 
          tim_read[2] = ch_hrs;
          inc_hr = 0;
          //write the data back to RTCC
          setConfig();
          i2c.write(addr, config_t, 9);
          }

       // create the display string and scroll it
       ManagedString s = disp_time; 
       uBit.display.scroll(s);
       uBit.sleep(50);
       
    }



    // If main exits, there may still be other fibers running or registered event handlers etc.
    // Simply release this fiber, which will mean we enter the scheduler. Worse case, we then
    // sit in the idle task forever, in a power efficient sleep.
    release_fiber();
}  // end of main