/**
 * @fn void interrupt ISR_handle(void)
 * @brief
 *
 * @param none
 * @return nothing
 */
void interrupt ISR_handle(void) {
	uint8_t ui8_slave_state = 0;
	uint8_t ui8_i2c_value = 0;
	if(SSPIF == 1) {
		SSPIF = 0; // Reset IRQ flag
		i2c_slave_state(&ui8_slave_state);
		if((ui8_slave_state == 1) || (ui8_slave_state == 3)) {
			i2c_slave_read(); // Read SSPBUF to clear BF bit but don't care about returned value
			gui8_recv_byte_idx = 0;
			gui8_frame_recv_size = 0;
		}
		else if(ui8_slave_state == 2) {
			ui8_i2c_value = i2c_slave_read(); // Read SSPBUF to clear BF bit and read data from master
			fifo_put(ui8_i2c_value);

			// copy frame size byte
			if(gui8_recv_byte_idx == 1) {
				gui8_frame_recv_size = ui8_i2c_value - 1;
			}
			/* else nothing to do */

			// indicate that is the last byte received
			if((gui8_frame_recv_size == gui8_recv_byte_idx) && 
			   (gui8_recv_byte_idx != 0)) {
				gui8_token ++; // increase the number of frames received
			}
			/* else nothing to do */

			gui8_recv_byte_idx ++;
		}
		/* else nothing to do */
		CKP = 1;
	}
	/* else nothing to do */
}
Exemple #2
0
void clear_fault(uint8_t slave_addr)
{
    uint8_t debug;
    //disable
    if (slave_addr == CHRGR_ADDR)
    {
        i2c_slave_command(USBA_ADDR, 0x10, 0x00);                   // clear any existing fault
    }
    else if (slave_addr == USBA_ADDR)
    {
        //TODO add fault handling from PORTB below
        USBA_EN_SetLow();
        for(debug = 0; debug < 100; debug++)
            __delay_ms(10);
        USBA_EN_SetHigh();
        __delay_ms(20);
        usb_port_init(USBA_ADDR);
    }
    else if (slave_addr == USBB_ADDR)
    {
        i2c_slave_command(USBB_ADDR, 0x10, 0x00); //try manually clearing
        putstring0("clear fault USBB0 - REG10: "); puthexbyte0(i2c_slave_read(USBB_ADDR, 0x10)); terpri0(); // DEBUG
//        putstring0("clear fault USBB0 - REG17: "); puthexbyte0(i2c_slave_read(USBB_ADDR, 0x17)); terpri0(); // DEBUG - verified - auto-retry is enabled
//        i2c_slave_command(USBB_ADDR, 0x17, 0xF4);        // disable port power
        i2c_slave_command(USBB_ADDR, 0x15, 0x10);       // discharge vbus, disable port power
        i2c_slave_command(USBB_ADDR, 0x10, 0x00);   // clear any existing fault
        for(debug = 0; debug < 100; debug++)
            __delay_ms(10);
//        usb_portb_regs.REG10 = i2c_slave_read(USBB_ADDR, 0x10); //DEBUG
//        putstring0("1USBB REG10: "); puthexbyte0(usb_portb_regs.REG10); terpri0();
//        i2c_slave_command(USBB_ADDR, 0x17, 0xF6);
        i2c_slave_command(USBB_ADDR, 0x15, 0x00);
        for(debug = 0; debug < 100; debug++)
            __delay_ms(10);
        i2c_slave_command(USBB_ADDR, 0x10, 0x00); //try manually clearing
        // if the I2C reset doesn't clear it, cut power and reinitialize
//        usb_portb_regs.REG10 = i2c_slave_read(USBB_ADDR, 0x10);
        if ( usb_portb_regs.REG10 != 0x00)
        {
            USBB_EN_SetLow();
            for(debug = 0; debug < 100; debug++)
                __delay_ms(10);
            USBB_EN_SetHigh();
            __delay_ms(20);
//            usb_port_init(USBB_ADDR); //DEBUG
            putstring0("Clear Fault USBB1 REG10: "); puthexbyte0(i2c_slave_read(USBB_ADDR, 0x10)); terpri0();
////            putstring0("clear fault USBB1 - REG17: "); puthexbyte0(i2c_slave_read(USBB_ADDR, 0x17)); terpri0(); // DEBUG
        }

    }
    return;
}
Exemple #3
0
/**
  Prototype:        TODO fill this in
  Input:
  Output:           none
  Description:
  Usage:            charger_init();
*/
void usb_port_init(uint8_t addr)
{

    // send a dummy read command to wake up the chip before doing anyhting. wait 3ms
    i2c_slave_read(addr, 0x00); //clear the junk byte
    __delay_ms(3);
    //TODO reset all registers then wait a few ms
    // TODO use GUI to go through and set all registers to what it's doing
    // ***Config registers
    // REG15 discharge VBUS and reset charge ration count
    i2c_slave_command(addr, 0x15, 0x13);
    // REG15 The ALERT# pin will be asserted if an error condition or indicator event is detected, The ALERT# pin will not be asserted on LOW_CUR or TREG, disable discharge and close VBUS switch, disable rationing, set ration to ignore
    i2c_slave_command(addr, 0x15, 0x03);
    // REG16 (default)The timeout and idle reset functionality is disabled for I2C, Emulation timeout is enabled during the DCE Cycle, restart DCE Cycle if no profile accepted, keep last DPDM setting once device starts drawing >Ichg/profile accepted,
    i2c_slave_command(addr, 0x16, 0x8C);
    // REG17 set pin ignore, M1=0,M2=EM_EN=1 (BC1.2 DCP), S0=1 (detection enabled), auto-retry on fault/error condition
    i2c_slave_command(addr, 0x17, 0xF6);
    // REG18 (default) set discharge time to 200ms, set attach/removal detection threshold to 800uA/700uA
    i2c_slave_command(addr, 0x18, 0x46);
    // REG25 disable highspeed data switch in all cases (it's not connected to anything)
    i2c_slave_command(addr, 0x25, 0x10);
    // *** End Config registers
     // REG19 set current limit to 2.5A (matches ILIM set by external resistor)
    i2c_slave_command(addr, 0x19, 0x03);
    //REG1E (default) set IBUS_CHG (min acceptable current when cycling DCE profiles) to 39mA
    i2c_slave_command(addr, 0x1E, 0x04);
    // REG1A-1B set max current ration to pack capacity BATT_CAP TODO adjust this smartly between ports based on how much has been drawn
    i2c_slave_command(addr, 0x1A, 0x0F);
    //REG20 disable DCP during DCE cycling
    i2c_slave_command(addr, 0x20, 0x16);

    i2c_slave_command(addr, 0x10, 0x00);    // clear any existing error flags
    return;
}
Exemple #4
0
int ds1307_read_ram(i2c_dev_t *dev, uint8_t offset, uint8_t *buf, uint8_t len)
{
    if (offset + len > RAM_SIZE)
        return -EINVAL;

    uint8_t reg = RAM_REG + offset;

    return i2c_slave_read(dev->bus, dev->addr, &reg, buf, len);
}
Exemple #5
0
/**
  Prototype:        void slave_check_fault(uint8_t addr)
  Input:            slave_addr: I2C address of slave
  Output:           none
  Description:      poll the I2C slave to see if any faults are occurring. if so, report
  Usage:            slave_check_fault(USBA_ADDR);
*/
void slave_check_fault(uint8_t slave_addr)
{
    //putstring0("slave_check_fault");

    if (slave_addr == CHRGR_ADDR)
    {
        usb_chrgr_regs.REG09 = i2c_slave_read(CHRGR_ADDR, 0x09);    // clear any existing fault
        usb_chrgr_regs.REG09 = i2c_slave_read(CHRGR_ADDR, 0x09);
        if (usb_chrgr_regs.REG09 != 0x00)   // check for errors
        {
            print_fault(CHRGR_ADDR, 0x09, usb_chrgr_regs.REG09);
        }
    }
    else if (slave_addr == USBA_ADDR)
    {
        i2c_slave_command(USBA_ADDR, 0x10, 0x00);                   // clear any existing fault
//        usb_porta_regs.REG10 = i2c_slave_read(USBA_ADDR, 0x10);
//        __delay_ms(5);  // give time for potential reset condition to occur
//        if (usb_porta_regs.REG10 & 0x20)   // if device has been reset, reinitialize
//                usb_port_init(USBA_ADDR);
        usb_porta_regs.REG10 = i2c_slave_read(USBA_ADDR, 0x10);
        if (usb_porta_regs.REG10 != 0x00)   // check for errors
        {
            print_fault(USBA_ADDR, 0x10, usb_porta_regs.REG10);
            clear_fault(USBA_ADDR);
        }
    }
    else if (slave_addr == USBB_ADDR)
    {
        i2c_slave_command(USBB_ADDR, 0x10, 0x00);                   // clear any existing fault
//        usb_portb_regs.REG10 = i2c_slave_read(USBB_ADDR, 0x10);
//        __delay_ms(5);  // give time for potential reset condition to occur
//        if (usb_portb_regs.REG10 & 0x20)   // if device has been reset, reinitialize
//                usb_port_init(USBB_ADDR);
        usb_portb_regs.REG10 = i2c_slave_read(USBB_ADDR, 0x10);
        if (usb_portb_regs.REG10 != 0x00)   // check for errors
        {
            print_fault(USBB_ADDR, 0x10, usb_portb_regs.REG10);
            clear_fault(USBB_ADDR);
        }
    }
    return;
}
static void handler (void)
{
    // Disable interrupt temp
    extint_disable (extint1);
    irq_clear (AT91C_ID_IRQ1);
    
    uint8_t addr;
    uint8_t buffer[2];
    i2c_ret_t ret;

    
    DELAY_US (4);
    //pio_output_toggle (LED1_PIO);

    ret = i2c_slave_read (i2c_slave1, buffer, sizeof (buffer), 10000);

    addr = buffer[0] - ARRAY_OFFSET;

    if (addr >= sizeof (comms_data))
        addr = 0;

    if (ret == 1)
    {
        // Have not received photo line command.
        if (buffer[0] != CD_PHOTO_LINE)
            ret = i2c_slave_write (i2c_slave1, comms_data[addr], 130, 1000); // Return data requested.
        else
        {
            // check if photo ready.
            if (comms_data[CD_PHOTO_READY-ARRAY_OFFSET])
            {
                ret = i2c_slave_write (i2c_slave1, comms_data[CD_PHOTO_NEXT_LINE-ARRAY_OFFSET], 130, 1000);
                if (ret > 0)
                {
                    ret++;
                    *comms_data[CD_FAULT - ARRAY_OFFSET] = ret;
                    comms_data[CD_PHOTO_NEXT_LINE-ARRAY_OFFSET] += ret;
                    if ((comms_data[CD_PHOTO_NEXT_LINE-ARRAY_OFFSET] - image) == image_size)
                    {
                        // We have sent the entire picture
                        comms_data[CD_PHOTO_NEXT_LINE-ARRAY_OFFSET] = image;
                        comms_data[CD_PHOTO_READY-ARRAY_OFFSET] = 0;
                    }
                }
            }
        }
        
    }
    if (ret == 2)
    {
        if (buffer[0] == COMMS_COMMAND)
            next_command = buffer[1];
    }
    extint_enable (extint1);
}
Exemple #7
0
void ds1307_get_time(i2c_dev_t *dev, struct tm *time)
{
    uint8_t buf[7];
    uint8_t reg = TIME_REG;

    i2c_slave_read(dev->bus, dev->addr, &reg, buf, 7);

    time->tm_sec = bcd2dec(buf[0] & SECONDS_MASK);
    time->tm_min = bcd2dec(buf[1]);
    if (buf[2] & HOUR12_BIT)
    {
        // RTC in 12-hour mode
        time->tm_hour = bcd2dec(buf[2] & HOUR12_MASK) - 1;
        if (buf[2] & PM_BIT)
            time->tm_hour += 12;
    }
    else
        time->tm_hour = bcd2dec(buf[2] & HOUR24_MASK);
    time->tm_wday = bcd2dec(buf[3]) - 1;
    time->tm_mday = bcd2dec(buf[4]);
    time->tm_mon = bcd2dec(buf[5]) - 1;
    time->tm_year = bcd2dec(buf[6]) + 2000;
}
Exemple #8
0
static uint8_t read_register(i2c_dev_t *dev, uint8_t reg)
{
    uint8_t val;
    i2c_slave_read(dev->bus, dev->addr, &reg, &val, 1);
    return val;
}
Exemple #9
0
int I2CSlave::read(char *data, int length) {
    return i2c_slave_read(&_i2c, data, length) != length;
}
Exemple #10
0
/****************************************************************************
 *
 *                        Main application
 *
****************************************************************************/
void main(void)
{
//    adc_result_t vbatt; // raw ADC of battery voltage
//    adc_result_t vbus;  // raw ADC of charger input voltage
    uint8_t soc_leds;   // result of raw ADC to 5 SOC LED conversion
    uint8_t c;  // dbg0, dbg1,

    // initialize the device
    SYSTEM_Initializer();
    CE_N_SetLow();                  // enable the input charger
    USBA_EN_SetHigh();              // enable usb porta
    M1_A_SetLow();                  // don't care since using pin_ignore/I2C only mode
    M2_A_SetHigh();                  // don't care since using pin_ignore/I2C only mode
    EM_EN_A_SetHigh();               // don't care since using pin_ignore/I2C only mode
    USBB_EN_SetHigh();              // enable usb portb
    M1_B_SetLow();                  // don't care since using pin_ignore/I2C only mode
    M2_B_SetHigh();                  // don't care since using pin_ignore/I2C only mode
    EM_EN_B_SetHigh();               // don't care since using pin_ignore/I2C only mode
    otg_mode_flag = 0;


    // initialise variables
    BTN0_dbstate = 0;                 // initial pushbutton state = released
    BTN0_change = 0;                  // clear pushbutton change flag (no change)
    BTN1_dbstate = 0;                 // initial pushbutton state = released
    BTN1_change = 0;                  // clear pushbutton change flag (no change)

    ADC_read_flag = 0;                //
    //ADC_channel = 0;

    print_start_msg();

     __delay_ms(10); // DEBUG
    charger_init();
    __delay_ms(10);  //DS: Upon power-up, the UCS1002 will not respond to any SMBus communications for 5.5 ms
    usb_port_init(USBA_ADDR);   // setup the USB smart output chips
     __delay_ms(10);    // DEBUG
    usb_port_init(USBB_ADDR);   // setup the USB smart output chips

    //enable interrupts - TODO should this wait unitl after i2c init routines?
    INTCONbits.IOCIF = 0;
    IOCBF1 = 0;
    IOCBF2 = 0;
    IOCBF3 = 0;
    IOCBF4 = 0;
    INTCONbits.IOCIE = 1;
    TMR0_StartTimer();
    TMR1_StartTimer();
    TMR2_StartTimer();
    INTERRUPT_PeripheralInterruptEnable();
    INTERRUPT_GlobalInterruptEnable();               // enable global interrupts

    /**
     *                          CORE APPLICATION
     */

    while (1)
    {
        // Add your application code

        //***DEBUG***//
        if (EUSART_IsDataReady() == 1)	// check for input
        {
                c = EUSART_GetByte();   // reading RCREG clear RCIF
                select_status_report(c);
        }

        if (A_DET_A_N_GetValue() == 0)
            FLASHLIGHT_SetHigh();
        //***DEBUG***//

        // check for self-attached cable
        if (SELF_DETECT_GetValue() == 1)
        {
            USBA_EN_SetLow();
            putstring0("Self Detect, USBA disabled"); // DEBUG
        }
        else USBA_EN_SetHigh();

        //grab battery level, input voltage, update SOC byte
        if (ADC_read_flag == 1)
        {
            ADC_read_flag = 0;
            vbatt = (ADC_GetConversion(channel_AN1) << 1);  // input voltage divided by 2 - multiply it back
            __delay_ms(1);                      // provide switching time
//            vbus = (ADC_GetConversion(channel_AN2) << 1);  // TODO figure out what to do with this
        }
        soc_leds = calc_soc(vbatt);

        // check for debounced button press
//        if (BTN0_change && !BTN0_dbstate)       // if button state changed and pressed (low)
        if (DBG_SPARE_change && DBG_SPARE_dbstate)       // if button state changed and pressed (high)
        {
            FLASHLIGHT_Toggle();               //   turn flashlight off and on
//            BTN0_change = 0;                  //   clear button change flag
            DBG_SPARE_change = 0;                  //   clear button change flag
        }
        
//        if (BTN1_change && !BTN1_dbstate)       // if button state changed and pressed (low)
//        {
//            soc_cntr_start_flag = 1;
            soc_update(soc_leds);           //   display SOC animation
//            BTN1_change = 0;                  //   clear button change flag
//        }
//        if (soc_cntr_done_flag == 1)        // let the SOC display stand for 5s
//        {
//            dbg1 += 1;
//            soc_cntr_start_flag = 0;
//            soc_cntr_done_flag = 0;
//            soc_update(dbg1);
////            soc_update(CLR_SOC);
//        }


        // TODO update more charger regs, react
        slave_check_fault(CHRGR_ADDR);
        if (otg_mode_flag == 1)
            i2c_slave_command(CHRGR_ADDR, 0x01, 0x6B); //REG01 reset watchdog, enable OTG only
        else
            i2c_slave_command(CHRGR_ADDR, 0x01, 0x5B); //REG01 reset watchdog, enable charger only

        // TODO update more usba regs, react
        slave_check_fault(USBA_ADDR);
        usb_porta_regs.REG00 = i2c_slave_read(USBA_ADDR, 0x00);   //update the current reading

        // TODO update more usbb regs, react
        slave_check_fault(USBB_ADDR);
        usb_portb_regs.REG00 = i2c_slave_read(USBB_ADDR, 0x00);   //update the current reading


        //debug
//        for (dbg0 = 0; dbg0 < 255; dbg0++);
//        {
//            __delay_ms(100);
//        }
//        soc_update(dbg1);
//        dbg1 += 1;
//        if (dbg1 == 0x1F)
//            dbg1 = 0;
//        if (debug_rprt_flag == 1)
//        {
//            debug_rprt_flag = 0;
//            FLASHLIGHT_Toggle();
//
//        }
 
    }
}
Exemple #11
0
void try_profile(uint8_t slave_addr, uint8_t profile, uint8_t dce,
        uint8_t* draw_best_ptr, uint8_t* best_profile_ptr, uint8_t* best_dce_ptr)
{
    uint8_t draw_now, cnt;

    // Try cycling each of the DCE profiles on one at a time TODO is there a better way to do this?
    //REG21 enable single legacy profiles during DCE cycling. skip if null (non DCE profile attempts)
    if (dce)
        i2c_slave_command(slave_addr, 0x21, dce);
    i2c_slave_command(slave_addr, 0x17, (profile & ~(1 << 1))); //disable port power
    putstring0("Config REG17 0 (hex): "); puthexbyte0(i2c_slave_read(slave_addr, 0x17)); terpri0();
    soc_update(0x00);
//    i2c_slave_command(slave_addr, 0x15, 0x10);       // discharge vbus, disable port power
    for (cnt = 0; cnt < PRFL_WAIT_MS/10; cnt++)  //TODO see how much this can be reduced
        __delay_ms(10);    
//    i2c_slave_command(slave_addr, 0x15, 0x00);  //
    i2c_slave_command(slave_addr, 0x17, profile); //enable port power
    putstring0("Config REG17 1 (hex): "); puthexbyte0(i2c_slave_read(slave_addr, 0x17)); terpri0();
    soc_update(0xFF);
    for (cnt = 0; cnt < PRFL_WAIT_MS/10; cnt++)  //wait for profile to be applied and go into effect on device
        __delay_ms(10);
    draw_now = i2c_slave_read(slave_addr, 0x00); //update the current reading
    if (draw_now > *draw_best_ptr)
    {
        *best_dce_ptr = dce;
        *best_profile_ptr = profile;
        *draw_best_ptr = draw_now;
    }
    //debug
    if (slave_addr == USBA_ADDR)
    {
        putstring0("USBA try profile port current: ");
        print_current(draw_now);
        print_status(USBA_ADDR, 0x12, i2c_slave_read(USBA_ADDR, 0x12)); terpri0(); // show applied profile 1 BC 1.2
        print_status(USBA_ADDR, 0x13, i2c_slave_read(USBA_ADDR, 0x13)); terpri0(); // show applied profile 2 legacy
        putstring0("Config REG17 (hex): "); puthexbyte0(i2c_slave_read(USBA_ADDR, 0x17)); terpri0();
        putstring0("Applied emulation REG30 (hex): "); puthexbyte0(i2c_slave_read(USBA_ADDR, 0x30)); terpri0(); terpri0();
//        IOCBF3 = 0;
    }
    if (slave_addr == USBB_ADDR)
    {
        putstring0("USBB try profile port current: ");
        print_current(draw_now);
        print_status(USBB_ADDR, 0x12, i2c_slave_read(USBB_ADDR, 0x12)); terpri0();
        print_status(USBB_ADDR, 0x13, i2c_slave_read(USBB_ADDR, 0x13)); terpri0();
        putstring0("Config REG17 (hex): "); puthexbyte0(i2c_slave_read(USBB_ADDR, 0x17)); terpri0();
        putstring0("Applied emulation REG30 (hex): "); puthexbyte0(i2c_slave_read(USBB_ADDR, 0x30)); terpri0(); terpri0();
//        IOCBF4 = 0;
    }
    return;
}
Exemple #12
0
void do_best_profile(uint8_t slave_addr)    //TODO should we test if current draw already > some threshold (e.g. 0.8A) then skip this?
{
    uint8_t draw_best, best_profile, best_dce, cnt; //draw_now
//    uint8_t* draw_now_ptr, draw_best_ptr, best_profile_ptr, best_dce_ptr;
//
//    draw_now_ptr = &draw_now;
//    draw_best_ptr = &draw_best;
//    best_profile_ptr = &best_profile;
//    best_dce_ptr = &best_dce_ptr;

//    INTERRUPT_GlobalInterruptDisable();
    INTCONbits.IOCIE = 0;

    putstring0("do best profile"); terpri0();
    for (cnt = 0; cnt < PRFL_WAIT_MS/10; cnt++)  //debug - the a_det is very sensitive, stall while connector is finished inserting
        __delay_ms(10);

    //REG21 disable all legacy profiles, enable one by one during DCE cycling
    i2c_slave_command(slave_addr, 0x21, 0x7F);
 
//    draw_now = i2c_slave_read(slave_addr, 0x00); //update the current reading
    draw_best = i2c_slave_read(slave_addr, 0x00); //update the current reading

    // Try the different emulation profiles, make note of the best
    putstring0("trying SDP"); terpri0();
    try_profile(slave_addr, SDP, 0, &draw_best, &best_profile, &best_dce);

    putstring0("trying CDP"); terpri0();
    try_profile(slave_addr, CDP, 0, &draw_best, &best_profile, &best_dce);

    putstring0("trying DCP"); terpri0();
    try_profile(slave_addr, DCP, 0, &draw_best, &best_profile, &best_dce);

    putstring0("trying DCE1"); terpri0();
    try_profile(slave_addr, DCE, DCE_P1, &draw_best, &best_profile, &best_dce);

    putstring0("trying DCE2"); terpri0();
    try_profile(slave_addr, DCE, DCE_P2, &draw_best, &best_profile, &best_dce);

    putstring0("trying DCE3"); terpri0();
    try_profile(slave_addr, DCE, DCE_P3, &draw_best, &best_profile, &best_dce);

    putstring0("trying DCE4"); terpri0();
    try_profile(slave_addr, DCE, DCE_P4, &draw_best, &best_profile, &best_dce);

    putstring0("trying DCE5"); terpri0();
    try_profile(slave_addr, DCE, DCE_P5, &draw_best, &best_profile, &best_dce);

    putstring0("trying DCE6"); terpri0();
    try_profile(slave_addr, DCE, DCE_P6, &draw_best, &best_profile, &best_dce);

    putstring0("trying DCE7"); terpri0();
    try_profile(slave_addr, DCE, DCE_P7, &draw_best, &best_profile, &best_dce);

// apply the best one
    putstring0("Best DCE (hex): "); puthexbyte0(best_dce); terpri0();
    putstring0("Best Profile (hex): "); puthexbyte0(best_profile); terpri0();
    if (best_profile == DCE) // only sent if legacy is best
        i2c_slave_command(slave_addr, 0x21, best_dce);
    i2c_slave_command(slave_addr, 0x17, (best_profile & ~(1 << 1))); //disable port power
//    i2c_slave_command(slave_addr, 0x15, 0x10);       // discharge vbus, disable port power
    for (cnt = 0; cnt < PRFL_WAIT_MS/10; cnt++)  //TODO see how much this can be reduced
        __delay_ms(10);
    i2c_slave_command(slave_addr, 0x17, best_profile); //enable port power
//    i2c_slave_command(slave_addr, 0x15, 0x00);  //

//    INTERRUPT_GlobalInterruptEnable();
    terpri0(); terpri0();
    print_selections_msg();
    INTCONbits.IOCIE = 1;
    return;
}