Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- 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.
- //
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement