dc550_i2cdriver.c

来自「一款经典的数字电话设计资料」· C语言 代码 · 共 947 行 · 第 1/2 页

C
947
字号
    rtcData.rtcMsg[5][0] = RTC_YEARDATE_ADDR;
    rtcData.rtcMsg[5][1] = (unsigned char)(date & 0x3F) |
                           (unsigned char)((year << 6) & 0xC0);

    rtcData.rtcMsg[6][0] = RTC_DOWMONTH_ADDR;
    rtcData.rtcMsg[6][1] = (unsigned char)(month & 0x1F) |
                           (unsigned char)((dayOfWeek << 5) & 0xE0);

    rtcData.rtcMsg[7][0] = RTC_ALARMCTRL_ADDR;
    rtcData.rtcMsg[7][1] = RTC_ALARMCTRL_OFF;

    rtcData.rtcMsg[8][0] = RTC_CONTROL_ADDR;
    rtcData.rtcMsg[8][1] = RTC_CONTROL_RUN;

    rtcData.Index = 0;
    rtcData.LastIndex = 8;
    rtcData.UpdateClock = TRUE;
    return 1;
}

int rtc_GetTimeOfDay( int *year,
                      int *month,
                      int *date,
                      int *hour,
                      int *minutes,
                      int *seconds,
                      int *dayOfWeek)
{
    if (seconds)
        *seconds = (int)(rtcData.TOD[0]);
    if (minutes)
        *minutes = (int)(rtcData.TOD[1]);
    if (hour)
        *hour = (int)(rtcData.TOD[2]);
    if (year)
        *year = (int)((rtcData.TOD[3] >> 6) & 0x3);
    if (date)
        *date = (int)(rtcData.TOD[3] & 0x3F);
    if (dayOfWeek)
        *dayOfWeek = (int)((rtcData.TOD[4] >> 5) & 0x7);
    if (month)
        *month = (int)(rtcData.TOD[4] & 0x1F);
    return 1;
}


/******************************************************************************
                     DTMF CHIP INTERFACE ROUTINES
 *****************************************************************************/
/*
030321 Modification:
static int dtmf_WriteByte(unsigned char val)
{
    i2c_StartBit(DTMF);
    if (!i2c_AddressSlave(DTMF, FALSE)) {
        i2c_StopBit(DTMF);
        return 0;
    }
    i2c_WriteByte(DTMF, val);
    i2c_StopBit(DTMF);
    return 1;
}

void dtmf_PlayTone(unsigned char val)
{
    dtmfData.Tone = val;
    dtmfData.Request = TRUE;
}
*/


/******************************************************************************
                       EEPROM INTERFACE ROUTINES
 *****************************************************************************/
/*
 *  Note: All of the eeprom_Write* and eeprom_Read* functions happen
 *  immediately, whereas the eeprom_Get* and eeprom_Set* functions are
 *  simply memory manipulations.  The magic number for waiting between
 *  write instructions seems to be 4 milliseconds (3.6 milliseconds works)
 */
int eeprom_SetNumber(int address, unsigned char* number, int length)
{
    // Declare function variables
    int i;
    int j;
    
    // dc550_printf("\r\nSaving: %s", number);
    
    // If there is space, schedule writing value into EEPROM
    if((eepromData.numberOfMessages + length) < EEPROM_ARRAY_SIZE) {
        i = (eepromData.beginIndex + eepromData.numberOfMessages) &
            EEPROM_ARRAY_MASK;
        for(j = 0; j < length; j++) {
            eepromData.address[i] = address + j;
            eepromData.value[i] = number[j];
            eepromData.numberOfMessages++;
            i = ((i + 1) & EEPROM_ARRAY_MASK);
        }
        return 1;
    }
    
    // Otherwise, return 0
    else
        return 0;
}

int eeprom_SetSetting(int address, unsigned char value)
{
    // Declare function variables
    int i;
    
    // If there is space, schedule writing value into EEPROM
    if((eepromData.numberOfMessages + 1) < EEPROM_ARRAY_SIZE) {
        i = (eepromData.beginIndex + eepromData.numberOfMessages) &
            EEPROM_ARRAY_MASK;
        eepromData.address[i] = address;
        eepromData.value[i] = value;
        eepromData.numberOfMessages++;
        
        return 1;
    }
    
    // Otherwise, return 0
    else
        return 0;
}

