Merck / Mbed OS SmartCap_OS5

Dependencies:   nRF51822

Source/hw.cpp

Committer:
sgetz7908
Date:
2019-03-19
Revision:
23:7ca590427f0e
Parent:
hw.cpp@ 10:b3553e75eee0
Child:
24:761c30334cf4

File content as of revision 23:7ca590427f0e:

//**********************************************************************
//
// Hardware Routines
//
// SPG 12/13/2016
//
//**********************************************************************

/// @file hw.cpp

#include "mbed.h"
#include "hw.h"
#include "nrf_delay.h"
#include "nrf_gpio.h"


Ticker seconds_ticker;
volatile uint32_t seconds = 0; // seconds clock, time since power up
volatile uint32_t sec_offset = 0; // when the actual time is set, this will contain the difference between actual time and the above variable


/// Software generate delay.
/// Interrupt can increase the delay length.
/// CPU runs at full power during delay.
void delay_ms(uint32_t volatile number_of_ms)
{
    while(number_of_ms != 0) {
        number_of_ms--;
        nrf_delay_us(999);
    }
}

void set_rtc(uint32_t s)
{
    seconds = s;
}

void update_rtc(uint32_t s)
{
    seconds += s;
}

// RTC in seconds since boot
static void seconds_ticker_interrupt(void)
{
    seconds += 1;
}

/// Initialize the seconds clock to 's' seconds 
void init_clock(uint32_t s)
{
    seconds_ticker.detach();
    seconds_ticker.attach(seconds_ticker_interrupt, 1.00);
    seconds = s;
}

/// Read the number of seconds since init_clock() was called
uint32_t read_clock(void)
{
    return seconds;
}

/// Set sec_offset by passing the current time, so correct time/date can be be found by adding sec_offset to internal time
void set_time_offset(uint32_t s)
{
    sec_offset = s - read_clock();
}

/// Return the time correction value, add this to the internal time to get real time
uint32_t read_time_correction(void)
{
    return sec_offset;
}

/// 10-bit ADC reading of the requested channel
/// Uses internal 1.2V reference, and 1/3 of the signal source.
/// This provides a result = Voltage/3.6*1023
/// @param chan is the channel to read
/// @param times is the number of readings to take
/// @return avg of all the readings
int adc_read(int chan, int num_readings)
{
    int result = 0;
    int times = num_readings;

    NRF_ADC->INTENCLR  = ADC_INTENCLR_END_Clear; // turn off ADC interrupts
    //NRF_ADC->EVENTS_END = 0;

    switch(chan) {
        case ADC_CHAN_BATTERY:
            NRF_ADC->CONFIG = (ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos) |
                              (ADC_CONFIG_INPSEL_SupplyOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) |
                              (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) |
                              (ADC_CONFIG_PSEL_Disabled << ADC_CONFIG_PSEL_Pos) |
                              (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos);
            break;

        case ADC_CHAN_CAP_SENSE:
            NRF_ADC->CONFIG = (ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos) |
                              (ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) |
                              (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) |
                              (ADC_CONFIG_PSEL_AnalogInput2 << ADC_CONFIG_PSEL_Pos) |
                              (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos);
            break;

        default:
            return 0;
    }

    NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Enabled; // enable ADC

    while(times--) {
        NRF_ADC->TASKS_START = 1; // start ADC conversion

        // wait for conversion to end
        while (!NRF_ADC->EVENTS_END) {
            ;
        }

        NRF_ADC->EVENTS_END = 0;
        result += NRF_ADC->RESULT;  //Save your ADC result
        NRF_ADC->TASKS_STOP = 1;     //Use the STOP task to save current.
    }

    //NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Disabled;
    return (int)result/num_readings; // 10 bit
}

/// Reads the battery voltage
/// Returns the voltage as an int * 100.  3V = 300
int read_battery_voltage(void)
{
    return ((float)adc_read(ADC_CHAN_BATTERY,4)*3.6)/1023.0*100.0;
}

char str_buf[21];

/// Convert unsigned int to string
/// @returns pointer to string
char * uli2a(uint32_t num)
{
    char * buf = str_buf;
    //int n=0;
    unsigned long d=1;
    while (num/d >= 10)
        d*=10;
    while (d!=0) {
        int dgt = num / d;
        num%=d;
        d/=10;
        *buf++ = dgt+'0';
        //n++;
    }
    *buf=0;

    return str_buf;
}

char hexdig(char c)
{
    if(c<10) return c+'0';
    return c-10+'a';
}

/// Convert unsigned char to string, 2 digit hex
/// @returns pointer to string
char * char2hex(char c)
{
    char * buf = str_buf;

    *buf++ = hexdig(c>>4);
    *buf++ = hexdig(c&0x0f);
    *buf=0;

    return str_buf;
}

/// Converts an unsigned 32 bit int to a hex string,
/// 'digits' specifies the number of hex digits to output
/// output string is null terminated
char * char2hex(uint32_t n, int digits)
{
    char * buf = str_buf+digits;
    *buf-- = 0; // null terminator
    
    if(digits>0 && digits<20) {
        while(digits-->0) {
            *buf-- = hexdig(n & 0x0f);
            n = n>>4;
        }
    }
    else
    {
        return "";
    }
    
    return str_buf;
}