Simple demo for exercising the board

Dependencies:   MAX11300 MAX4822 OneWire Terminal ds3231 mbed

main.cpp

Committer:
j3
Date:
2017-03-06
Revision:
12:97bc95dbfc64
Parent:
11:fe03fb61fb08

File content as of revision 12:97bc95dbfc64:

/**********************************************************************
* Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved.
*
* 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 MAXIM INTEGRATED 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.
*
* Except as contained in this notice, the name of Maxim Integrated
* Products, Inc. shall not be used except as stated in the Maxim Integrated
* Products, Inc. Branding Policy.
*
* The mere transfer of this software does not imply any licenses
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
**********************************************************************/

#include "mbed.h"
#include "ds3231.h"
#include "MAX4822.h"
#include "MAX11300.h"
#include "Terminal.h"
#include "OneWire.h"

using namespace OneWire;
using namespace RomCommands;

void set_rtc(Terminal & term, Ds3231 & rtc);
void get_time_date(Terminal & term, Ds3231 & rtc);
void search_ow_bus(Terminal & term, DS2484 & owm);
void print_rom_id(Terminal & term, RomId & romId);
bool calibrate_420_io(Terminal & term, MAX11300 & pixi, DS2484 & owm, uint16_t *calData, bool loopAlreadyCal);
void DS1920Menu(Terminal & term, const RomId & romId, MultidropRomIterator & selector);
bool check_420_cal(Terminal & term, DS2484 & owm, uint16_t *calData);

