8 Replies Latest reply on May 11, 2015 5:10 PM by abdurrachman.mappuji

    CY8CKIT-049, USB-Serial CY7C65211 use as an I2C master.

    miguel.parra

      Not sure if this goes here or in the USB forum but since it's part of the PSoC 4xxx prototype boards I decided to post it in here:

         

      Someone in a forum asked for a cheap and easy USB to I2C Dev Kit, so I suggested using the break off USB Serial part of the CY8CKIT-049.

         

      As my example I used an RTC clock based on the PCF8563 chip from NXP

         

      So first I open the Cypress USB-Serial Configuration Utility after plugin in the board to my PC USB port, and selected my USB-Serial (Single Channel) target and clicked on Connect:

         

         


      I left the USB configuration alone, but you can change the VID/PID manufacturer and product strings etc, also left the IO levels to CMOS (you can select TTL) and clicked on the SCB tab:



      Next I selected the mode to be I2C and clicked Configure

         

      Note that you can set the notification LEDs to use GPIO pins to drive transmit and receive individual LEDs or a single one for both tx/rx

         

      Selected 400KHz and set it to be in Master mode and ok.

         




      Back to the previous screen click on program.



      And it will come back with success (if everything is setup right).

         


         

       

         

      I added two 2.2K Ohm pull-up resistors as required for 400Kbps

         

         

      Altered the I2cmaster example that came with the USB-Serial Software Development Kit

         

      http://www.cypress.com/?rID=83110

         

      I'll include the code at the end of the post.

         

      I did probe the SCL and SDA to make sure I was reading/writing the right data:

         

         

       And it worked great:

         

         

      So that little chip that we use for communicating with the boot loader has other uses, it can also do UART of course, and SPI.

         

      Here is the code (Windoes based):

         
              
         
              
         
          #include "stdafx.h"   
         
              
         
          #include <stdio.h>   
         
          #include <windows.h>   
         
          #include <dbt.h>   
         
          #include <conio.h>   
         
          #include "..\..\..\library\inc\CyUSBSerial.h"   
         
              
         
          // Define VID & PID   
         
          // These numbers depends on individual products   
         
          #define VID 0x04B4   
         
          #define PID 0x0004    
         
              
         
          //Variable to store cyHandle of the selected device   
         
          CY_HANDLE cyHandle;    
         
          //Varible to capture return values from USB Serial API    
         
          CY_RETURN_STATUS cyReturnStatus;    
         
              
         
          //CY_DEVICE_INFO provides additional details of each device such as product Name, serial number etc..   
         
          CY_DEVICE_INFO cyDeviceInfo, cyDeviceInfoList[16];    
         
              
         
          //Structure to store VID & PID defined in CyUSBSerial.h   
         
          CY_VID_PID cyVidPid;   
         
              
         
          //Data configuration and buffer structures   
         
          CY_I2C_DATA_CONFIG cyI2CRWDataConfig;   
         
          CY_DATA_BUFFER cyDataRWBuffer;   
         
              
         
          //Variables used by application   
         
          UINT8 cyNumDevices;   
         
          unsigned char deviceID[16];   
         
              
         
          #define changeIntToHex(dec)     ( (((dec)/10) <<4) + ((dec)%10) )   
         
          #define converseIntToHex(dec)     ( (((dec)>>4) *10) + ((dec)%16) )   
         
          #define changeHexToInt(hex)     ( (((hex)>>4) *16 ) + ((hex)%16) )   
         
          #define converseHexToInt(hex)     ( (((hex)/10) <<4 ) + ((hex)%10) )   
         
              
         
          #define CTRL_BUF1     0x00   
         
          #define CTRL_BUF2     0x01   
         
              
         
          #define SECOND_DATA_BUF     0x02   
         
          #define MINUTE_DATA_BUF     0x03   
         
          #define HOUR_DATA_BUF     0x04   
         
              
         
          #define DAY_DATA_BUF             0x05   
         
          #define WEEK_DATA_BUF     0x06   
         
          #define MONTH_DATA_BUF     0x07   
         
          #define YEAR_DATA_BUF     0x08   
         
              
         
          #define MINUTE_AE_BUF     0x09   
         
          #define HOUR_AE_BUF     0x0A   
         
          #define DAY_AE_BUF     0x0B   
         
          #define WEEK_AE_BUF     0x0C   
         
              
         
          #define CLK_FRQ_BUF     0x0D   
         
          #define TIMER_CTRL_BUF     0x0E   
         
          #define COUNT_VAL_BUF     0x0F   
         
              
         
          typedef unsigned char uchar;   
         
          typedef unsigned int uint;   
         
              
         
          void WriteAByte(uchar wordAdr, uchar dat)   
         
          {   
         
           uchar buffer[2];   
         
           buffer[0] = wordAdr;   
         
           buffer[1] = dat;   
         
           cyDataRWBuffer.buffer = buffer;   
         
           cyDataRWBuffer.length = 2;   
         
           CyI2cWrite(cyHandle, &cyI2CRWDataConfig, &cyDataRWBuffer, 5000);   
         
          //     SMBus_Write(0xA2, wordAdr, dat, 2);   
         
          }   
         
              
         
          void ReadNByte(uchar wordAdr, uchar *pRdDat, uchar length)   
         
          {   
         
           cyDataRWBuffer.buffer = &wordAdr;   
         
           cyDataRWBuffer.length = 1;   
         
           CyI2cWrite(cyHandle, &cyI2CRWDataConfig, &cyDataRWBuffer, 5000);   
         
          //     SMBus_Write(0xA2, wordAdr, 0, 1);   
         
              
         
           cyDataRWBuffer.buffer = pRdDat;   
         
           cyDataRWBuffer.length = length;   
         
           CyI2cRead(cyHandle, &cyI2CRWDataConfig, &cyDataRWBuffer, 5000);   
         
          //     SMBus_Read(0xA3, pRdDat, 11);   
         
          }   
         
              
         
          void PCF8563_getTime(uchar *buf)   
         
          {   
         
           ReadNByte(SECOND_DATA_BUF, buf, 11);   
         
           buf[0] = buf[0] & 0x7f;     //get second data   
         
           buf[1] = buf[1] & 0x7f;     //get minute data   
         
           buf[2] = buf[2] & 0x3f;     //get hour data   
         
           buf[3] = buf[3] & 0x3f;     //get day data   
         
           buf[4] = buf[4] & 0x07;     //get weekday data   
         
           buf[5] = buf[5] & 0x9f;     //get century_month data (most significant bit Century bit 0=2000 1=1900)   
         
          //     buf[6] = buf[6];     //get year data   
         
           buf[7] = buf[7] & 0xff;     //get minute_alarm data   
         
           buf[8] = buf[8] & 0xaf;     //get hour_alarm data   
         
           buf[9] = buf[9] & 0xaf;     //get day_alarm data   
         
           buf[10] = buf[10] & 0x87;     //get weekday_alarm data   
         
              
         
           buf[0] = converseIntToHex(buf[0]);   
         
           buf[1] = converseIntToHex(buf[1]);   
         
           buf[2] = converseIntToHex(buf[2]);   
         
           buf[3] = converseIntToHex(buf[3]);   
         
           buf[4] = converseIntToHex(buf[4]);   
         
           buf[5] = converseIntToHex(buf[5]);   
         
           buf[6] = converseIntToHex(buf[6]);   
         
          }   
         
              
         
          void PCF8563_setTime(uchar hour, uchar minute, uchar second, uchar day, uchar weekday, uchar month, uint year)   
         
          {   
         
           hour = changeIntToHex(hour);   
         
           minute = changeIntToHex(minute);   
         
           second = changeIntToHex(second);   
         
           day = changeIntToHex(day);   
         
           weekday = changeIntToHex(weekday);   
         
           month = changeIntToHex(month);   
         
           if (year < 2000)   
         
           {   
         
           // if 19xx set Century bit   
         
           month |= 0x80;   
         
           }   
         
           year %= 100;   
         
           year = changeIntToHex(year);   
         
              
         
           WriteAByte(HOUR_DATA_BUF, hour);   
         
           WriteAByte(MINUTE_DATA_BUF, minute);   
         
           WriteAByte(SECOND_DATA_BUF, second);   
         
           WriteAByte(DAY_DATA_BUF, day);   
         
           WriteAByte(WEEK_DATA_BUF, weekday);   
         
           WriteAByte(MONTH_DATA_BUF, month);   
         
           WriteAByte(YEAR_DATA_BUF, year);   
         
          }   
         
              
         
          void PCF8563_init(void)   
         
          {   
         
           WriteAByte(CTRL_BUF1, 0x00);     //basic setting   
         
           WriteAByte(CTRL_BUF2, 0x12);     //alarm enable   
         
          }   
         
              
         
          CY_RETURN_STATUS I2CMasterSetup(int deviceNumber)   
         
          {   
         
           CY_I2C_CONFIG cyI2CConfig;   
         
           CY_RETURN_STATUS rStatus;   
         
           int interfaceNum = 0;   
         
              
         
           // Configure the I2C read and write data   
         
           cyI2CRWDataConfig.isStopBit = true;   
         
           cyI2CRWDataConfig.isNakBit = false;   
         
           cyI2CRWDataConfig.slaveAddress = 0xA2 >> 1;   
         
              
         
           // Configure the I2C   
         
           printf("Opening I2C device with device number %d...\n", deviceNumber);   
         
              
         
           //Open the device at deviceNumber   
         
           rStatus = CyOpen(deviceNumber, interfaceNum, &cyHandle);   
         
           if (rStatus != CY_SUCCESS)   
         
           {   
         
           printf("I2C Device open failed...\n");   
         
           return rStatus;   
         
           }   
         
              
         
           // Get configuration   
         
           printf("I2C Open successfull. Invoking API for retrieving I2C configuration...\n");   
         
           rStatus = CyGetI2cConfig(cyHandle, &cyI2CConfig);   
         
           if (rStatus != CY_SUCCESS)   
         
           {   
         
           printf("CyGetI2cConfig returned failure code.\n");   
         
           return rStatus;   
         
           }   
         
           printf("I2C Frequency : %d , Slave address : %d\n",   
         
           cyI2CConfig.frequency,   
         
           cyI2CConfig.slaveAddress);   
         
              
         
           // Set configuration   
         
              
         
           // Configure I2C with different settings   
         
           printf("Setting new I2C configuration...\n");   
         
           cyI2CConfig.frequency = 400000;   
         
           cyI2CConfig.slaveAddress = 0x60; // Ain't matter, this is for slave mode.   
         
           cyI2CConfig.isMaster = 1;   
         
           printf("New Configuration - I2C Frequency : %d , Slave address : %d, isMaster : %d\n",   
         
           cyI2CConfig.frequency,   
         
           cyI2CConfig.slaveAddress,   
         
           cyI2CConfig.isMaster);   
         
              
         
           rStatus = CySetI2cConfig(cyHandle, &cyI2CConfig);   
         
           if (rStatus != CY_SUCCESS)   
         
           {   
         
           printf("CySetI2cConfig returned failure code.\n");   
         
           return rStatus;   
         
           }   
         
           printf("Setting new I2C configuration successful.\n");   
         
              
         
           // Check to see if the new configuration is applied on I2C   
         
           printf("Checking the new I2C configuration ...\n");   
         
           rStatus = CyGetI2cConfig(cyHandle, &cyI2CConfig);   
         
           if (rStatus != CY_SUCCESS)   
         
           {   
         
           printf("CyGetI2cConfig returned failure code.\n");   
         
           return rStatus;   
         
           }   
         
           printf("I2C Configuration retrieved - I2C Frequency : %d , Slave address : %d, isMaster : %d\n",   
         
           cyI2CConfig.frequency,   
         
           cyI2CConfig.slaveAddress,   
         
           cyI2CConfig.isMaster);   
         
           return rStatus;   
         
          }   
         
              
         
          int FindDeviceAtSCB0()   
         
          {   
         
           CY_VID_PID cyVidPid;   
         
              
         
           cyVidPid.vid = VID; //Defined as macro   
         
           cyVidPid.pid = PID; //Defined as macro   
         
              
         
           //Array size of cyDeviceInfoList is 16    
         
           cyReturnStatus = CyGetDeviceInfoVidPid (cyVidPid, deviceID, (PCY_DEVICE_INFO)&cyDeviceInfoList, &cyNumDevices, 16);   
         
              
         
           int deviceIndexAtSCB0 = -1;   
         
           for (int index = 0; index < cyNumDevices; index++)   
         
           {   
         
           printf ("\nNumber of interfaces: %d\n \   
         
           Vid: 0x%X \n\   
         
           Pid: 0x%X \n\   
         
           Serial name is: %s\n\   
         
           Manufacturer name: %s\n\   
         
           Product Name: %s\n\   
         
           SCB Number: 0x%X \n\   
         
           Device Type: %d \n\   
         
           Device Class: %d\n\n\n",   
         
           cyDeviceInfoList[index].numInterfaces,                     
         
           cyDeviceInfoList[index].vidPid.vid,   
         
           cyDeviceInfoList[index].vidPid.pid,   
         
           cyDeviceInfoList[index].serialNum,   
         
           cyDeviceInfoList[index].manufacturerName,   
         
           cyDeviceInfoList[index].productName,   
         
           cyDeviceInfoList[index].deviceBlock,   
         
           cyDeviceInfoList[index].deviceType[0],   
         
           cyDeviceInfoList[index].deviceClass[0]);   
         
              
         
           // Find the device at device index at SCB0   
         
           if (cyDeviceInfoList[index].deviceBlock == SerialBlock_SCB0)   
         
           {   
         
           deviceIndexAtSCB0 = index;   
         
           }   
         
           }   
         
           return deviceIndexAtSCB0;   
         
          }   
         
              
         
          char *weekday[] =   
         
          {   
         
           "Sunday",   
         
           "Monday",   
         
           "Tuesday",   
         
           "Wednesday",   
         
           "Thursday",   
         
           "Friday",   
         
           "Saturday"   
         
          };   
         
              
         
          char *month[] =   
         
          {   
         
           "January",   
         
           "February",   
         
           "March",   
         
           "April",   
         
           "May",   
         
           "June",   
         
           "July",   
         
           "August",   
         
           "September",   
         
           "October",   
         
           "November",   
         
           "December"   
         
          };   
         
              
         
          /** ********************************   
         
          Application main() function   
         
          *** ******************************** */        
         
          int _tmain(int argc, _TCHAR* argv[])   
         
          {   
         
           //Assmumptions:   
         
           //1. SCB0 is configured as I2C    
         
              
         
           int deviceIndexAtSCB0 = FindDeviceAtSCB0();   
         
              
         
           //Open the device at deviceIndexAtSCB0   
         
           if (deviceIndexAtSCB0 >= 0)   
         
           {   
         
           //Assuming that device at index is I2C device   
         
           //Device Open, Close, Configuration, Data operations are handled in the function I2CMaster   
         
              
         
           cyReturnStatus = I2CMasterSetup(deviceIndexAtSCB0);   
         
           if (cyReturnStatus == CY_SUCCESS)   
         
           {   
         
           SYSTEMTIME localtime;   
         
           uchar time[16], tmp = 0;   
         
           char command;   
         
           printf("\nI2CMaster returned success.\n");   
         
              
         
           PCF8563_init();   
         
              
         
           printf("\nType s to set, r to reset, anything else to resume current time\n");   
         
           command = getch();   
         
           if (command == 's')   
         
           {   
         
           GetLocalTime(&localtime);   
         
           // 21 hours, 37 minutes, 30 seconds, day 6, weekday Friday(5), month 3, year 2015   
         
           PCF8563_setTime(localtime.wHour, localtime.wMinute, localtime.wSecond, localtime.wDay, localtime.wDayOfWeek, localtime.wMonth, localtime.wYear);   
         
           }   
         
           else if (command == 'r')   
         
           {   
         
           // 21 hours, 37 minutes, 30 seconds, day 6, weekday Friday(5), month 3, year 2015   
         
           PCF8563_setTime(23, 59, 30, 28, 6, 2, 2015);   
         
           }   
         
           while (1)   
         
           {   
         
           PCF8563_getTime(time);   
         
           if (time[0] != tmp)   
         
           {   
         
           uint year = time[5] > 80 ? 1900 : 2000;   
         
           year += time[6];   
         
           uint hour = ((time[2] % 12) == 0) ? 12 : time[2] % 12;   
         
           printf("%s, %s %d, %04d %02d:%02d:%02d %s\n", weekday[time[4]], month[((time[5] > 80) ? time[5] - 80 : time[5])-1], time[3], year, hour, time[1], time[0], (time[2]>11) ? "PM" : "AM");   
         
           }   
         
           tmp = time[0];   
         
           }   
         
           CyClose(cyHandle);   
         
           }   
         
           else   
         
           {   
         
           printf("\nI2CMaster returned failure code.\n");   
         
           }   
         
           } //cyNumDevices > 0 && cyReturnStatus == CY_SUCCESS   
         
           return 0;   
         
          }