Arduino QN8027 Library with all posible settings and RDS support. tested and working ! /* Written By ManojBhakarPCM (india), 30 My 2021 during lockdown of second wave of corona. i am not associated with Quintic anyhow, but lover of RadioFrequency field. and i love all single chip transmitters. because i couldnt make any with transistor only :( */
/* Transmit Mono audio only and stop tranmitting streo channels. Transmitter first create MPX spectrum in which it mixes all kind of data then this MPX spectrum is Modulated in Carrier Frequency which is determined by setFrequency() function. then this modulated frequency is amplified by internal RF PowerAmplifier(PA) and then sent to antenna. the MPX spectrum of FM channel is-
| || ||
|---------------| || /----------\ /------------\ ||
| MONO | || / Left \ / Right \ /\ || /
||||/_/_________________/||/___
19KHz 38KHz 57KHz
Stereo Pilot Tone Saperation Pilot Tone RDS Data Channel
This spectrum contains all data, which are - mono(left+right) audio channel, left channel , right channel , RDS channel. all channels are saprated by pilot tones. which are 19KHz,19x2KHz,19x3KHz. actually there is only one pilot tone which is 19KHz, rest of that tones are second and third harmonics of this 19KHz pilot tone. harmonics are always weaker in amplitude than main tone. left and right side of 57KHz pilot tone are RDS data channel. in this chip you can set all these things-
Mono channel + LEFT + RIGHT ON/OFF - mute(); 19KHz pilot tone width(Bandwidth) with its harmonics - setTxPilotFreqDeviation(); LEFT + RIGHT channel ON/OFF - MonoAudio(); RDS channel ON/OFF - RDS(); RDS data Width(Bandwidth) - setRDSFreqDeviation(); Entire MPX channel BandWidth - setTxFreqDeviation();
Before mixing audio, audio is inputted to Input Buffer. where it can be amplified by which also depend on input impdence which is set by setAudioInpImp() here they are Emphasized(Amplified) to reduce noise(hiss sound) which will enter in transmission when wave will travel in Air. high frequency hiss noise is very bad. to remove that unwanted noise is to reduce high frequency amplification compared to low frequency.(de - emphasis) but then frequency response will not be flat. so we need to pre amplify the high frequency audio in transmitter so that after de-amplifying in receiver, it becomes flat. but what is cutoff for frequency for that you can determine which is "high" frequency and which is "low" freq. well that cutoff is called TC(time constant). 75uS(2.1221KHz) pre emphasis means above this frequency audio will be more amplified then lower to it. 75uS(2.1221KHz) EmphTimeConstant gives more treble while 50uS(3.1831KHz) gives bass boost.
if TimeConstant to Emphasize are opposite to each other in Transmitter and Receiver, Receiver will get either too much treble or too much bass.
so use setPreEmphTime50() function to match emphasisTimeConstant according to receiver side de-emphasis time constant.
then it is converted to digital audio by a ADC, where it can also be further amplified by setTxDigitalGain()
crystal is only needed for carrier frequency and pilot tone generation. I2C uses SCL wire instead.
many things can be used instead of crystal which can be selected by - setClockSource() when selected crystal, crystal frequency is selected by - setCrystalFreq() also, Max crystal current can also be adjusted by - setCrystalCurrent()
when using 12MHz crystal with setCrystalFreq(24), it will transmit at half frequency with much more power.(because power reduced with frequency) with this hack, you can transmit from 38MHz to 54MHz. this happens because carrier freq is generated by multiplying crystal freq. when you set carrier freq to 96MHz, chip thinks there is 24MHz crystal, so it multiply its freq by 4, but acutaly there is only 12MHz crystal, so multiplied freq will be only 12x4 = 48 Mhz !! :)
RDS data format: RDS data is sent in one or more groups. a group is made of 104 bits which structure is- | Block1 | Block2 | Block3 | Block4 |
| 16bit data | 10bitcheckword | 16bit data | 10bitcheckword | 16bit data | 10bitcheckword | 16bit data | 10bitcheckword |
you can input 8 bytes in this function. each two bytes represents 16bit data of each block (8x2=16). 10bitcheckword of each group is send automatically so no need to worry about it. that means that- By0 and By1 = 16 bit data of block1 By2 and By3 = 16 bit data of block2 By4 and By5 = 16 bit data of block3 By6 and By7 = 16 bit data of block4 ............... dont put your data in these bytes directly. it wont appear on receiver because data need to be encoded first in RDS format(which is very simple format though)
there is a space in receiver where you can put characters. that space indicated by GTYPE below. character position on that space is indexed. that means you have to send index position with characters so that receiver put that characters at given index to construct complete string to show at display. for example when sending characters on "radio text" space, we can send 4 characters at once. but there is total 64 characters can be placed on that space. so we send it in 16 groups. only one group can be send by using function sendRDS() function. so we need to call this function 16 times. for first 4 characters, we will use index 0000 (0), which means index position 1,2,3,4. for next 4 characters , we will use index 0001 (1), which indicates index position of character number 5,6,7,8 ...... each group is made of 4 blocks. first block(first two bytes) are always PI code. which you can set anything(if you dont know what is it). here i used 0x6400. second block is made of many things- for example for Song/Artist/Album name (which is called radioText GTYPE) format is as follows- in this example we want to send "ManojBhakar!" as radio text. GTYPE(4bit)|B0(1bit)|TP(1bit)|PTY(5bit)|screenClear(1bit)|Index(4bit) = total 16 bits = 2 bytes. GTYPE = 0010 (radio Text) B0 = 0 (Format A , there is also Format B which is complex) TP = 0 (This is not a traffic alert program) PTY = 10011(Program Type = Religious Music) SC = 0 (dont need to clear screen of receiver) index = 0000 (put character1 to index 1, character2 to 2, c3 to 3, 4 to 4 etc.) third block is also 16bit(2 byte) long. here we put our first two characters which we want to place at index 1 and 2 fourth block is also 16 bit long . here we will put our third and fourth character which will be placed at index 3 and 4 on receiver's display.
so entire 8 bytes for sending our first four characters will look like this - 0x64 0x00 0x22 0x60 M a n o
for next 4 characters group will look like this - 0x64 0x00 0x22 0x61 j B h a
and last 4 characters will be sent in this format- 0x64 0x00 0x22 0x62 k a r !
note that when sending station name block1 will be same block2 will be entirely diffrent from last 5 bytes. station name is called GTYPE A0 which means Group Type 0 in Format A. you can search internet for getting exact format of this group. what i can tell here is that this grouptype is only capable of sending 2 bytes at once and can send maximum 8 bytes.
value of onOffCtrl variable can be: ON or OFF.