int main(void)
{
    Terminal term(USBTX, USBRX);
    term.baud(57600);
    term.cls();
    term.home();
    term.printf("Starting Demo\n");
    
    SPI spi_bus(D11, D12, D13);
    MAX4822 rly_drvr(spi_bus, D10);
    DigitalOut rly_drvr_set(D7, 1);
    DigitalOut rly_drvr_reset(D6, 1);
    
    rly_drvr.reset_all_relays(rly_drvr_reset);
    
    MAX11300 pixi(spi_bus, D8, NC, D9);
    
    //set all analog outs to 0
    for(uint8_t idx = 0; idx < 9; idx++)
    {
        pixi.single_ended_dac_write(static_cast<MAX11300::MAX11300_Ports>(idx), 0);
    }
    
    //ensure latching relays are reset 
    for(uint8_t idx = 0; idx < 3; idx++)
    {
        pixi.gpio_write(static_cast<MAX11300::MAX11300_Ports>(idx + 9), 1);
        wait_ms(200);
        pixi.gpio_write(static_cast<MAX11300::MAX11300_Ports>(idx + 9), 0); 
    }
    
    I2C i2c_bus(D14, D15);
    i2c_bus.frequency(400000);
    
    Ds3231 rtc(i2c_bus);
    
    DS2484 owm(i2c_bus);
    OneWireMaster::CmdResult owm_result = owm.OWInitMaster();
    if(owm_result != OneWireMaster::Success)
    {
        //wait_ms(100);
        term.printf("Failed to initialize OneWire master\n");
        //owm_result = owm.OWInitMaster();
    }
    else
    {
        term.printf("OneWire master initialized\n\n");
    }
    
    
    float aio_slope = 0;
    float aio_offset = 0;
    float aii_slope = 0;
    float aii_offset = 0;
    uint16_t calData[4];
    
    bool currentLoopCal = false;
    if(check_420_cal(term, owm, calData))
    {
        aio_slope = (((calData[1]*1.0) - (calData[0]*1.0))/16.0);
        aio_offset = ((-1.0*aio_slope*4.0) + calData[0]);
        
        aii_slope = (16.0/((calData[3]*1.0) - (calData[2]*1.0)));
        aii_offset = ((-1.0*aii_slope*calData[2]) + 4.0);
    
        currentLoopCal = true;
    }
    
    int32_t user_entry = 0;
    int32_t relay = 0;
    
    uint16_t analog_out_ch, analog_val;
    float avo_volts, aio_mA, aii_mA;
    
    const int32_t QUIT = 15;
    
    MAX11300::CmdResult pixi_result;
    MAX4822::CmdResult rly_drvr_result;
    
    while(user_entry != QUIT)
    {
        term.printf("1.  Set RTC\n");
        term.printf("2.  Get Time/Date\n");
        term.printf("3.  Search OneWire bus\n");
        term.printf("4.  Set non-latching relay\n");
        term.printf("5.  Reset non-latching relay\n");
        term.printf("6.  Set all non-latching relays\n");
        term.printf("7.  Reset all non-latching relays\n");
        term.printf("8.  Set latching relay\n");
        term.printf("9.  Reset latching relay\n");
        term.printf("10. Set 0-10 analog out\n");
        term.printf("11. Set 4-20 out\n");
        term.printf("12. Get 4-20 in\n");
        term.printf("13. Calibrate 4-20 io\n");
        term.printf("%d. Clear Screen\n", (QUIT - 1));
        term.printf("%d. Quit\n\n", QUIT);
        
        user_entry = term.get_int32("Please select an option above: ", 1, QUIT);
        
        //get non-latching relay
        if((user_entry == 4) || (user_entry == 5))
        {
            relay = term.get_int32("Select a relay from 1 to 8: ", 1, 8);
        }
        
        //get latching relay
        if((user_entry == 8) || (user_entry == 9))
        {
            relay = (8 + term.get_int32("Select a relay from 1 to 3: ", 1, 3));
        }
        
        switch(user_entry)
        {
            case 1:
                set_rtc(term, rtc);
            break;
            
            case 2:
                get_time_date(term, rtc);
            break;
            
            case 3:
                search_ow_bus(term, owm);
            break;
            
            case 4:
                rly_drvr_result = rly_drvr.set_relay(static_cast<MAX4822::RelayChannel>(relay));
                if(rly_drvr_result != MAX4822::Success)
                {
                    term.printf("Failed to set relay\n");
                }
            break;
            
            case 5:
                rly_drvr_result = rly_drvr.reset_relay(static_cast<MAX4822::RelayChannel>(relay));
                if(rly_drvr_result != MAX4822::Success)
                {
                    term.printf("Failed to reset relay\n");
                }
            break;
            
            case 6:
                rly_drvr.set_all_relays(rly_drvr_set);
                term.printf("\n");
            break;
            
            case 7:
                rly_drvr.reset_all_relays(rly_drvr_reset);
                term.printf("\n");
            break;
            
            case 8:
                pixi_result = pixi.gpio_write(static_cast<MAX11300::MAX11300_Ports>(relay), 1);
                if(pixi_result != MAX11300::Success)
                {
                    term.printf("Failed to set relay\n");
                }
            break;
            
            case 9:
                pixi_result = pixi.gpio_write(static_cast<MAX11300::MAX11300_Ports>(relay), 0);
                if(pixi_result != MAX11300::Success)
                {
                    term.printf("Failed to reset relay\n");
                }
            break;
            
            case 10:
                analog_out_ch = (term.get_int32("Please select a 0-10V output; 1-8: ", 1, 8) - 1);
                avo_volts = term.get_float("Please enter a voltage from 0.0 to 10.0 volts: ", -0.1, 10.1);
                analog_val = static_cast<uint16_t>((avo_volts/10.0) * 4095);
                
                term.printf("DAC Code = %d\n", analog_val);
                
                pixi_result = pixi.single_ended_dac_write(static_cast<MAX11300::MAX11300_Ports>(analog_out_ch), analog_val);
                if(pixi_result != MAX11300::Success)
                {
                    term.printf("Failed to set 0-10 out\n");
                }
            break;
            
            case 11:
                if(currentLoopCal)
                {
                    aio_mA = term.get_float("Please enter a current from 4.0 to 20.0 mA: ", 3.9, 20.1);
                    analog_val = static_cast<uint16_t>((aio_slope * aio_mA) + aio_offset);
                    
                    pixi_result = pixi.single_ended_dac_write(MAX11300::PORT8, analog_val);
                    if(pixi_result != MAX11300::Success)
                    {
                        term.printf("Failed to set 4-20 out\n");
                    }
                }
                else
                {
                    term.printf("Please calibrate 4-20mA loop first, option 13.\n");
                }
            break;
            
            case 12:
                if(currentLoopCal)
                {
                    pixi_result = pixi.single_ended_adc_read(MAX11300::PORT12, analog_val);
                    aii_mA = ((aii_slope*analog_val) + aii_offset);
                    if(pixi_result == MAX11300::Success)
                    {
                        term.printf("4-20 in = %.2fmA\n", aii_mA);
                    }
                    else
                    {
                        term.printf("Failed to read 4-20 in\n");
                    }
                }
                else
                {
                    term.printf("Please calibrate 4-20mA loop first, option 13.\n");
                }
            break;
            
            case 13:
                if(calibrate_420_io(term, pixi, owm, calData, currentLoopCal))
                {
                    aio_slope = (((calData[1]*1.0) - (calData[0]*1.0))/16.0);
                    aio_offset = ((-1.0*aio_slope*4.0) + calData[0]);
                    
                    aii_slope = (16.0/((calData[3]*1.0) - (calData[2]*1.0)));
                    aii_offset = ((-1.0*aii_slope*calData[2]) + 4.0);
                
                    currentLoopCal = true;
                    
                    term.printf("Calibration data saved to 1-Wire EEPROM\n");
                }
            break;
            
            case (QUIT - 1):
                term.cls();
                term.home();
            break;
            
            case QUIT:
                term.printf("\nEnding Program\n");
            break;
            
            default:
                mbed_die();
            break;
        }
    }
}

