I am editing the code below, it's for sniffing i2c bus on the fm-tuner. In this code i wanna use millis() for measuring time between block_2 and block_4, and also for other things. But code use interrupts and built-in timer switched to off. If I enable it all decoding become very unstable. So how can i use millis()? Stand alone oscillator or something can be changing in the code?
/*
Arduino program for interfacing the Sony XDR-F1HD Receiver to RDS Spy.
(Tested on both ATMEGA168 and ATMEGA328 based Arduinos.)
(c) 2010-2011 by Ray H. Dees
Version Modified By Date Comments
.10 R. Dees 12/23/2010 Initial Release.
.11 R. Dees 01/04/2011 Modified to support RDS Spy (Version 0.94) "RESET" command.
.12 R. Dees 04/10/2011 Modified to support Arduinos running at 16mHz on 3.3v.
Inputs:
Serial Data (SDA) - Arduino Digital Pin 2.
Serial Clock (SCK) - Arduino Digital Pin 3.
Ouputs:
RDS data formatted in RDS Spy protocol via the Arduino USB port.
Setup:
RDS Spy should be configured as follows:
Select Configure,
Select RDS Source,
Select P75/P175 FM Analyzer,
Set Connection Type RS232/USB,
Select the RS232 COM Port that your Arduino appears as.
You may use this program for personal purposes only. The use of this program
in a commercial product requires explicit written permission from the author.
The author is not responsible or liable for damage or loss that may be caused
by the use of this program.
*/
#include <WProgram.h>
//
// Definitions
//
#define SDA 2
#define SCK 3
#define BUFFER_LENGTH 64
#define DELAY asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop");
//
enum {IDLE, START, RCVG, STOP};
//
// Global variables
//
byte* rxBuffer = 0;
volatile byte rxBufferIndex = 0;
volatile byte rxBits = 0;
volatile byte rxComplete = 0;
volatile byte rxCount = 0;
volatile byte rxState = 0;
//
word address = 0;
word data = 0;
byte block = 0;
word block_1;
word block_2;
word block_3;
word block_4;
byte group_complete = 0;
byte synchronized = 0;
//
// Setup begins here.
//
void setup()
{
delay(500); // A 500ms delay, change this to suit your taste!
pinMode(SDA, INPUT);
digitalWrite(SDA, HIGH);
pinMode(SCK, INPUT);
digitalWrite(SCK, HIGH);
delay(100);
initialize(); // Call initialize to set everything up.
delay(100);
Serial.begin(19200);
}
//
// Main Program Loop.
//
void loop()
{
while(1)
{
if (rxComplete)
{
update_blocks();
rxComplete = 0;
}
if (group_complete)
{
send_data();
group_complete = 0;
}
}
}
//
// RDS Blocks get updated and sorted here. First the register address, then the corresponding data.
//
void update_blocks()
{
if (rxBuffer[0] != 0x38) // This version does not support HD, return.
return;
if (rxBuffer[4] == 0xC4) // Any write to address 0xC4 is a channel change.
{
clear(); // Reset RDS Spy.
return;
}
if (rxBuffer[3] == 0x30)
{
address = 0x0000 | rxBuffer[5] << 8 | rxBuffer[6];
synchronized = 1;
switch (address)
{
case 0x0080:
block = 1;
break;
case 0x0084:
block = 2;
break;
case 0x0088:
block = 3;
break;
case 0x008C:
block = 4;
break;
default:
block = 0;
synchronized = 0;
}
return;
}
if (!synchronized)
return;
if (rxBuffer[3] == 0x31)
{
data = 0x0000 | rxBuffer[5] << 8 | rxBuffer[6];
switch (block)
{
case 1:
block_1 = data;
break;
case 2:
block_2 = data;
break;
case 3:
block_3 = data;
break;
case 4:
block_4 = data;
group_complete = 1;
break;
}
}
}
//
// Send the data to RDS Spy.
//
void send_data()
{
Serial.println("G:");
printHex(block_1);
printHex(block_2);
printHex(block_3);
printHex(block_4);
Serial.println();
Serial.println();
}
//
// Four digit hexadecimal print routine.
//
void printHex(word value)
{
Serial.print(value >> 12 & 0x0F, HEX);
Serial.print(value >> 8 & 0x0F, HEX);
Serial.print(value >> 4 & 0x0F, HEX);
Serial.print(value >> 0 & 0x0F, HEX);
}
//
// This routine resets RDS Spy.
//
void clear()
{
Serial.println("G:");
Serial.println("RESET");
Serial.println();
rxState = IDLE;
group_complete = 0;
}
//
// Setup the microprocessor.
//
void initialize()
{
cli(); // Disable global interrupts while we make our changes.
EICRA |= (1 << ISC11 | 1 << ISC10 | 1 << ISC00); // Setup Interrupt 0 & 1.
EIMSK |= (1 << INT1 | 1 << INT0); // Enable Interrupt 0 & 1;
ADCSRA &= ~(1 << ADEN); // Disable the analog comparator.
TIMSK0 &= ~(1 << TOIE0); // Disable Timer 0.
TIMSK1 &= ~(1 << TOIE1); // Disable Timer 1 - Turns Off PWM.
TIMSK2 &= ~(1 << TOIE2); // Disable Timer 2.
rxBuffer = (uint8_t*) calloc(BUFFER_LENGTH, sizeof(uint8_t)); // Initialize the receive buffer.
sei(); // Enable global interrupts.
}
//
// Interrupt 0 Service Routine - Triggered on the Rising and Falling edge of Serial Data.
//
ISR(INT0_vect, ISR_NOBLOCK)
{
byte mask = (PIND & 0x0C);
switch (rxState)
{
case IDLE:
if (mask != 0x08)
return;
rxBufferIndex = 0;
rxState = START;
break;
case START:
rxBits = 0;
rxCount = 0;
rxState = RCVG;
break;
case RCVG:
if (mask == 0x08)
{
rxState = START;
return;
}
case STOP:
if (mask != 0x0C)
return;
rxComplete = 1;
rxState = IDLE;
break;
default:
rxState = IDLE;
break;
}
}
//
// Interrupt 1 Service Routine - Triggered on the Rising edge of Serial Clock.
//
ISR(INT1_vect, ISR_NOBLOCK)
{
DELAY;
switch (rxCount)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
if (PIND & _BV(2))
bitSet(rxBits, (7 - rxCount));
rxCount++;
break;
case 8:
rxBuffer[rxBufferIndex] = rxBits;
rxBufferIndex++;
rxBits = 0;
rxCount = 0;
break;
default:
rxState = IDLE;
break;
}
}
//
// That's all.
//