int eeprom_SetVersion(unsigned char version)
{
    // Declare function variables
    int i;
    
    // If there is space, schedule writing version and version inverse into
    // EEPROM, and reset the eepromData.eepromVersion variable
    if((eepromData.numberOfMessages + 1) < EEPROM_ARRAY_SIZE) {
        i = (eepromData.beginIndex + eepromData.numberOfMessages) &
            EEPROM_ARRAY_MASK;
        eepromData.address[i] = EEPROM_ADDRESS_VERSION;
        eepromData.value[i] = version;
        eepromData.numberOfMessages++;

        i = (eepromData.beginIndex + eepromData.numberOfMessages) &
            EEPROM_ARRAY_MASK;
        eepromData.address[i] = EEPROM_ADDRESS_VERSIONINVERSE;
        eepromData.value[i] = ~version;
        eepromData.numberOfMessages++;
        
        eepromData.eepromVersion = version;
        
        return 1;
    }
    
    // Otherwise, return 0
    else
        return 0;
}

unsigned char eeprom_GetVersion(void)
{
    return eepromData.eepromVersion;
}

int eeprom_WriteArray(int address, unsigned char* array, int arraysize)
{
    // Declare function variables
    int i;
    int j;
    
    for(j = 0; j < arraysize; j++) {
        for(i = 0; i < 4000; i++);     // Wait 4ms (a write takes over 3ms)
        if( eeprom_WriteByte(address + j, array[j]) == 0)
          return 0;
    }
    
    return 1;
}

int eeprom_ReadArray(int address, unsigned char* array, int arraysize)
{
    // Declare function variables
    int i;
    int j;
    
    for(j = 0; j < arraysize; j++) {
        for(i = 0; i < 4000; i++);     // Wait 4ms (a write takes over 3ms)
        if( eeprom_ReadByte(address + j, &array[j]) == 0)
          return 0;
    }
    
    return 1;
}

int eeprom_WriteByte(int addr, unsigned char val)
{   
    i2c_StartBit(EEPROM);
    if (!i2c_AddressSlave(EEPROM, FALSE)) {
        i2c_StopBit(EEPROM);
        return 0;
    }

    i2c_WriteByte(EEPROM, (addr >> 8) & 0xFF );
    i2c_WriteByte(EEPROM, (addr & 0xFF));
    i2c_WriteByte(EEPROM, val);
    i2c_StopBit(EEPROM);
    return 1;
}

int eeprom_ReadByte(int addr, unsigned char *val)
{
    i2c_StartBit(EEPROM);
    if (!i2c_AddressSlave(EEPROM, FALSE)) {
        i2c_StopBit(EEPROM);
        return 0;
    }
    i2c_WriteByte(EEPROM, (addr >> 8) & 0xFF );
    i2c_WriteByte(EEPROM, (addr & 0xFF));

    i2c_StartBit(EEPROM);
    if (!i2c_AddressSlave(EEPROM, TRUE)) {
        i2c_StopBit(EEPROM);
        return 0;
    }
    i2c_ReadByte(EEPROM, val, TRUE);
    i2c_StopBit(EEPROM);
    return 1;
}

/******************************************************************************
                       DIGPOT INTERFACE ROUTINES
 *****************************************************************************/
#define DIGPOT_WRITEDATA_CMD 0x10

void digpot_Volume(unsigned char val)
{
    if (val > 15) val = 15;
    digpotData.VolumeSetting = digpotData.VolumeLevels[val];
    digpotData.VolumeRequest = TRUE;
}

void digpot_Contrast(unsigned char val)
{
    if (val > 15) val = 15;
    digpotData.ContrastSetting = digpotData.ContrastLevels[val];
    digpotData.ContrastRequest = TRUE;
}

int digpot_WriteByte(DIGPOT_ID potId, int value)
{
    i2c_StartBit(DIGPOT);
    i2c_WriteByte(DIGPOT, ((DIGPOT_WRITEDATA_CMD+potId) & 0xff) );
    i2c_WriteByte(DIGPOT, value);
    i2c_StopBit(DIGPOT);
    return 1;
}


/******************************************************************************
 *  FUNCTION: void i2cdriver_init(void)
 ******************************************************************************
 *  DESCRIPTION:
 *  This function is called during the initialization phase to initialize all
 *  of the i2c driver variables.
 *****************************************************************************/
void i2cdriver_init(void)
{
    int i;
    unsigned char inverse;

    // Set up clock and data lines to be outputs and to be high
    I2C_POUT |= (I2C_CLOCK_MSK | I2C_DATA_MSK);
    I2C_PDIR |= (I2C_CLOCK_MSK | I2C_DATA_MSK);
    i2cData.i2cMaster = IDLE;

    rtcData.UpdateClock = FALSE;
    // 030321: dtmfData.Request = FALSE;
    digpotData.VolumeRequest = FALSE;
    digpotData.ContrastRequest = FALSE;

    // 030321: dtmf_PlayTone(DTMF_OFF);

    // Initialize volume/contrast values for the digital pot
    digpotData.ContrastLevels[0] = 218;
    digpotData.ContrastLevels[1] = 214;
    digpotData.ContrastLevels[2] = 210;
    digpotData.ContrastLevels[3] = 206;
    digpotData.ContrastLevels[4] = 202;
    digpotData.ContrastLevels[5] = 198;
    digpotData.ContrastLevels[6] = 194;
    digpotData.ContrastLevels[7] = 190;
    digpotData.ContrastLevels[8] = 186;
    digpotData.ContrastLevels[9] = 182;
    digpotData.ContrastLevels[10] = 178;
    digpotData.ContrastLevels[11] = 174;
    digpotData.ContrastLevels[12] = 170;
    digpotData.ContrastLevels[13] = 166;
    digpotData.ContrastLevels[14] = 162;
    digpotData.ContrastLevels[15] = 158;

    digpotData.VolumeLevels[0] = 136;
    digpotData.VolumeLevels[1] = 143;
    digpotData.VolumeLevels[2] = 150;
    digpotData.VolumeLevels[3] = 157;
    digpotData.VolumeLevels[4] = 164;
    digpotData.VolumeLevels[5] = 171;
    digpotData.VolumeLevels[6] = 178;
    digpotData.VolumeLevels[7] = 186;
    digpotData.VolumeLevels[8] = 193;
    digpotData.VolumeLevels[9] = 200;
    digpotData.VolumeLevels[10] = 207;
    digpotData.VolumeLevels[11] = 214;
    digpotData.VolumeLevels[12] = 221;
    digpotData.VolumeLevels[13] = 228;
    digpotData.VolumeLevels[14] = 235;
    digpotData.VolumeLevels[15] = 242;
    
    // Initialize digital pot
    digpot_WriteByte(VOLUME_POT, digpotData.VolumeLevels[0]);
    digpot_WriteByte(CONTRAST_POT, digpotData.ContrastLevels[0]);    

    // Just powering-up: set time/date to *something*
    memset(rtcData.TOD, 0, sizeof(rtcData.TOD));
    rtc_SetTimeOfDay(0, 1, 1, 0, 0, 0, 0);

    // Initialize EEPROM Variables
    eepromData.beginIndex = 0;
    eepromData.numberOfMessages = 0;

    // Get EEPROM Version Number
    eeprom_ReadByte(EEPROM_ADDRESS_VERSION, &eepromData.eepromVersion);
    for(i = 0; i < 4000; i++);         // Wait 4ms (a write takes over 3ms)
    eeprom_ReadByte(EEPROM_ADDRESS_VERSIONINVERSE, &inverse);
    if((eepromData.eepromVersion ^ inverse) != 0xFF)
      eepromData.eepromVersion = 0;
}


/******************************************************************************
 *  FUNCTION: void i2cdriver_exec(void)
 ******************************************************************************
 *  DESCRIPTION:
 *  This function is called to execute the i2c driver task.
 *****************************************************************************/