//*********************************************************************
void set_rtc(Terminal & term, Ds3231 & rtc)
{
    //default, use bit masks in ds3231.h for desired operation
    ds3231_cntl_stat_t rtc_control_status = {0,0}; 
    ds3231_time_t rtc_time;
    ds3231_calendar_t rtc_calendar;
    
    rtc.set_cntl_stat_reg(rtc_control_status);
    
    //get day from user
    rtc_calendar.day = term.get_int32("\nPlease enter day of week, 1 for Sunday (1-7): ", 1, 7);
 
    //get day of month from user
    rtc_calendar.date = term.get_int32("\nPlease enter day of month (1-31): ", 1, 31);
 
    //get month from user
    rtc_calendar.month = term.get_int32("\nPlease enter the month, 1 for January (1-12): ", 1, 12);
 
    //get year from user
    rtc_calendar.year = term.get_int32("\nPlease enter the year (0-99): ", 0, 99);
      
    //Get time mode
    rtc_time.mode = term.get_int32("\nWhat time mode? 1 for 12hr 0 for 24hr: ", 0, 1);  
    
    if(rtc_time.mode)
    {
        //Get AM/PM status
        rtc_time.am_pm = term.get_int32("\nIs it AM or PM? 0 for AM 1 for PM: ", 0, 1);  
        //Get hour from user
        rtc_time.hours = term.get_int32("\nPlease enter the hour (1-12): ", 1, 12);
    }
    else
    {
        //Get hour from user
        rtc_time.hours = term.get_int32("\nPlease enter the hour (0-23): ", 0, 23);
    }
     
    //Get minutes from user
    rtc_time.minutes = term.get_int32("\nPlease enter the minute (0-59): ", 0, 59);
    
    
    //Get seconds from user
    rtc_time.seconds = term.get_int32("\nPlease enter the second (0-59): ", 0, 59);
    
    term.printf("\n");
    
    rtc.set_time(rtc_time);
    rtc.set_calendar(rtc_calendar);
}

