Sicily 2373. I2C

2373. I2C

Constraints

Time Limit: 1 secs, Memory Limit: 256 MB

Description

 

I 2C (Inter-Integrated Circuit) is a serial communication protocol that is used to attach low-speed peripherals (100 kbit/sec) to a motherboard, embedded system or cell phone. A single I 2C data bus may have several devices attached, each with a different 7-bit address. One of the nice things about I 2C is that it only requires two signal lines, SCL (clock) and SDA (data). One bit of data is presented on the I2C data bus (SDA line) per clock (SCL). Typically, one device on the bus is designated as the master, and the other devices are slaves. The master will initiate communication to a specific device on the bus by specifying its address in a transaction.
If there is no activity on the I 2C bus, both the SCL and SDA signals are in a high state (1). The master initiates a transaction on the bus by pulling the SDA signal to a low state (0), while the SCL signal is high (1): this is called a START bit. At this point, all slaves on the bus must start paying attention to the signaling to see if the transaction is directed at them. The master will then send the 7bit slave address (most significant bit first), one bit at-a-time. This is done by bringing the SCL signal low (0), presenting the next bit value on the SDA line, then releasing the SCL signal so it goes high (1). The slaves will read the SDA signal as soon as the clock goes high (1). This operation is repeated 7 times, one for each bit of the desired slave address. Another data bit is presented on the bus in the same manner. This last bit is an indicator as to whether the master wants to read from (1) or write to (0) the addressed slave device. When a slave recognizes its address on the bus, it must acknowledge  (ACK) that it is available and ready by pulling the SDA line low. The master will see this the next time it brings the clock high, at which point, the data transfer can begin. If no  ACK is seen this means that the slave specified by the address does not exist. Note: If no device pulls a signal low, it will go high by default; a device simplyreleases a signal, and it will go high.
Data is always transferred as 8 bit bytes, 1 bit at-a-time, most significant bit first. After each byte, the slave must  ACK the master by pulling the SDA line low. If the slave is not ready to transmit (or receive) the next byte of data, it may pull the SCL line low. This will cause the master to go into await mode until the slave is ready. The slave indicates it is ready by bringing SDA low, and releasing the SCL line so it goes high. The next byte of data can then be transferred. The sequence repeats until the master decides all the data has been transferred, at which point it will send a STOP bit. This is done when the master lets the SDA line go high while the SCL line is high.
For this problem, you will write a program that sniffs the  I 2 C bus signals and displays the details of transactions.

Input

The first line of input contains a single integer P, (1$ \le$P$ \le$1000), which is the number of data sets that follow. Each data set consists of multiple lines which represents a single I2C transaction. The first line contains two (2) decimal integer values: the problem number, followed by a space, followed by the number of signal samples S, (1$ \le$S$ \le$1161), for the transaction. The remaining line(s) contain(s) the signal samples. Each line of samples contains 40 samples (except the last which may contain less). Each sample consists of 2 binary digits characters representing SCL and SDA in that order.

Output

 

For each data set, display a single line containing a decimal integer giving the data set number followed by a single space, followed by a description of the transaction. There will only be six different descriptions (two non-error cases, and four error cases):

Non-error cases:
WRITE OF  n  BYTES TO SLAVE  xx
READ OF  n  BYTES FROM SLAVE  xx

Error cases:
ERROR NO START BIT
ERROR NO STOP BIT
ERROR NO ACK FROM SLAVE  xx
ERROR NO ACK FOR DATA

n is a decimal integer (1 - 128) representing the number of data bytes. 
xx is a 2 digit hexadecimal value (00-7F) representing the slave address. 
The  ERROR NO ACK FROM SLAVE  xx case occurs when there is no ACK for the supplied address 
The  ERROR NO ACK FOR DATA case occurs when there is no ACK after a data byte

For the error cases, only the first error detected should be displayed.

Sample Input

4 
1 97 
01111001110010001000100111011101110111001000100010011100100010001000100010001000 
10001001110010001000100010011100100010001001110010001000100111001000100010001001 
1100100010001001110111001000101111 
2 169 
01111000100010011100100010001001110010001000100010011100100010001000100010001000 
10001001110010001000100010011100100010001001110010001000100111001000100010001001 
11001000100010011101110010001000100111001000100111001000100010001000100111001000 
10011100100111001000100010011100100010011101110010001000100010011100100010011101 
110111001000101111 
3 60 
01111000100010001001110010011101110010001000100010011100100010001000100010001000 
1000100111001000100010001001110010001111 
4 40 
01111000100010011101110010011100100111001111111111111111111111111111111111111111