void i2cdriver_exec(void)
{
    /*
    030321 Modification:
    // If we're ringing, handle any state machine change *first*
    if (audio_ringerStateMachine())
        return;

    // Now, handle lower priority tasks
    // Any DTMF tones to generate?
    if ( dtmfData.Request && (i2cData.i2cMaster == IDLE) ) {
        dtmf_WriteByte(dtmfData.Tone);
        dtmfData.Request = FALSE;
        return;
    }
    */
    
    // Updating the time of day (RTC)?
    if ( rtcData.UpdateClock &&
         ((i2cData.i2cMaster == RTC) || (i2cData.i2cMaster == IDLE)) ) {
        i2cData.i2cMaster = RTC;
        if (rtcData.Index > rtcData.LastIndex) {
            rtcData.UpdateClock = FALSE;
            i2cData.i2cMaster = IDLE;
        }
        else {
            // Write out the next byte to the RTC chip
            rtc_WriteByte(rtcData.rtcMsg[rtcData.Index][0],
                          rtcData.rtcMsg[rtcData.Index][1]);
            rtcData.Index++;
            return;
        }
    }

    // Volume adjustment requested?
    if ( digpotData.VolumeRequest && (i2cData.i2cMaster == IDLE) ) {
        digpot_WriteByte(VOLUME_POT, digpotData.VolumeSetting);
        digpotData.VolumeRequest = FALSE;
        return;
    }

    // Contrast adjustment requested?
    if ( digpotData.ContrastRequest && (i2cData.i2cMaster == IDLE) ) {
        digpot_WriteByte(CONTRAST_POT, digpotData.ContrastSetting);
        digpotData.ContrastRequest = FALSE;
        // dc550_printf("\r\nSet contrast to %d", digpotData.ContrastSetting);
        return;
    }

    // EEPROM write requested?
    if ( eepromData.numberOfMessages &&
         ((i2cData.i2cMaster == EEPROM) || (i2cData.i2cMaster == IDLE)) ) {
        
        // Write the byte in the array
        eeprom_WriteByte( eepromData.address[eepromData.beginIndex],
                          eepromData.value[eepromData.beginIndex] );
        
        // Increment the begin index, decrement the number of messages
        eepromData.beginIndex = ( (eepromData.beginIndex + 1) & 
                                  EEPROM_ARRAY_MASK );
        eepromData.numberOfMessages--;
        
        // If there are still more messages to write, reserve the I2C bus
        if(eepromData.numberOfMessages)
          i2cData.i2cMaster = EEPROM;
        else
          i2cData.i2cMaster = IDLE;
    }

    // Now, handle the *really* low priority tasks
    if (i2cData.i2cMaster == IDLE) {
        switch (idleTask) {
        case RTC_UPDATE:
            /* Update our Notion of Time of Day */
            i2c_StartBit(RTC);
            if (!i2c_AddressSlave(RTC, FALSE)) {
                i2c_StopBit(RTC);
                idleTask++;
                return;
            }
            i2c_WriteByte(RTC, RTC_SECONDS_ADDR);
            i2c_StartBit(RTC);
            if (!i2c_AddressSlave(RTC, TRUE)) {
                i2c_StopBit(RTC);
                idleTask++;
                return;
            }
            i2c_ReadByte(RTC, rtcData.TOD, FALSE);
            i2c_ReadByte(RTC, rtcData.TOD+1, FALSE);
            i2c_ReadByte(RTC, rtcData.TOD+2, FALSE);
            i2c_ReadByte(RTC, rtcData.TOD+3, FALSE);
            i2c_ReadByte(RTC, rtcData.TOD+4, TRUE);
            i2c_StopBit(RTC);
            idleTask++;
            return;

        case RTC_DISPLAY:
            {
            static int last_mins=-1;
            int year,month,date,hour,mins,secs,dow;
            /*
            char *days[8] =
                 {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT", "---" };
            */

            rtc_GetTimeOfDay(&year, &month, &date, &hour, &mins, &secs, &dow);
            if (dow > 6) dow = 7;
            if (mins != last_mins) {
                /*
                dc550_printf("\r\n%s %c%c-%c%c-0%c %c%c:%c%c:%c%c",
                             days[dow], '0'+(month>>4), '0'+(month&0xf),
                             '0'+(date>>4), '0'+(date&0xf),'0'+year, 
                             '0'+(hour>>4), '0'+(hour&0xf),
                             '0'+(mins>>4), '0'+(mins&0xf),
                             '0'+(secs>>4), '0'+(secs&0xf));
                */
                last_mins = mins;
            }
            idleTask++;
            return;
            }

        case I2C_IDLE_TASK_LAST:
            idleTask = I2C_IDLE_TASK_FIRST;
            break;
        }
    }

    return;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?