//*********************************************************************
void get_time_date(Terminal & term, Ds3231 & rtc)
{
    time_t epoch_time;
    
    epoch_time = rtc.get_epoch();
    term.printf("\n%s\n", ctime(&epoch_time));
}

//*********************************************************************
void search_ow_bus(Terminal & term, DS2484 & owm)
{
    OneWireMaster::CmdResult result = owm.OWReset();
    MultidropRomIterator selector(owm);
    SearchState search_state;
    
    if(result == OneWireMaster::Success)
    {
        term.printf("\nOWReset success, starting search\n");
        
        result = OWFirst(owm, search_state);
        if(result == OneWireMaster::Success)
        {
            while(result == OneWireMaster::Success) 
            {
                //print current devices rom id
                print_rom_id(term, search_state.romId);
                
                if(search_state.romId.familyCode() == 0x10)
                {
                    DS1920Menu(term, search_state.romId, selector);
                }
                
                //find the next device if any
                result = OWNext(owm, search_state);
            }
            term.printf("\n");
        }
        else
        {
            term.printf("\nSearch failed\n");
            term.printf("\nError code = %d\n", result);
        }
    }
    else 
    {
        term.printf("\nFailed to find any 1-wire devices on bus\n");
        term.printf("\nError code = %d\n", result);
    }
}

//*********************************************************************
void print_rom_id(Terminal & term, RomId & romId)
{
    //print the rom number
    term.printf("\n");
    int8_t idx = 7;
    do
    {
        term.printf("0x%02x ", romId.buffer[idx--]);
    }
    while(idx >= 0);
    term.printf("\n");
}

