Você está na página 1de 7

The C6 00 16 4E 03 turn on

the C7 33 32 68 00 vol up
81 37 10 8D 48 freq the change
the C6 00 62 4E 01 turn off

frequency:
the second and third bytes (37 and 10, in this example, - 103.5 MHz),
the second byte - low byte of
the third byte - high byte
Step - 0.05 MHz
There is one thing - you need to make the reversal of bytes to understand the meaning of,
example, for 103.55Mgts byte is B7, and the whole package of 81 B7 10 48 8D
And please, I do not mind!

The C6 00 16 4E 03 turn on
the C7 33 32 68 00 vol up
81 37 10 8D 48 freq the change
the C6 00 62 4E 01 turn off

frequency:
the second and third bytes (37 and 10, in this example, - 103.5 MHz),
the second byte - low byte of
the third byte - high byte
Step - 0.05 MHz
There is one thing - you need to make the reversal of bytes to understand the meaning of,
example, for 103.55Mgts byte is B7, and the whole package of 81 B7 10 8D 48

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/twi.h>
#include <inttypes.h>
#include <stdlib.h>

#define F_OSC 3686400L

#define FM1216_ADDR 0xC2


#define R_IF 0xA4
#define AFC 0xA5
#define MUTE 0xAC

#define CTRL_INFO_BYTE 0x80


#define CTRL_INFO_CP 6
#define CTRL_INFO_T2 5
#define CTRL_INFO_T1 4
#define CTRL_INFO_T0 3
#define CTRL_INFO_RSA 2
#define CTRL_INFO_RSB 1
#define CTRL_INFO_OS 0

int getChar(void) {
while (!(UCSRA & (1<<RXC)));
return UDR;
}

int putChar(char c) {
while (!(UCSRA & (1<<UDRE)));
UDR = c;
return 0;
}

void putString(char* str) {


char c = *(str++);
while(c != 0) {
putChar(c);
c = *(str++);
}
}

void putStringP(PGM_P str) {


char c = pgm_read_byte(str++);
while(c != 0) {
putChar(c);
c = pgm_read_byte(str++);
}
}

inline uint8_t twiStart(void) {


// send start condition
TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
// wait for transmission
while ((TWCR & (1 << TWINT)) == 0) ;
// return result
return TW_STATUS;
}

inline void twiStop(void) {


TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN);
}

inline uint8_t twiWrite(uint8_t data) {


TWDR = data;
// clear interrupt to start transmission
TWCR = (1 << TWINT) | (1 << TWEN);
// wait for transmission
while ((TWCR & (1 << TWINT)) == 0) ;
// return result
return TW_STATUS;
}

void fm1216Tune(uint16_t freqDiv, uint8_t ctrlInfo, uint8_t ports) {


uint8_t repCnt = 0;

restart:
if(repCnt++ > 100) {
return;
}

// start senden
//putStringP(PSTR("start\r"));
switch(twiStart()) {
case TW_REP_START:
case TW_START:
// allet jut
//putStringP(PSTR("ok\r"));
break;
default:
// error (keine stop condition senden)
putStringP(PSTR("error\r"));
return;
}

// adresse
//putStringP(PSTR("address\r"));
switch(twiWrite(FM1216_ADDR | TW_WRITE)) {
case TW_MT_SLA_ACK:
// allet jut
//putStringP(PSTR("ok\r"));
break;
case TW_MT_SLA_NACK:
// nack during select: device busy writing
goto restart;
default:
// error
putStringP(PSTR("error\r"));
twiStop();
return;
}

// program divider byte 1


//putStringP(PSTR("program divider byte 1\r"));
switch(twiWrite(freqDiv >> 8)) {
case TW_MT_DATA_ACK:
// allet jut
//putStringP(PSTR("ok\r"));
break;
default:
// error
putStringP(PSTR("error\r"));
twiStop();
return;
}

// program divider byte 2


//putStringP(PSTR("program divider byte 2\r"));
switch(twiWrite(freqDiv & 0xFF)) {
case TW_MT_DATA_ACK:
// allet jut
//putStringP(PSTR("ok\r"));
break;
default:
// error
putStringP(PSTR("error\r"));
twiStop();
return;
}

// control information byte 1


//putStringP(PSTR("control information byte 1\r"));
switch(twiWrite(ctrlInfo)) {
case TW_MT_DATA_ACK:
// allet jut
//putStringP(PSTR("ok\r"));
break;
default:
// error
putStringP(PSTR("error\r"));
twiStop();
return;
}

// control information byte 2 aka ports byte


//putStringP(PSTR("control information byte 2\r"));
switch(twiWrite(ports)) {
case TW_MT_DATA_ACK:
// allet jut
//putStringP(PSTR("ok\r"));
break;
default:
// error
putStringP(PSTR("error\r"));
twiStop();
return;
}

twiStop();
}

