PrinceNai
Joined: 31 Oct 2016 Posts: 479 Location: Montenegro
|
i2c sniffer |
Posted: Thu Mar 21, 2019 1:37 pm |
|
|
Dear All,
This is an I2C sniffer using 18f4520. It is very basic, doesn't handle restart conditions (or maybe it does, the communication I'm listening to doesn't use them). The extracted data is stored in the buffer. No parsing is done.
main.h
Code: |
#include <18F4520.h>
#device ADC=10
#FUSES NOWDT //No Watch Dog Timer
#device ICD=TRUE
#use delay(internal=32000000)
#use i2c(Slave,Fast,sda=PIN_C4,scl=PIN_C3,force_hw,address=0x0)
|
main.c
Code: |
#include <main.h>
#INCLUDE <ctype.h>
#BYTE SSPCON1 = 0XFC6
#BYTE SSPSTAT = 0XFC7
#define S SSPSTAT, 3
#define P SSPSTAT, 4
#define SCL PIN_C3
#define SDA PIN_C4
char test;
int8 COLLECT = 0;
#define WAIT_CLK 2
#define IDLE 0
#define SAMPLE_DATA 1
#define WAIT_ACK 3
int8 Sample_Counter = 0;
int8 Raw_Data = 0;
#define BUFFER_SIZE 200 //create 200 byte large buffer
char buffer[BUFFER_SIZE];
int8 next_in = 0;
int1 Store = 0;
//-----------------------------------------------------------------------------
//----------------------------- clear buffer ----------------------------------
void Clear_UART_Buffer() {
next_in=0;
while (next_in < BUFFER_SIZE){
buffer[next_in] = '\0';
next_in++;
}
next_in=0;
}
// ****************************************************************************
#INT_EXT
void EXT_isr(void) {
}
#INT_SSP
void SSP_isr(void) {
Sample_Counter = 0;
}
// ****************************************************************************
void main() {
bit_set(SSPCON1,3); // enable SSP interrupt on START and STOP
// enable_interrupts(INT_EXT);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
output_high(PIN_B5);
Clear_UART_Buffer();
while(TRUE){
while(bit_test(S)){ // START was the last thing seen on the line
test = input_c();
delay_cycles(1); // have start?
switch (COLLECT){
// .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
// As soon as we se a STOP condition or we sample the data, SCK line is still high.
// Here we wait for SCK to go low after START condition or after sampling
// .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
case IDLE:{
if(Store){
Store = 0; // move received character to buffer
if(isalpha(Raw_Data)){
buffer[next_in] = Raw_Data;
next_in++;
if(next_in > BUFFER_SIZE){
next_in = 0;
}
}
}
while(input_state(SCL)){ // wait till PIN_C3 (SCK) goes low
}
COLLECT = WAIT_CLK;
break;
}
// .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
// The second state is waiting while the SCK is low for the next transition
// to high, where we sample the data. When we detect a change on SCK from
// LOW to HIGH, we sample SDA.
// .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
case WAIT_CLK:{ // and back high
while(!input_state(SCL)){ // wait till PIN_C3 (SCK) goes high
}
if(Sample_Counter == 8){
Sample_Counter = 0;
COLLECT = WAIT_ACK;
break;
}
COLLECT = SAMPLE_DATA;
break;
}
// .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
// Here we actually sample the data (SCK HIGH, SDA stable)
// .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
case SAMPLE_DATA:{ // SCK high to low, then low to high. Data is valid then.
output_low(PIN_B5); // get some visual indication that something is going on
if(input_state(SDA)){
bit_set(Raw_Data,0);
}
else{
bit_clear(Raw_Data,0);
}
if(Sample_Counter < 7){ // rotate until 7 bits of data are extracted
rotate_left(&Raw_Data,1);
}
// don't rotate last bit
if(Sample_Counter == 7){ // got all 8 bits, move data to buffer
Store = 1;
}
Sample_Counter++;
output_high(PIN_B5);
COLLECT = IDLE;
break;
}
// .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
case WAIT_ACK:{
COLLECT = IDLE;
break;
}
// .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
} //switch
} // while S
while(bit_test(P)){ // sit here, STOP was the last thing seen
}
delay_cycles(1);
}
}
|
|
|