//*********************************************************************
bool calibrate_420_io(Terminal & term, MAX11300 & pixi, DS2484 & owm, uint16_t *calData, bool loopAlreadyCal)
{
    char user_entry;
    //initial vals for aio determined imperically on one pcb
    static uint16_t aio_4mA = 518;
    static uint16_t aio_20mA = 2592;
    
    if(loopAlreadyCal)
    {
        aio_4mA = calData[0];
        aio_20mA = calData[1];
    }
    uint16_t aii_4mA, aii_20mA;
    
    term.cls();
    term.home();
    
    //cal aio
    term.printf("\nConnect DMM in series with AIO and AII.\n");
    term.printf("AIO----(DMMM)----AII\n\n");
    term.printf("Use 'i' and 'd' keys to increase/decrease measurement to calibration value.\n\n");
    term.printf("Setting AIO calibration val to 4mA, enter 'q' when DMM measurement = 4mA.\n\n");
    
    do
    {
        printf("aio_4mA = %d\n", aio_4mA);
        pixi.single_ended_dac_write(MAX11300::PORT8, aio_4mA);
        user_entry = term.get_char("increase (i), decrease (d), quit (q) when DMM = 4mA: ", 'd', 'q');
        
        if(user_entry == 'i')
        {
            aio_4mA++;
        }
        else if(user_entry == 'd')
        {
            aio_4mA--;
        }
        else if(user_entry == 'q')
        {
            term.printf("\nSetting AIO calibration val to 20mA, enter 'q' when DMM measurement = 20mA.\n\n");
        }
        else
        {
            term.printf("Not an option, please read the instructions.\n");
        }
    }
    while(user_entry != 'q');
    
    do
    {
        pixi.single_ended_dac_write(MAX11300::PORT8, aio_20mA);
        user_entry = term.get_char("increase (i), decrease (d), quit (q) when DMM = 20mA: ", 'd', 'q');
        
        if(user_entry == 'i')
        {
            aio_20mA++;
        }
        else if(user_entry == 'd')
        {
            aio_20mA--;
        }
        else if(user_entry == 'q')
        {
            term.printf("\nExecuting AII Cal\n\n");
        }
        else
        {
            term.printf("Not an option, please read the instructions.\n");
        }
    }
    while(user_entry != 'q');
    
    calData[0] = aio_4mA;
    calData[1] = aio_20mA;
    
    uint8_t idx;
    //cal aii
    pixi.single_ended_dac_write(MAX11300::PORT8, aio_4mA);
    for(idx = 0; idx < 10; idx++)
    {
        term.printf("AII 4mA input cal...\n");
        wait(1.0);
    }
    pixi.single_ended_adc_read(MAX11300::PORT12, aii_4mA);
    
    calData[2] = aii_4mA;
    
    pixi.single_ended_dac_write(MAX11300::PORT8, aio_20mA);
    for(idx = 0; idx < 10; idx++)
    {
        term.printf("AII 20mA input cal...\n");
        wait(1.0);
    }
    pixi.single_ended_adc_read(MAX11300::PORT12, aii_20mA);
    
    calData[3] = aii_20mA;
    
    
    bool rtn_val = false;
    
    //Write cal data to eeprom
    OneWireMaster::CmdResult result = owm.OWReset();
    MultidropRomIterator selector(owm);
    SearchState search_state;
    
    DS2431 eeprom(selector);
    
    search_state.findFamily(0x2D);
    result = OWNext(owm, search_state);
    if(result == OneWireMaster::Success)
    {
        eeprom.setRomId(search_state.romId);
        DS2431::Scratchpad scratchPadBuf = {'C','a','l','T','r','u','e','!'};
        OneWireSlave::CmdResult slaveResult = eeprom.writeMemory(0, scratchPadBuf);
        if(slaveResult == OneWireSlave::Success)
        {
            //cal data stored MSB first;
            scratchPadBuf[0] = ((aio_4mA >> 8) & 0xFF);
            scratchPadBuf[1] = (aio_4mA & 0xFF);
            scratchPadBuf[2] = ((aio_20mA >> 8) & 0xFF);
            scratchPadBuf[3] = (aio_20mA & 0xFF);
            scratchPadBuf[4] = ((aii_4mA >> 8) & 0xFF);
            scratchPadBuf[5] = (aii_4mA & 0xFF);
            scratchPadBuf[6] = ((aii_20mA >> 8) & 0xFF);
            scratchPadBuf[7] = (aii_20mA & 0xFF);
            
            slaveResult = eeprom.writeMemory(8, scratchPadBuf);
            if(slaveResult == OneWireSlave::Success)
            {
                rtn_val = true;
                term.printf("\nCal done.\n\n");
                wait(1.0);
            }
            else
            {
                term.printf("Failed to write cal data.\n\n");
            }
        }
        else
        {
            term.printf("Failed to write cal message.\n\n");
        }
    }
    
    return rtn_val;
}