Sample Output

1 READ OF 4 BYTES FROM SLAVE 47
2 WRITE OF 8 BYTES TO SLAVE 11 
3 ERROR NO STOP BIT 
4 ERROR NO ACK FROM SLAVE 1A

Problem Source

每周一赛第一场

// Problem#: 2373
// Submission#: 3593621
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
/*
 * F - I2C
 * ACM International Collegiate Programming Contest
 * Greater New York Region
 * October 24, 2010
 */     

#include <stdio.h>
#include <stdlib.h>

char buf[128];
char *p = NULL;

void GetSample(int &scl, int &sda)
{
    scl = sda = 0;
    for(;;){
        if(p == NULL || *p == '\0'){
            p = ::fgets(&(buf[0]), sizeof(buf), stdin);
            if(p == NULL){
                break;
            }
        }
        if(*p == '0' || *p == '1'){
            scl = *p - '0';
            p++;
            sda = *p - '0';
            p++;
            break;
        } else {
            p++;
        }
    }
}

int main(int argc, char **argv)
{
    int i, nByteCount, nProb, np, nb, scl, sda, nState, nAddr, nFlag, nBit, nByte, nLastDa;

    ::fgets(&(buf[0]), sizeof(buf), stdin);
    nProb = ::atoi(&(buf[0]));

    for(i = 1; i <= nProb; i++){
        if(::fgets(&(buf[0]), sizeof(buf), stdin) == NULL){
            break;
        }
        if(::sscanf(&(buf[0]), "%d %d", &(np), &(nb)) != 2){
            break;
        }
        nState = 0;
        nByteCount = 0;
        p = NULL;
        while(nState >= 0 && nb > 0){
            nb--;
            GetSample(scl, sda);
            switch(nState){
            case 0:  // waiting for clock high and data high
                if(scl == 1 && sda == 1){
                    nState++;
                }
                break;

            case 1: // waiting for data to go low with clock high
                if(scl == 0){
                    nState = 0;
                } else {
                    if(sda == 0){
                        // got start
                        nState++;
                        // Flag indicates we are doing the first byte (addr)
                        nFlag = 0;
                        nBit = 0;
                        nByte = 0;
                        nLastDa = 0;
                    }
                }
                break;

            case 2: // getting a byte - wait for clock low
                if(scl == 0){
                    nState++;
                } else {
                    if(nLastDa == 0 && sda == 1){
                        // SDA was brought high while clock was high, this is a stop
                        nState = -1;
                    }
                }
                break;

            case 3: // wait for clock high, then save bit
                if(scl == 1){
                    nLastDa = sda;
                    nByte = (nByte << 1) | sda;
                    nBit++;
                    if(nBit == 8){
                        if(nFlag == 0){
                            nAddr = nByte;
                        }
                        nState++;
                    } else {
                        // wait for clock to go low for next bit
                        nState = 2;
                    }
                }
                break;

            case 4: // got last bit of byte. wait for clock high and data low for ack
                if(scl == 1){
                    if(sda == 0){
                        nState++;
                        if(nFlag == 0){
                            nFlag = 1;
                        } else {
                            nByteCount++;
                        }
                        nByte = 0;
                        nBit = 0;
                        nState = 2;
                    }
                    nLastDa = sda;
                }
                break;
            }
        }
        // Gotta suck up rest of data even though we dont care about it since we saw a stop
        while(nb-- > 0){
            GetSample(scl, sda);
        }
        switch(nState){
        case 0:
        case 1:
            printf("%d ERROR NO START BIT\n", i);
            break;
        case 2:
        case 3:
            printf("%d ERROR NO STOP BIT\n", i);
            break;
        case 4:
            if(nByteCount == 0){
                printf("%d ERROR NO ACK FROM SLAVE %02X\n", i, nAddr >> 1);
            } else {
                printf("%d ERROR NO ACK FOR DATA\n", i);
            }
            break;
        case -1:
            printf("%d %s OF %d BYTES %s SLAVE %02x\n",
                i, (nAddr & 1) ? "READ" : "WRITE",
                nByteCount,
                (nAddr & 1) ? "FROM" : "TO",
                nAddr >> 1);
            break;

        default:
            printf("%d GENERAL ERROR %d SHOULDNT HAPPEN\n", i, nState);
            break;
        }
    }
    return(0);
}                                 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值