uint8_t fm1216ReadStatus(void) {
uint8_t status = 0, repCnt = 0;

restart:
if(repCnt++ > 100) {
return 0;
}

// start senden
//putStringP(PSTR("start\r"));
switch(twiStart()) {
case TW_REP_START:
case TW_START:
// allet jut
//putStringP(PSTR("ok\r"));
break;
default:
// error (keine stop condition senden)
//putStringP(PSTR("error\r"));
return 0;
}

// adresse
//putStringP(PSTR("address\r"));
switch(twiWrite(FM1216_ADDR | TW_READ)) {
case TW_MR_SLA_ACK:
// allet jut
//putStringP(PSTR("ok\r"));
break;
case TW_MR_SLA_NACK:
// nack during select: device busy writing
goto restart;
default:
// error
//putStringP(PSTR("error\r"));
twiStop();
return 0;
}

// status byte lesen


TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA);
// wait for transmission
while ((TWCR & (1 << TWINT)) == 0) ;
switch(TW_STATUS) {
default:
break;
case TW_MR_DATA_ACK:
status = TWDR;
}

twiStop();
return status;
}

int main(void) {
char c, num[9];
uint16_t freqDiv = 2266, f;
uint8_t ctrlInfo, ports, status, cp=1;

// UART Init
UCSRB = (1 << TXEN) | (1 << RXEN);
UBRRL = (F_OSC / (16 * 115200L)) - 1;

// TWI Init
TWSR = 0;
TWBR = (F_OSC / 100000L - 16) / 2;
putStringP(PSTR("Radio\r\r"));

ports = AFC;

while(1) {
ctrlInfo = CTRL_INFO_BYTE | (1 << CTRL_INFO_T0);
if(cp) ctrlInfo |= 1 << CTRL_INFO_CP;

fm1216Tune(freqDiv, ctrlInfo, ports);


status = fm1216ReadStatus();

putStringP(PSTR("freqDiv="));
itoa(freqDiv, num, 10);
putString(num);

putStringP(PSTR(" status=0b"));
itoa(status, num, 2);
putString(num);
putChar('\r');

putStringP(PSTR("F="));
f = (freqDiv-214)/2;
itoa(f, num, 10);
if(f >= 1000) {
putChar(num[0]);
putChar(num[1]);
putChar(num[2]);
putChar('.');
putChar(num[3]);
} else {
putChar(num[0]);
putChar(num[1]);
putChar('.');
putChar(num[2]);
}
if(freqDiv % 2 == 0) {
putChar('0');
} else {
putChar('5');
}
putStringP(PSTR("MHz\r"));

c = getChar();
switch(c) {
case 'm':
ports = MUTE;
break;
case 'a':
ports = AFC;
break;
case 'r':
ports = R_IF;
break;
case '*':
freqDiv += 10;
break;
case '/':
freqDiv -= 10;
break;
case '+':
freqDiv++;
break;
case '-':
freqDiv--;
break;
case 'c':
if(cp) {
putStringP(PSTR("charge pump
off\r"));
cp = 0;
} else {
putStringP(PSTR("charge pump
on\r"));
cp = 1;
}
}
}

return 0;
}

Você também pode gostar