//*********************************************************************
void DS1920Menu(Terminal & term, const RomId & romId, MultidropRomIterator & selector)
{
    char userEntry = '0';
    uint8_t th, tl, idx;
    uint8_t scratchPadBuff[8];
    float temperature;
    
    DS1920 tempIbutton(selector);
    DS1920::CmdResult result = DS1920::OpFailure;
    tempIbutton.setRomId(romId);
    
    while(userEntry != '7')
    {
        term.printf("\nDS1920 Menu Options\n");
        term.printf("\n%t1. Write ScratchPad");
        term.printf("\n%t2. Read Scratchpad");
        term.printf("\n%t3. Copy Scratchpad");
        term.printf("\n%t4. Convert Temperature");
        term.printf("\n%t5. Recall EEPROM");
        term.printf("\n%t6. Clear Screen");
        term.printf("\n%t7. Quit");
        
        userEntry = term.get_char("\nPlease select an option above: ", '1', '7');
        
        switch(userEntry)
        {
            case '1':
                th = term.get_int32("\nPlease enter upper temperature threshold, integer values only: ", 0, 100);
                tl = term.get_int32("\nPlease enter lower temperature threshold, integer values only: ", -55, 0);
                
                result = tempIbutton.writeScratchPad(th, tl);
                if(result == DS1920::Success)
                {
                    term.printf("\nWrite Scratchpad Success\n");
                }
                else
                {
                    term.printf("\nWrite Scratchpad Fail\n");
                }
                
            break;
            
            case '2':
            
                result = tempIbutton.readScratchPad(scratchPadBuff);
                if(result == DS1920::Success)
                {
                    term.printf("\nRead Scratchpad Success\n");
                    term.printf("\nScratchpad = ");
                    for(idx = 0; idx < 8; idx++)
                    {
                        if(scratchPadBuff[idx] < 16)
                        {
                            term.printf("0x0%x ", scratchPadBuff[idx]);
                        }
                        else
                        {
                            term.printf("0x%2x ", scratchPadBuff[idx]);
                        }
                    }
                    term.printf("\n");
                    
                }
                else
                {
                    term.printf("\nRead Scratchpad Fail\n");
                }
                
            break;
            
            case '3':
                
                result = tempIbutton.copyScratchPad();
                if(result == DS1920::Success)
                {
                    term.printf("\nCopy Scratchpad Success\n");
                }
                else
                {
                    term.printf("\nCopy Scratchpad Fail\n");
                }
                
            break;
            
            case '4':
                
                result = tempIbutton.convertTemperature(temperature);
                if(result == DS1920::Success)
                {
                    term.printf("\nConvert Temperature Success\n");
                    term.printf("\nTemperature = %.1f", temperature);
                }
                else
                {
                    term.printf("\nConvert Temperature Fail\n");
                }
                
            break;
            
            case '5':
                
                result = tempIbutton.recallEEPROM();
                if(result == DS1920::Success)
                {
                    term.printf("\nRecall EEPROM Success\n");
                }
                else
                {
                    term.printf("\nRecall EEPROM Fail\n");
                }
                
            break;
            
            case '6':
                term.cls();
                term.home();
            break;
            
            case '7':
                term.printf("\nLeaving DS1920 Menu Options\n");
            break;
            
            default:
                mbed_die();
            break;
        }
    }
}

//*********************************************************************
bool check_420_cal(Terminal & term, DS2484 & owm, uint16_t *calData)
{
    OneWireMaster::CmdResult result = owm.OWReset();
    MultidropRomIterator selector(owm);
    SearchState search_state;
    
    DS2431 eeprom(selector);
    
    bool rtn_val = false;
    
    term.printf("\n\nPlease remove any 1-Wire devices connected to bus on start up and calibrartion of 4-20mA loop.\n\n");
    wait(2.5);
    
    search_state.findFamily(0x2D);
    result = OWNext(owm, search_state);
    if(result == OneWireMaster::Success)
    {
        eeprom.setRomId(search_state.romId);
        uint8_t temp_data[8];
        
        OneWireSlave::CmdResult slaveResult = eeprom.readMemory(0, 8, temp_data);
        
        if((temp_data[0] == 'C') && (slaveResult == OneWireSlave::Success))
        {
            slaveResult = eeprom.readMemory(8, 8, temp_data);
            if(slaveResult == OneWireSlave::Success)
            {
                calData[0] = ((temp_data[0] << 8) | temp_data[1]);
                calData[1] = ((temp_data[2] << 8) | temp_data[3]);
                calData[2] = ((temp_data[4] << 8) | temp_data[5]);
                calData[3] = ((temp_data[6] << 8) | temp_data[7]);
                
                rtn_val = true;
            }
            else
            {
                term.printf("Failed to read row 1 of EEPROM\n\n");
            }
        }
        else
        {
            if(slaveResult == OneWireSlave::Success)
            {
                term.printf("No cal data stored, please calibrate 4-20mA loop\n\n");
            }
            else
            {
                term.printf("Failed to read row 0 of EEPROM\n\n");
            }
        }
    }
    
    return rtn_val;
}