stand-alone RDS Encoder (report)

stand-alone RDS Encoder (report)
UNIVERSITY COLLEGE LONDON
Department of Electronics and Electrical Engineering
RDS Encoder
Hamed Haddadi
Supervisor: Dr. Paul Brennan
Final Report
March 2003
Abstract
Radio Data Systems was development started 20 years ago in the European Broadcast Union,
EBU. The developers aimed to ease the process of tuning in to a station, especially as the
number of broadcasters was increasing and use of alternative frequencies to avoid interference
would make it difficult to keep tuned to a certain station. The use of RDS would overcome
this problem and will also enable the transmission of the Programme Service name (PS),
traffic information and other useful features which will make the FM receivers more userfriendly.
University College London has got its own radio station, RARE FM, which requires an RDS
encoder to enable them to transmit the name of the station. Commercial RDS encoders are
relatively expensive and complex and they need a dedicated PC and network connection to
enable the other features such as traffic information, which is not required by Rare FM. The
purpose of this project is to build an isolated RDS encoder which will not need a PC and is
simple enough to be used by a non-technical person in the station.
Some work has already been done last year to develop the encoder using analogue techniques.
However any changes to the station name will require modification of components and
switches and valid data has not been prepared for encoding and modulation alongside the FM
carrier. The technique pursued in this project is using a micro-controller to control the data
and bit-stream conversion and validations. This makes the system easier to operate and make
it easier to change the settings of the transmitted data-stream if needed in future.
This report contains the background research and knowledge taken from the RDS standard.
Objectives of the project and the approaches are also discussed within the appropriate section.
The work done and the achievements of the project are also explained, as well as the time and
budget planning and goals.
One of the major obstacles met in previous projects has been providing data and transmitting
the correct information at the right time. In this project the data processing part has been
investigated and planned first. This made sure that the new tasks are done before going
through the development and improvement of previous attempts to make an RDS Encoder.
Acknowledgements:
The author would like to acknowledge the work done By Timothy Shaw and Richard Koch as
their project in development of the RDS encoder and appreciate their valuable advice and
ideas given prior to start of the project. Many thanks are also forwarded to Dr. Paul Brennan
of the department for his help and supervision from the start of the research into the project
and Gerald McBrearty and Andrew Moss of the EE laboratory for their valuable advice and
support during the software development and hardware realisation of the project.
RDS Encoder Project
Hamed Haddadi
2
CONTENTS
Page
1. An introduction to RDS
5
2. Physical Layer of RDS system
6
2.1. Subcarrier frequency
2.2. Subcarrier phase
2.3. Subcarrier level
2.4. Method of modulation
2.5. Clock frequency and data rate
2.6. Differential coding
2.7. Data channel spectrum shaping
3. Base-band coding of the RDS system
3.1. Base-band coding structure
3.2. Order of bit transmission
3.3. Error protection
3.4. Message format
4. Project objectives and strategies
12
12
12
13
14
16
4.1. Providing frame data
4.2. Data input method for PS
4.3. Data display and user interface
4.4 Data processing and input/output control
4.5. CRC calculation
4.6 Bit-stream output
5. Software development tools
16
17
18
20
22
24
26
5.1. MPLAB Integrated Development Environment
5.2. Proteus Virtual Circuit Modelling
5.3. Orcad PSpice
5.4. Easy PC
6. RDS encoder block circuits
26
26
27
27
28
6.1. Radio data message source
6.2. Differential encoder
6.3. Bi-phase symbol generator
6.4. Shaping Filter
6.5. 57 KHz signal generator
6.6. Divide-by-24 counter
6.7. Divide-by-2 counter
6.8. Modulation
6.9 Power supply
7. Conclusions and future work
28
29
29
31
31
32
34
34
36
37
7.1 Objectives and achievements
7.2 Future work and improvements
8. Appendix
9. References
10. Component datasheets
RDS Encoder Project
6
6
8
8
8
8
9
37
37
38
63
64
Hamed Haddadi
3
List of Figure and Captions
Page
Figure 1: FM spectrum
Figure 2: Block diagram of RDS encoder at the transmitter
Figure 3: Block diagram of a typical RDS receiver
Figure 4: Amplitude response of specified transmitter/ receiver data-shaping filter
Figure 5: Amplitude response of combined transmitter/ receiver data-shaping filter
Figure 6: Spectrum of bi-phase coded radio-data signals
Figure 7: Time-function of a single bi-phase symbol
Figure 8: 57 kHz radio-data signals
Figure 9: Structure of the base-band coding
Figure 10: Message format and addressing
Figure 11: Basic tuning and switching information – Type 0B group
Figure 12: PI structure
Figure 13: Data input via push-button switches
Figure 14: Pin-out diagram of PIC16F877 micro-processor
Figure 15: Clocking the PIC
Figure 16: RDS encoder data input and user interface
Figure 17: CRC generator circuit
Figure 18: Modulo2 division
Figure 19: Modulo2 division using one register
Figure 20: MPLAB IDE software
Figure 21: Proteus VSM software interface
Figure 22: Data message source connected on breadboard
Figure 23: PCB design for the data message source block
Figure 24: Differential encoder
Figure 25: PIC16C622 for bi-phase symbol generation
Figure 26: Inverting amplifier for negative pulses
Figure 27: Shaping filter
Figure 28: Divide-by-3 waveform
Figure 29: PLL and divide-by-3 circuit
Figure 30: PLL waveform
Figure 31: Divide-by-24 counter
Figure 32: Divide-by-24 waveform
Figure 33: PLL and divide-by-24 circuits
Figure 34: Divide-by-2 counter
Figure 35: Divide-by-2 waveform
Figure 36: Square-to-sinusoidal wave converter
Figure 37: Square-to-sinusoidal waveform
Figure 38: Modulator
Figure 39: Modulator waveform
Figure 40: Modulator circuit
Figure 41: Positive voltage regulator
Figure 42: Voltage inverter
RDS Encoder Project
Hamed Haddadi
6
7
7
10
10
11
11
11
12
12
14
16
17
21
21
22
22
23
23
26
27
28
28
29
30
30
31
31
32
32
33
33
33
34
34
34
35
35
35
36
36
36
4
1.
An introduction to RDS
The use of more frequencies for the radio programmes in the VHF/FM range makes it
difficult for an in-car radio to remain tuned to the desired programme as the stations have to
constantly change frequencies in different regions to avoid interference. RDS employ an FM
subcarrier to transmit steady stream traffic information and the station name. This is a real
advantage over conventional radio systems as the sales of FM in-car radio systems were not
growing at the desired rate. The RDS system allows the station to transmit its Programme
Service Name (PS), an eight-character sequence identifying the station. This makes tuning to
a station by frequency redundant. Another important addition is the PI code. This code allows
receivers to automatically switch to the best available frequency for a particular station,
especially useful on long car journeys where frequencies for the same station change to avoid
interference patterns.
Following a long period of systems development in the 1970s and early 1980s, RDS is now
implemented all over Western Europe, and in several other regions of the world. This was
after the improvement of the in-car entertainment system developments. RDS had major
advantages for the traveller. RDS can provide traffic information and filter out the
unnecessary information when travelling in a specific route by recognizing the location codes.
Nowadays RDS is implemented in most FM radios and virtually all in-car radio systems.
Even though the university radio station does not intend to transmit any traffic or news
announcements, it still is an advantage if they can employ an RDS encoder to transmit the
station name. Commercial RDS encoders are expensive and require a dedicated PC to operate
them. The addition of a PC will make the system complicated for non-technical users and also
the station’s budget does not allow for such purchases. However it is possible to build an RDS
encoder by using simple components and a microprocessor.
Some work has already been done to develop and RDS encoder. The knowledge gained from
the previous students will be build upon of to make a functional unit within this project. The
programmes for the microprocessor, provisionally PIC16F877, will be written and compiled
using the MPLAB software and the circuit simulations will be done using the Proteus Virtual
System Modelling software.
This report contains a brief review of the RDS standard, which includes the physical layer
(hardware) and the data-link layer and message format (software) part of the encoder system.
After the review of the theory, the software format, which has been already implemented, has
been discussed. As there are various different comparisons made within the text between the
different strategies and their implementation advantages and disadvantages, the
implementation of the chosen strategy for each specific task is explained immediately after
the technical discussion part. A brief description of the intended hardware layout, the project
timescale and budget planning are also included in the discussions section.
RDS Encoder Project
Hamed Haddadi
5
2. Physical layer of RDS system
The RBDS standard, April 1998 was consulted to produce the following technical details of
and RDS signal. RBDS standard is the American version of RDS and it is exactly similar in
terms of operation and it was used as it is freely available on the web. The Radio Data System
is intended for application to VHF/FM sound broadcasts in the range 87.5 to 108.0 MHz
which may carry either stereophonic (pilot tone) or monophonic programs. The main
objectives of RDS are to enable improved functionality for FM receivers and to make them
more user friendly by using features such as Programme Identification (PI), Programme
Service (PS) display and where applicable, automatic tuning for portable and in particular, car
radios.
2.1
Subcarrier Frequency
During stereo broadcasts, the subcarrier will be locked to the third harmonic of the 19 kHz
pilot-tone. The tolerance on the frequency of the 19 kHz pilot tone is ±2Hz, therefore the
tolerance on the frequency of the subcarrier during stereo broadcast will be ± 6 Hz.
During monophonic broadcasts the frequency of the subcarrier will be 57 kHz ±6 Hz.
2.2
Subcarrier phase
During stereo broadcasts the subcarrier will be locked either in phase or in quadrature to the
third harmonic of the 19 kHz pilot tone. The tolerance on this phase must be within ±10°,
measured at the modulation input to the FM transmitter. Figure 1 shows the FM signal.
Figure 1: FM spectrum
Figures 2 and 3 represent the block diagrams of the transmitter and receiver.
RDS Encoder Project
Hamed Haddadi
6
Figure 2: Block diagram of RDS encoder at the transmitter
Figure 3: Block diagram of a typical RDS receiver
RDS Encoder Project
Hamed Haddadi
7
2.3
Subcarrier level
The deviation range of the FM carrier due to the un-modulated subcarrier is from ±1.0 kHz to
± 7.5 kHz. The recommended best compromise is ± 2.0 kHz. The decoder/demodulator
should also operate properly when the deviation of the subcarrier is varied within these limits
during periods not less than 10ms. The maximum permitted deviation due to the composite
multiplex signal is ± 75 kHz.
2.4
Method of modulation
The subcarrier is amplitude-modulated by the shaped and bi-phase coded signal. The
subcarrier is suppressed. This method of modulation may alternatively be thought of as a form
of two-phase phase shift keying (PSK) with a phase deviation of ± 90°.
2.5
Clock Frequency and Data Rate
The basic clock frequency is obtained by dividing the transmitted subcarrier frequency by 48.
The basic data rate of the system is therefore 1187.5 bit/s ± 0.125 bit/s.
2.6
Differential Coding
The source data at the transmitter are differentially encoded using table 1:
Previous output (at time ti-1)
New input (at ti)
New Output (at time ti)
0
0
0
0
1
1
1
0
1
1
1
0
Table 1: Differential encoding
Where ti is some arbitrary time and ti-1 is the time one message-data clock period earlier, and
where the message-data-clock rate is equal to 1187.5 Hz.
Thus when the input level is 0, the output remains unchanged from the previous output bit,
and when an input 1 occurs, the new output bit is the complement of the previous output bit.
In the receiver, the data may be decoded by the inverse process, as shown in table 2.
RDS Encoder Project
Hamed Haddadi
8
Previous input (at time ti-1)
New input (at ti)
New Output (at time ti)
0
0
0
0
1
1
1
0
1
1
1
0
Table 2: Differential decoding
The data is thus correctly decoded whether or not the demodulated data signal in inverted.
2.7 Data Channel Spectrum Shaping
The power of the data signal at and close to the 57 kHz subcarrier is minimised by coding
each source data bit as a bi-phase symbol.
This is done to avoid data-modulated cross talk in phase locked loop (PLL) stereo decoders,
and to achieve compatibility with the ARI system. The principle of the process of generation
was shown in Fig 2. In concept each source bit gives rise an odd impulse pair, e(t), such that
logic level 1 at source gives:
e(t) = δ(t) -δ (t-td/2)
And logic 0 at source gives:
e(t) = δ(t) +δ (t-td/2)
These pairs are then shaped by a filter HT(f), to give the required band limited spectrum
where:
td =
1
s
1187.5
The data-spectrum shaping filtering has been split equally between the transmitter and the
receiver (to give optimum performance in the presence of noise) so that, ideally, the data
filtering at the receiver should be identical to that of the transmitter, i.e. as given above. The
overall data-channel spectrum shaping Ho(f) would then be 100% cosine roll-off.
The specified transmitter and receiver low-pass filter responses, as defined in previous
equations, and the overall data-channel spectrum shaping is shown in figure 5.
The spectrum of the transmitted bi-phase coded radio-data signal is shown in figure 6 and the
time-function of a single bi-phase symbol (as transmitted) in figure 7.
RDS Encoder Project
Hamed Haddadi
9
The 57 kHz radio-data signal waveform at the output of the radio-data source equipment may
be seen in the photograph of figure 7.
Figure 4: Amplitude response of the specified transmitter or receiver data-shaping filter
Figure 5: Amplitude response of the combined transmitter and receiver data-shaping filters
RDS Encoder Project
Hamed Haddadi
10
Figure 6: Spectrum of bi-phase coded radio-data signals
Figure 7: Time-function of a single bi-phase symbol
Figure 8: 57 kHz radio-data signals
RDS Encoder Project
Hamed Haddadi
11
3.
Base-band coding of the RDS system
3.1 Base-band coding structure
Figure 9 shows the structure of the baseband coding. The largest element in the structure is
called a “group” of 104 bits each. Each group comprises 4 blocks of 26 bits each. Each block
comprises an information word and a checkword. Each information word comprises 16 bits.
Each checkword comprises 10 bits.
Figure 9: Structure of the baseband coding
3.2 Order of bit transmission
All information words and checkwords have their most significant bit (m.s.b) transmitted first
(see figure 10). Thus the last bit transmitted in a binary number or address has weight 20.
The data transmission is fully synchronous and there are no gaps between the groups or
blocks.
Figure 10: Message format and addressing
Information words and their use are explained in section 4, message format.
RDS Encoder Project
Hamed Haddadi
12
3.3 Error protection
Each transmitted 26-bit block contains a 10-bit checkword which is primarily intended to
enable the receiver/decoder to detect and correct errors which occur in transmission. This
checkword (i.e. c’9, c’8 … c’0 in figure 9) is the sum (modulo 2) of:
a)
the reminder after multiplication by x10 and then division (modulo 2) by the
generator polynomial g(x), of the 16-bit information word),
b)
a 10-bit binary string d(x), called the 2offset word2,
Where the generator polynomial, g(x) is given by:
g(x) = x10 + x8 + x7 + x5 + x4 + x3 + 1
The offset value, d(x), which is different for each block within a group is given in table 3.
Binary Value
Offset Word
D9
D8
D7
D6
D5
D4
D3
D2
D1
D0
0
0
1
1
1
1
1
1
0
0
B
0
1
1
0
0
1
1
0
0
0
C
0
1
0
1
1
0
1
0
0
0
C’
1
1
0
1
0
1
0
0
0
0
D
0
1
1
0
1
1
0
1
0
0
A
Table 3: The checkword offset values
The purpose of adding the offset word is to provide a group and block synchronisation system
in the receiver/decoder. Because the addition of the offset is reversible in the decoder, the
normal additive error correcting and detecting properties of the basic code are unaffected.
The error-protecting code has the following error-checking capabilities:
a)
b)
c)
Detects all single and double errors in a block.
Detects any single error burst spanning 10 bits or less.
Detects about 99.8% of bursts spanning 11 bits and about 99.9% of all longer bursts.
The code is also an optimal burst error correcting code 5 and is capable of correcting any
single burst of 5 bits or less.
The beginnings and ends of the data blocks ma be recognised in the receiver/decoder by using
the fact that the error-checking decoder will detect block synchronisation slip as well as the
additive errors. This system is made reliable by the addition of the offset words, which also
serve to identify the blocks within the group.
RDS Encoder Project
Hamed Haddadi
13
3.4 Message format (session and presentation layer)
The main features of the message structure have been illustrated in figure 10. These may be
seen to be:
1)
The first block in every group always contains a Program Identification (PI) code.
This information consists of a code enabling the receiver to distinguish between countries,
areas in which the same programme is transmitted and the identification of the program itself.
2)
The first four bits of the second block of every group are allocated to a four-bit code
which specifies the application of the group. Groups will b referred to as types 0 to 15
according to the binary weighting of A3, A2, A1, and A0. For each type (0 to 15) two
“versions” can be defined. The “version” is specified by the fifth bit (B0) of block 2:
a)
B0 = 0: the PI code is inserted in block 1 only. This is called version A.
b)
B0 = 1: the PI is inserted in blocks 1 and 3 of all group type. This is version B.
3) The Programme Type code (PTY) and Traffic Program identification (TP) occupy fixed
location in block 2 of every group. This is an identification number to be transmitted with
each program item and which is intended to specify the current program type (e.g. news,
sports…)
The above features are available in all of the 30 possible group types. The main objective of
this project is to transmit the station name. Groups 0A and 0B are the most basic groups that
without any need for other information, e.g. constant information feedback or traffic or text
update, will transmit the station name. Block 3 of Group 0A consists of a list of alternative
frequencies. This feature is for hand-over between different frequencies for stations which
transmit over a wide geographical area and is not being used by the UCL radio station. Block
3 of group 0B simply repeats the PI code, with a different offset word, C’. Hence for the
purpose of this project, group 0B is chosen for transmitting the station name. Figure 11 shows
the format of the group type 0B.
Figure 11: Basic tuning and switching information – Type 0B group
A total of four type 0B groups are required to transmit the entire Program Service (PS) name
and therefore four type 0B groups will be required per second. The Program Service name
comprises eight characters. It is the primary aid to listeners in program identification and
selection. The PS name is to be used only to identify the station. This text may be changed as
required by station, but shall not be scrolled or flashed or altered in a manner that would be
distracting to the viewer (i.e. not more frequently than once per minute).
Notes on group 0B:
1.
TA = Traffic Announcement code (1 bit)
RDS Encoder Project
Hamed Haddadi
14
2.
M/S = Music-Speech switch code
3.
DI = Decoder-Identification control code (4 bits). This code is transmitted as
1 bit in each 0B group. The Program Service name and DI segment address code (C1 and C0)
serve to locate these bits in the codeword. Thus in a group with C1C0 = “00” the DI bit is d3.
These code bits are transmitted most significant bit (d3) first. Table 4 demonstrates the DI bitsettings.
Settings
Bit d0 set to 0:
Bit d0 set to 1:
Bit d1 set to 0:
Bit d1 set to 1:
Bit d2 set to 0:
Bit d2 set to 1:
Bit d3 set to 0:
Bit d3 set to 1:
Table 4: DI code bits
Meaning
Mono
Stereo
Not Artificial Head
Artificial Head
Not compressed
Compressed
Static PTY
Dynamically switched PTY
4.
Program Service name is transmitted as 8-bit character as defined in the 8-bit
code-tables in annex E of RBDS standard [1]. Eight characters (including spaces) are allowed
for each network and are transmitted as a 2-characteer segment in each group. These
segments are located in the displayed name by the code bits C1 and C0 in block 2. The
addresses of the characters increase from left to right in the display. The most significant bit
(b7) of each character is transmitted first.
RDS Encoder Project
Hamed Haddadi
15
4. Project objectives and strategies
As clearly suggested by the title, the main objective of this project is to build an RDS encoder
to enable the UCL radio station, RARE FM, to transmit the station name on the FM spectrum.
This task has been attempted in the Electronic & Electrical Engineering department. The main
reason of failure of previous attempts has been the absence of valid data for transmission. The
hardware design has been studied and areas for improvement have been identified. The focus
of the first stage of the project has mainly been on development of the message format and
session-presentation layer. The following objectives are set for the project:
•
To build a complete (hardware & software) RDS Encoder to facilitate Program
Service transmission for RARE FM.
•
To provide valid data according to the European RDS standard for encoding.
•
To design and implement a user-friendly interface to enable non-technical personnel
to easily enter the desired PS name.
•
To offer the facility to restore the settings hence avoid the need to enter the same data
in case of power failure.
•
To complete the unit within the allocated time and budget, 6 months and £100.
The choice of group 0B for the purpose of the encoding has been based on the fact that it will
allow the transmission of PS with no need for any other information such as traffic or
announcement. This means that the unit functions as a stand-alone without any need for
further attention to provide data or network connection. Transmission of PS as the main
objective of the project will enable easy tuning for the in-car radio units.
4.1 Providing frame data
There are various constants and variables within a group. It would be possible to enable the
user to enter all the required data at the start-up part of the system. But this will only make the
unit extremely hard to operate as all the values have to be set according to the RDS standard
and any mistake will mean that the bit-stream is not verified and displayed at the receiver end.
In order to avoid this, the constant parts of the group data are set within the program memory,
according to RDS standard as explained below, and user is only required to enter the PS
name.
1.
PI code: Figure 12 shows the PI structure.
Figure 12: PI structure
These bits are all pre-set in according to RDS standard as followed:
Bits b15 to b12: Country Code: These bits are set to 0xC or 0b1100 for UK.
Bits b11 to b8: Area coverage: These bits are set to 0x0 or 0b0000 for local coverage.
Bits b7 to b0: Program reference number: These bits are set to 0x00 for not assigned.
2.
Group Type: These bits are set to 0x0 for 0 group type.
3.
B0: This bit is set to 1 for group B type.
4.
TP: This is set to 0 for no traffic program.
5.
PTY: These bits are set to obooooo for not assigned.
6.
TA: This is set to 0 for no traffic announcement.
7.
M/S: This bit is set to 0 according to RDS standard by default for music.
8.
DI, C1, C0: These bits are set in each group according to the group sequence in the
stream as followed:
RDS Encoder Project
Hamed Haddadi
16
A)
B)
C)
D)
First group: 0b0 (d3)00 for static PTY.
Second group: 0b0 (d2)00 for not compressed.
Third group: 0b0 (d2)00 for no artificial head.
Second group: 0b1 (d2)00 for stereo.
9.
Program Service name: Every group will transmit 2 characters, starting from the most
significant character, e.g. [RA] in (RARE__FM) is located in first group.
4.2 Data input method for PS
Data can either be input via setting 64 switches for the 8 character ASCII code of the PS name
or it can be input to the microcontroller via push button switches or a PS2 keyboard. The
analogue method has been attempted before and is extremely difficult to operate. The more
feasible design is to input the values to the microcontroller via a digital device:
A: PS2 keyboard. This method is extremely friendly but it introduces the complexity of
writing a keyboard driver and also occupying much more space while adding the risk of
breakages and damage in the busy studio environment.
B: Push button switches: Using three heavy duty push button switches, the user can decide
whether to restore the previous settings or not, scrolling between YES and NO, and then
pressing the SET switch. If he chooses not to restore the previous settings, he will scroll
through the available set of ASCII characters, from SPACE through Z. By pressing the set
button, the first character is set and stored in the EEPROM. The same routine is repeated for
the other 7 characters and by pressing the SET button for the final character, the program will
proceeds to CRC calculation. The disadvantages of this method are the cost of these switches
and the fact that using this method, it will take a bit longer to input the data. But the cost can
be compromised by the fact that the switches are not prone to damages in the studio
environment. Figure 13 shows the design of this interface.
Figure 13: Data input via push-button switches
The following algorithm is implemented for polling for the switches for restoring data:
CHECK_SWITCH
GET_IT btfsc
call
btfsc
call
got
btfss
goto
movf
andlw
btfsc
goto
return
; Polls switches for decision to restore setting
SWITCH_PORT,0
D0_SET
SWITCH_PORT,1
D1_SET
SWITCH_PORT,2
GET_IT
DECISION,W
0xff
STATUS,Z
GET_IT
; restore
: Don't restore
; Check if D2 is not pressed
; without making a decision
; if yes, loop until decision is made
The following code demonstrates the acquisition of one PS character and storing it in the PIC
EEPROM:
GET_PS8 btfsc
call
btfsc
call
btfss
SWITCH_PORT,0
CHAR_UP
SWITCH_PORT,1
CHAR_DOWN
SWITCH_PORT,2
RDS Encoder Project
Hamed Haddadi
17
goto
GET_PS8
return
CHAR_UP
call
movf
call
movf
call
movf
call
return
check_max
movwf
movf
subwf
btfsc
goto
goto
SWITCH_DELAY
POSITION,0
SET_ADDR
CHARACTER,0
check_max
CHARACTER,0
LCD_CHAR
; move character to W register
; check if reached the upper boundary
CHAR_TEMP
MAX_CHAR,0
CHAR_TEMP,0
STATUS,Z
SET2MAX
INCREMENT
;
;
;
;
;
;
;
; set display position
it checks mor the upper character
store the character locally
now move MAX_CHAR to W register
subtract the two files
Is the result zero?? then we reached maximum
keep the character as it is
if not reached the max, increment the character
SET2MAX
movf
MAX_CHAR,0
return
INCREMENT
incf
CHARACTER,1
return
; Keep MAX_CHAR as the character of chioce
; increment the character
CHAR_DOWN
call
movf
call
movf
call
movf
call
return
SWITCH_DELAY
POSITION,0
SET_ADDR
CHARACTER,0
check_min
CHARACTER,0
LCD_CHAR
; move character to W register
; check if reached the lower boundary
check_min
movwf
movf
subwf
btfsc
goto
goto
CHAR_TEMP
MIN_CHAR,0
CHAR_TEMP,0
STATUS,Z
SET2MIN
DECREMENT
;
;
;
;
;
;
;
; set display position
it checks mor the lower character
store the character locally
now move MIN_CHAR to W register
subtract the two files
Is the result zero?? then we reached minimum
keep the character as it is
if not reached the min, decrement the character
SET2MIN
movf
MIN_CHAR,0
return
DECREMENT
decf
CHARACTER,1
return
; Keep MIN_CHAR as the character of chioce
; decrement the character
EEPROM storage:
movwf
bsf
bsf
btfsc
call
bcf
movwf
movlw
movwf
bsf
bcf
bsf
movlw
movwf
movlw
movwf
bsf
bcf
clrf
PS_8
STATUS,RP1
STATUS,RP0
EECON1,WR
DELAY_5MS
STATUS,RP0
EEDATA
0x07
EEADR
STATUS,RP0
EECON1,EEPGD
EECON1,WREN
0x55
EECON2
0xaa
EECON2
EECON1,WR
EECON1,WREN
STATUS
; store in variable
; Store in EEPROM
; Make sure there is no other WRITE in progress
; Select bank 0
4.3 Data display and user interface
As there is a need for characters to be displayed for verification and during transmitting stage,
there is need for a display. Two type of display are available:
A: Alphanumeric LED display
RDS Encoder Project
Hamed Haddadi
18
This display is cheap and easy to operate as each character is driven separately and there is no
processing required, but in order to use this facility, there is a need for driving each character
separately, this will mean either using many ICs, which will increase the complexity of the
PCB and will introduce heat dissipation problems, or multiplexing the data line through one
IC, which maybe very complicated for driving a large number of characters.
B: Using an intelligent LCD display
The new ranges of displays have eliminated the need for driving each character separately by
using an internal chip and timing issues are dealt within the chip. But they are relatively
expensive and a typical entry level can cost around £30. There is also need for writing an
initialisation code for the display and one of the ports need to be constantly swapped between
input and output to check the busy flag of the LCD to make sure there in no data loss. The
initialisation code is as followed:
For the purpose of this project, a very cheap LCD module was obtained which would cost
60% less than the commercial ones available. But the initialisation was implemented in a
different way than the standard data sheet and the code is shown below:
; INIT_LCD...... Module to initialise the display
;**********************************************************************
INIT_LCD
call
DELAY_30MS
movlw
call
call
0x38
LCD_CMND
DELAY_5MS
RDS Encoder Project
; 8-bit-interface, 2-lines... 0b00111000
Hamed Haddadi
19
movlw
call
call
0x38
LCD_CMND
DELAY_125US
; 8-bit-interface, 2-lines... 0b00111000
movlw
call
call
0x38
LCD_CMND
DELAY_125US
; 8-bit-interface, 2-lines... 0b00111000
movlw
call
call
0x0F
LCD_CMND
DELAY_5MS
; display On, curser On, blink On 0b00001111
movlw
0x01
call
LCD_CMND
return
; display clear, 0b00000001
The delays have been implemented using a series of recursive loops. All the function calls and
descriptions can be found in appendix A.
4.4 Data processing and input/output control
Providing the data at the right time for modulation with the FM signal has been the major
obstacle of this project in previous attempts. Analogue and digital methods have both been
tried and with great advantage, a digital source provides a much more versatile way of
controlling and manipulating the data. Since the use of intelligent LCD and de-bounce
switches will also emphasis the need for a microprocessor, this method was chosen for data
control. The following is the control software data flow required for the encoder:
Top Level Software Flow Diagram
Switch on
Display Opening
message
Do you want to use
previous settings?
Yes
Input New Data
Perform CRC
Output Data
After studying the wide range of microcontrollers that are commercially available,
Microchip’s PIC16F877 was chosen for the data control. This is an 8 bit microprocessor with
8k program memory and 256 byte EEPROM data memory which both memory limits were
enough for the application. The development environment, MPLAB IDE, is freely available
on the web and from Microchip’s website [2] and the programmer, PICstart PLUS, is
available in the departmental laboratory. Figure 14 shows the pin-out diagram of PIC16F877.
RDS Encoder Project
Hamed Haddadi
20
Figure 14: Pin-out diagram of PIC16F877 micro-processor
It operates with clock rates of up to 20MHz giving an instruction arte of up to 5 MIPS, so the
clock frequency is equal to 0.2µs. A crystal oscillator was chosen to ensure that correct
timings and clock rate are achieved. Figure 15 shows the connection of the crystal to the
microprocessor.
Figure 15: Clocking the PIC
The suggested values for the stabiliser capacitors were between 15-33 pF.
Another problem encountered was the fact that switches bounce back after being pressed
down and released which would lead to many jumps in the character range with just one
switch. This problem was solved by adding a short 0.2 second de-bounce delay after the
switch port reading, which would clear the port from the previous switch voltage. The
switches were also tied with 4k7 Ohm resistors to limit the current drawn from the power
supply when the switches are being pressed often. Figure 16 demonstrates the data control
and user-interface of the RDS encoder.
RDS Encoder Project
Hamed Haddadi
21
BAT1
5V
LCD1
D0
D1
D2
D3
D4
D5
D6
D7
7
8
9
10
11
12
13
14
RS
RW
E
4
5
6
1
2
3
VSS
VDD
VEE
LM016L
U1
X1
CRYSTAL
13
14
1
2
3
4
5
6
7
8
9
10
OSC1/CLKIN
OSC2/CLKOUT
MCLR/Vpp/THV
RB0/INT
RB1
RB2
RB3/PGM
RB4
RB5
RB6/PGC
RB7/PGD
RA0/AN0
RA1/AN1
RA2/AN2/VREFRA3/AN3/VREF+
RA4/T0CKI
RA5/AN4/SS RC0/T1OSO/T1CKI
RC1/T1OSI/CCP2
RE0/AN5/RD
RC2/CCP1
RE1/AN6/WR
RC3/SCK/SCL
RE2/AN7/CS
RC4/SDI/SDA
RC5/SDO
RC6/TX/CK
RC7/RX/DT
RD0/PSP0
RD1/PSP1
RD2/PSP2
RD3/PSP3
RD4/PSP4
RD5/PSP5
RD6/PSP6
RD7/PSP7
PIC16F877
33
34
35
36
37
38
39
40
15
16
17
18
23
24
25
26
19
20
21
22
27
28
29
30
R3
R2
R1
4k7
4k7
4k7
Figure 16: RDS encoder data input and user interface
4.5 CRC calculation
Every block in the group contains a 16 bit information word and a 10 bit checkword which is
obtained by adding the result of the calculation of the Cyclic Redundancy Check to a specific
offset, as explained in section 3.3. Calculation of the CRC can be done in the hardware as
explained in the RDS standard. Figure 17 shows the hardware arrangement required to
generate the 10 bit CRC value.
Figure 17: CRC generator circuit
This method can lead to a very high component count and greatly add to the complexity of the
circuits. It has the advantage of being easily implemented as the method is pre-designed.
It is also possible to calculate the CRC value in the microprocessor. This will lead to a much
less complex circuit and budget saving on component purchase. The only disadvantage of this
method is the need to divide a 26 bit number by a 10 bit number, in an 8 bit microprocessor.
This method was chosen to pursue whilst accepting the challenge of mathematical
manipulations. Figure 18 shows the basic method of performing a modulo2 division.
RDS Encoder Project
Hamed Haddadi
22
Figure 18: Modulo2 division
However, in a microprocessor, there are only 8-bit registers available, and there is no
command for modulo2 division. However, using pseudo algorithm this process can be
explained:
1. Load the register with zero bits.
2. Augment the message by appending W zero bits to the end of it.
While (more message bits)
Begin
3. Shift the register left by one bit, reading the next bit of the augmented
message into register bit position 0.
If (a 1 bit popped out of the register during step 3)
Register = Register XOR Poly.
End
The register now contains the remainder.
In practice the IF condition can be tested by testing the top bit of Register before performing
the shift. Figure 19 demonstrates the implementation of the above technique. This method can
be extended for larger numbers. In the case of the RDS block, 26 bits means that four 8-bit
registers are used for the message data and the 10-bit polynomial will require two 8-bit
registers. A buffer register and two working registers will be used, and data is left-rotated into
the working registers, bit by bit, and whenever a 1 appears on the carry flag, both working
registers or XORed with the generator polynomial registers. This process is repeated until all
the 16 extra bits (in comparison with the 10-bit polynomial) are shifted out. The reminder in
the working registers is the CRC value for the given 16-bit information word.
Figure 19: Modulo2 division using one register
RDS Encoder Project
Hamed Haddadi
23
The following is an extract from the assembly code generating the CRC:
CRC_INIT
clrf
bcf
rlf
rlf
rlf
bcf
rlf
rlf
rlf
CHAR_BUF
STATUS,C
CHAR_LOW,1
CHAR_HIGH,1
CHAR_BUF,1
STATUS,C
CHAR_LOW,1
CHAR_HIGH,1
CHAR_BUF,1
;
;
;
;
;
;
;
Initialise the registers
rotate left twice, through carry,
so that the 10^X factor can correctly
be implemented, i.e. by adding an 8bit
all 0s register to the end of the data,
and shifting to left twice to have another
2 obits.
movlw
movwf
movf
movwf
movf
movwf
movf
movwf
movlw
movwf
0x10
ITERATIONS
CHAR_BUF,0
CRC_HIGH
CHAR_HIGH,0
CRC_LOW
CHAR_LOW,0
CRC_BUF1
0x00
CRC_BUF2
; 16 left shifts, for the CRC calculation
movlw
movwf
movlw
movwf
0x05
GXPOLY_HIGH
0xb9
GXPOLY_LOW
; Storing the g(x) polynomial in registers
; shifting all to the right place
; adding the last 8 zero's
return
CRC_GEN
bcf
rlf
rlf
rlf
rlf
btfsc
call
decfsz
goto
return
STATUS,C
CRC_BUF2,1
CRC_BUF1,1
CRC_LOW,1
CRC_HIGH,1
CRC_HIGH,2
DO_XOR
ITERATIONS,1
CRC_GEN
movf
xorwf
movf
xorwf
return
GXPOLY_LOW,0
CRC_LOW,1
GXPOLY_HIGH,0
CRC_HIGH,1
DO_XOR
;
;
;
;
;
CRC generator routine
clear the carry bit
left shift all the data by one bit,
using carry flag, so the carry 1 or 0
will go to the LSB of next byte
;
;
;
;
is the last bit a 1?
if yes, XOR the working registers with g(x)
Decrement iterations, more bits left?
if yes, do another bit
; Modulo 2 division with the g(x)
4.6 Bit stream output
Data transmission tasks start after the CRC calculation steps. User is informed of the
PS name currently being transmitted via the LCD display and the microprocessor constantly
polls for the 1187.5 signal. As soon as this signal goes high, the m.s.b of first block of the first
group is output to the output port. The block data is then rotated left and the carry will
represent the next bit to be transmitted. This process is repeated 16 times for block
information words and 8 times for each check-word value. For the top 2 bits of the checkword values, the data nibbles are swapped and then rotated left twice. In this way there is only
need for two transmission cycles and many fewer instruction cycles. This is done in only 5
steps so it will have a frequency much higher than the 1187.5Hz signal. The next bit will be
ready for transmission before the 1187.5 goes high again. After the first group, the second,
third and fourth group are transmitted in turn and then the program loops back to the first
group. The following code is a very small part of the transmission assembly code:
movlw
movwf
movf
movwf
swapf
rlf
rlf
call
0x02
; Send
ITERATIONS
CHCKWRD_3_HIGH,0
TRX_BUF
TRX_BUF,1
TRX_BUF,1
TRX_BUF,1
TRANSMIT_BUF_DATA
movlw
0x08
RDS Encoder Project
the top two bits of PS checkword
; Move the whole byte
; Swap nibbles
; Rotate left twice, to bring the first bit
; of the two bits to the MSB location
; Send lower byte of PS checkword
Hamed Haddadi
24
movwf
movf
movwf
call
ITERATIONS
CHCKWRD_3_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
return
TRANSMIT_BUF_DATA
rlf
TRX_BUF,1
btfss
STATUS, C
call
TRANSMIT_0
btfsc
STATUS, C
call
TRANSMIT_1
decfsz ITERATIONS,1
goto
TRANSMIT_BUF_DATA
return
;
;
;
;
Transmit the data byte held in the buffer
Rotate left once, in itself
Test the carry flag value
is carry 0? transmit a 0
; Is carry 1? transmit a 1
; Decrement iteration until it reaches 0
TRANSMIT_0
btfss
RDS_PORT,SIGNAL
goto
TRANSMIT_0
bcf
RDS_PORT, RDS_DATA
return
; Is 1187.5 high?
; No? then loop until it goes high
; Clear the port bit, 0 will be modulated
TRANSMIT_1
btfss
RDS_PORT,SIGNAL
goto
TRANSMIT_1
bsf
RDS_PORT, RDS_DATA
return
; Is 1187.5 high?
; No? then loop until it goes high
; Set the port bit, 1 will be modulated
Even though use of intelligent LCD and microprocessor has the disadvantage of taking a
considerable amount of time to develop skills in a new programming language and its
abilities, the time saved on designing complex circuits for the analogue techniques and the
extremely user-friendly interface means that the encoder would be compensate for the
software development time. The unit is much easier to operate and even upgrade in the future
if any other facilities such as radio text are considered to be added to the system.
RDS Encoder Project
Hamed Haddadi
25
5.
Software development tools
The software side of the project is done using various simulation tools for the hardware parts
of the encoder block and assembly programming language is used for the microcontroller part
of the radio message source. This section entails a brief description of the software tools used
for software and hardware development.
5.1. MPLAB IDE
The assembly codes for the PIC microcontrollers used within the project are developed using
MPLAB Integrated Development Environment. Figure 20 shows a screen dump of the
MPLAB IDE software.
Figure 20: MPLAB IDE software
This software facilitates assembly code debugging, and it enables communication with the
programmer PICstart PLUS, which loads the program .HEX file into the PIC. The software
has been tested on the hardware circuit and it performs all the required action. The EEPROM
data is also restored after power-up if requested by the user
The main objectives of the project in this part are achieved. An easy to operate user-interface
is implemented and PS name is obtained from the user and the cyclic redundancy checks are
performed. The user is also informed of the transmitted PS via the LCD interface and he will
have the opportunity to restore the PS name in case the unit is turned off and then on for any
reason.
5.2. Orcad PSpice
PSpice is the design software by Cadence Ltd allowing simulation and synthesis of circuit
diagrams. All the circuit diagrams in this report have been designed using Orcad Design.
RDS Encoder Project
Hamed Haddadi
26
5.3. Proteus Virtual Circuit Modelling
Proteus VSM is a mixed signal simulation environment allowing an extensive range of
microcontrollers and devices to be used within functional blocks. It also enables the use of
oscilloscope and signal generators so simulation of various signals within an embedded
system environment is possible using this software. Because of high license costs, an
evaluation model was used with a low code limit and component count however it helped
design of the PIC and LCD units. Figure 21 shows the interface of Protues VSM.
Figure 21: Proteus VSM software interface
5.4. Easy PC
Easy PC is the “Printed Circuit Board” design software provided by Number One Systems
Ltd. It enables design of various PCBs and it has a simple user interface allowing control over
drill holes and component spacing. This software was used to design the PCB for the radio
message source block.
RDS Encoder Project
Hamed Haddadi
27
6. RDS encoder block circuits
Circuit blocks are all made according to RBDS standard [1] and using the block diagram of
figure 2 on page 7. The circuit diagrams and where relevant the input and output are shown.
6.1. Radio Data Message source
The radio data message source as explained in section 4.4 is designed using PIC16F877
microcontroller and heavy duty push button switches. Pull-up resistors of 4k7 Ohms are used
to limit the current on the PIC ports when switches are pushed down or when the 1187.5
signal goes high. An extra emergency battery holder, containing 3 AA batteries will be added
to make sure that the module doesn’t stop transmitting if disconnected for a short period of
time. Figure 22 shows a picture of the data message source on breadboard and figure 23
shows the PCB design for this part of the encoder.
Figure 22: Data message source connected on breadboard
Figure 23: PCB design for the data message source block
RDS Encoder Project
Hamed Haddadi
28
6.2. Differential encoder
Data from the PIC port is passed to a differential encoder. This block is explained in the
section 2.6, extracted from the RBDS [1] standard. The flip-flop used is a Philips 74HC74 Dtype positive edge-triggered flip-flop. Exclusive-OR function was implemented using a
Fairchild DM74LS86 2-input gate. Figure 24 shows the PSpice diagram of the differential
encoder.
U4A
2
3
1
74LS86
14
1
1187.5
J1
Q1
12
To bi-phase Encoder
CLK1
K1
Q1
13
2
3
U1A
74LS73
CL1
From PIC Microcontroller
Figure 24: Differential encoder
6.3. Bi-phase symbol generator
The bi-phase symbol generator converts each bit to an odd pair of short pulses which are
spaced one bit length. A "1" is converted to a +- pair, a "0" is converted to a -+ pair. The
pulses are then passed through a 2nd Order Sallen-Key low-pass filter with a cosine-shaped
transfer function. The combination of this filter and the inherent spectrum-shaping of the biphase scheme lead to a spectrum with a maximum near 1 kHz and zero amplitude at 0 and 2.4
kHz. Section 2.7 explains the theory behind bi-phase encoding. As delay and subtraction of
short pulses is not possible in the flip-flops, another PIC microcontroller was used for
generation and subtraction of data pulses, namely PIC16C622. The system is clocked with the
2375Hz clock generated from the divide-by-24 counter. The PIC starts of by polling for the
1187.5 clock. When this clock goes high, it also polls for the data line and output is decided
based on table 5. In this case the previous input is zero as the input is only valid when the
1187.5 clock is high. The PIC generates the output pulse of short duration, about 51µs, by
taking an output port high, then pulling it low after the delay. When a negative pulse is to be
generated, one of the PIC ports goes high, but the output is connected to a fast inverting
amplifier circuit, using MC33171 Op-amp with slew rate of 2V/µ. The next time that the 2375
signal goes high, the 1187.5 is low so the input data is considered to be zero. The output is
then decided to be the opposite of the previous output, according to table 6.
Input N
Previous Input
(N-1)
N-(N-1)
output
+VE
-VE
0
0
+VE
-VE
Table 5: Output at 1187.5 data signal levels
Input N
Previous Input
(N-1)
N-(N-1)
output
0
0
+VE
-VE
-VE
+VE
Table 6: Output at 2375 zero pulse level
The following is an extract from the assembly code written for bi-phase symbol generation
from the PIC.
RDS Encoder Project
Hamed Haddadi
29
poll11875
btfss
PORTB,CLK11875
goto
poll11875
return
signal_pulse
btfss
goto
goto
PORTB, RDS
PULSE_DOWN
PULSE_HIGH
poll2375
btfss
PORTB, CLK2375
goto
poll2375
return
clear_pulse
btfsc
goto
goto
MEMORY,0
PULSE_DOWN
PULSE_HIGH
PULSE_HIGH
bsf
PORTB, PULSEHIGH
call
DELAY_51US
bcf
PORTB, PULSEHIGH
bsf
MEMORY,0
return
PULSE_DOWN
bsf
PORTB, PULSEDOWN
call
DELAY_51US
bcf
PORTB, PULSEDOWN
bcf
MEMORY,0
return
Figure 25 shows the PSpice diagram of the PIC configuration for bi-phase symbol generation.
U1
22pF
17
18
1
2
3
CRY STAL
10MHz
22pF
16
15
4
5V
14
1187.5 clock
RB0/INT
RA0/AN0
RB1
RA1/AN1
RB2
RA2/AN2/REF
RB3
RA3/AN3
RB4
RA4/T0CLK
RB5
RB6
OSC1/CLK
RB7
OSC2/CLKOUT
6
7
8
9
10
11
12
13
2375 clock
RDS data
High Pulse
LOW pulse (to -v e opamp)
MCLR/VPP
VDD
PIC16C622
Figure 25: PIC16C622 for bi-phase symbol generation
Figure 26 shows the PSpice diagram of the inverting amplifier for negative pulse generation.
- 12V
4
5
1K
6
To shaping f ilter
7
1
3
MC33171
+
1k
-
2
Pulse f rom PIC
+12V
Figure 26: Inverting amplifier for negative pulses
RDS Encoder Project
Hamed Haddadi
30
6.4. Shaping filter
Data from the bi-phase symbol generator must go through a shaping filter as explained in
section 2.7. This is a raised cosine filter with 100% roll-off and cut-off frequency of
1187.5Hz. A 2nd order Sallen-Key was devised for this purpose. The component values are
calculated to give a cut-off at 1187.5Hz frequency, thus giving
C1 =
2
and C 2 =
Rω 0
1
,
2 Rω 0
where ω0 is the cut-off frequency in radians. Using 10nf capacitors, R1 will be 18K9 Ohms
and R2 will be 9k5 Ohms. Figure 27 shows a PSpice diagram of the shaping filter.
+12V
4
5
C1
741
2
-
R1
3
to modulator
C2
7
1
R2
+
Bi-Phase pulses
6
-VE 12V
Figure 27: Shaping filter
6.5. 57 kHz signal generator
The RDS data has to be modulated with the FM signal and hence it needs to be clocked. The
RDS carrier is at 57 kHz while the only signal available from the station stereo coder is the 19
kHz pilot tone. In order to generate a 57 kHz carrier in phase with the 19 kHz pilot tone, it is
possible to use a filter to find the 3rd harmonic. This would need many active components and
would require considerable phase compensation. As the 19 kHz pilot tone is a square wave, it
can be fed into a Schmidt trigger circuit, then using a phase-locked-loop to generate a 57 kHz
signal from the 3rd harmonic. A dedicated PLL chip, HC4046B by ST, is used and the voltage
controlled oscillator’s output is then fed into a divide-by-3 circuit.
Divide-by-3 part of the PLL is implemented using a pre-settable counter, HCC4018B, and 2
NAND-gates, on HCF4011B. Figure 28 shows the oscilloscope display of this division. It is
not possible to get a 50% duty cycle from the circuit because of the configuration of the gates,
but as PLL is edge-triggered, this causes no problems for the system.
Figure 28: Divide-by-3 waveform
RDS Encoder Project
Hamed Haddadi
31
Using a few variable resistors at the VCO input and the R1 input on pin 11 it is possible to get
a 57 kHz signal with less than 0.05% variation at times, which is due to variations in the 19
kHz signal input. Figure 29 shows a PSpice diagram of the complete PLL and divide-by-3
circuit.
VCC
7
7
74LS00
2
3
1
SIN
CX
14
1
14
3
6
R1
10K
CAP 1nF
9
CAP 100nF
10
15
VCOIN
CX
INH
R1
R2
DEMO
ZEN
DM7476
J1
Q1
12
5
CLK1
K1
7
Q1
13
10
DM7476
J2
Q2
9
CLK2
K2
CL2
P2
3
4
Q2
8
6
13
CIN
VCOUT
CL1
47k
PP
P1
14
1
2
1
2
74LS00
2
3
14
Sq-Sine Conv erter 57 kHz
7
5
11
12
2
4046
1
3
2
10k
Phase Adjust
1
3
10k
Phase Adjust
U5A
1
19kHz Sinusoidal Wav e input
2
74HC14
Figure 29: PLL and divide-by-3 circuit
Figure 30 shows the oscilloscope waveform of the 19 kHz input and the 57 kHz output of the
PLL circuit.
Figure 30: PLL waveform
6.6. Divide-by-24 counter
In order to generate the 2375 Hz signal for the bi-phase signal generator, the 57 kHz signal
must be divided by 24. This is done in two stages using HCF4018B divide-by-N counters,
dividing by 6 at the first stage, and dividing the output by 4 at the second stage. This signal is
then used to clock the PIC for the bi-phase symbol generator. Divide-by-24 stage does not
require any extra gates or components as the dividers allow straight division for even
numbers. Figure 31 shows the PSpice diagram of the divide-by-24 circuit.
RDS Encoder Project
Hamed Haddadi
32
Div ide by 6
2
3
7
9
12
14
57KHz Clock
+5V
1
10
15
I1
I2
I3
I4
I5
Div ide by 4
Q1
Q2
Q3
Q4
Q5
5
4
6
11
13
2
3
7
9
12
14
CLK
+5V
D
PRE
RST
4018
1
10
15
I1
I2
I3
I4
I5
Q1
Q2
Q3
Q4
Q5
5
4
6
11
13
2375 clock
CLK
D
PRE
RST
4018
Figure 31: Divide-by-24 counter
Figure 32 shows the oscilloscope waveform of the divide-by-24 circuit. There is no phase
shift introduces as result of this division.
Figure 32: Divide-by-24 waveform
Figure 33 shows the circuit configuration for the PLL and divide-by-24 blocks.
Figure 33: PLL and divide-by-24 circuits
RDS Encoder Project
Hamed Haddadi
33
6.7 Divide-by-2 counter
In order to generate the 1187.4 Hz clock for data output from the message source, the 2375
has to be divided by 2. This is done by using a simple DM74LS393N counter. Figure 34
shows the PSpice diagram of the circuit configuration.
U1A
1
2375Hz
2
CLK
QA
QB
QC
QD
CLR
+5V
3
4
5
6
1187.5 Hz
74LS393
Figure 34: Divide-by-2 counter
Figure 35 displays the waveform output for the complete 57 kHz division to generate the
1187.5 Hz signal.
Figure 35: Divide-by-2 waveform
6.8. Modulation
The RDS bi-phase filtered symbols are modulated into the FM signal using double sideband
suppressed carrier method. The carrier is generated using the 57 kHz clock generated by the
PLL circuit. This is a square wave and it is converted to a sinusoidal wave for use by the
modulator. This conversion is done by using an L-C tuned circuit with a centre frequency of
57 kHz. As the current drawn by the modulator is very little there is no need for transistor
biasing. Figure 36 shows the PSpice diagram of the square-to-sinusoidal converter.
220k
57kHz Sq. Input
57kHz Sine out
100mH
1pF<C<10pF
Figure 36: Square-to-sinusoidal wave converter
The output can be adjusted using the trimmer until the two waves or completely in-phase.
Figure 37 shows the oscilloscope waveform output for the square-to sinusoidal waveform
converter.
RDS Encoder Project
Hamed Haddadi
34
Figure 37: Square-to-sinusoidal waveform
Modulation of the data with the carrier is done using AD633 chip from Analog Devices. It is a
low cost analogue multiplier which uses two external capacitors for double sideband
suppressed carrier modulation. Figure 38 shows the circuit configuration of the modulator.
240nF
AD633JN
RDS data stream
57kHz carrier
1
2
3
4
1
2
3
4
8
7
6
5
8
7
6
5
to station transmitter
0
0
240nF
Figure 38: Modulator
Figure 39 displays the oscilloscope waveform of the modulator output, the input is a pure sine
wave for demonstration purposes.
Figure 39: Modulator waveform
RDS Encoder Project
Hamed Haddadi
35
Figure 40 shows the complete modulator block and square-to sinusoidal converter circuit and
the inverting regulator on breadboard.
Figure 40: Modulator circuit
6.9 Power supply
Most of the components and circuits in the unit require 0V and +5V supplies. The modulator
and inverting amplifier and filtering circuits operate in the range of -12V to +12V. Therefore
a 12V, 400 mA adaptor is purchased to provide regulated DC power from mains. For the
circuits requiring +5V supply, a positive voltage regulator is used to provide regulated DC
voltages. Figure 41 shows the PSpice diagram of circuit configuration of the regulator.
L7805/TO220
+12V DC f rom adaptor
1
VIN
2
VOUT
CAP 0.33uF
+5V
0.1uF
Figure 41: Positive voltage regulator
The -12V voltage is provided using LT1054 from Linear Technology, a switched capacitor
voltage converter with regulator. It simply inverts the input voltage and uses two 100 µF
capacitors. Figure 42 shows the PSpice diagram of the circuit configuration for the voltage
inverter.
1
2
4
7
6
+
CAPACITOR 100uF
8
FB/SD
CAP+
CAPOSC
VREF
VOUT
5
-v e 12V
+
CAPACITOR 100uF
+VCC
LT1054
+v e 12v input
Figure 42: voltage inverter
RDS Encoder Project
Hamed Haddadi
36
7. Conclusions and future work
7.1 Objectives and achievements
The initial objectives of the project and achievements are discussed within this section.
Objective A) Provide RDS data stream for transmission.
This requirement has been fully met as the complete data message source unit has been
designed and tested according to RBDS standard [1]. Valid data is output from the complete
encoder circuit.
Objective B) Complete the real time control software.
This objective has been fully achieved as the control software completes the CRC error
detections and then outputs the data at the right frequency when the 1187.5 signal goes high.
Objective C) Design and build a stand-alone RDS encoder circuit within budget
This objective is achieved based on the fact that all the functional modules and circuits are
tested and synthesized. The PCB design for the data message source has been completed but
the PCBs for the rest of the encoder circuits have not been completed yet. One of the
obstacles in the design has been the lack of PCB auto-routing software that enables PCB
design from schematic diagrams. Table 7 shows the bill for the complete list of components.
It can be verified that the whole system has been built with a budget much less than 3rd year
project budgets, £100. The only part that has not yet been purchased is a PCB rack for the
system which will cost no more than £20.
Component
Trimod LCD 16x2
Push button switch
PIC 16F877 MCU
10 MHz crystal
4018 Counter
Power switch
4046 PLL
Emergency battery holder
Inverting regulator
Modulator
PIC 16C622
Regulator
DC adaptor
Misc. components
Total
Table 7: Project component purchase price
Quantity
1
3
1
2
3
1
1
1
1
1
1
2
1
£66.84
Cost
£10.38
£14.04
£8.72
£5.24
£1.48
£1.71
£0.48
£1.14
£4.06
£0.95
£4.78
£0.87
£7.99
£5.00
7.2 Future work and improvements
The work to be done in the future includes designing PCBs for the rest of the module and
mounting the components. Another task to be completed is extraction of the 19 kHz pilot-tone
from the stereo-coder and feeding it into the system. The final task is to test the system on-air,
when RARE FM launches officially in spring 2004.
RDS Encoder Project
Hamed Haddadi
37
8. Appendix
A. RDS.asm
;
Filename:
rds.asm
*
;
Date:
10th November 2002
*
;**********************************************************************
list
p=16f877
#include <p16f877.inc>
; list directive to define processor
; processor specific variable definitions
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _XT_OSC & _WRT_ENABLE_ON
& _LVP_OFF & _DEBUG_OFF & _CPD_OFF
;***** VARIABLE DEFINITIONS
LCD_DATA
LCD_CTRL
SWITCH_PORT
RDS_PORT
EQU
EQU
EQU
EQU
PORTB
PORTE
PORTD
PORTC
; PORT E, LCD control bits
RS
EQU
0
RW
EQU
1
E
EQU
2
; Switches
; The 1187.5Hz signal input & RDS output port
; LCD Register-Select control line
; LCD Read/Write control line
; LCD Enable control line
;PORT C, RDS data stream output
RDS_DATA
EQU
7
; RDS data stream output, to be transmitted
SIGNAL
EQU
6
; 1187.5 signal
LCD_BYTE
to lcd
CNT_DELAY1
routine
CNT_DELAY2
routines
CNT_DELAY3
LCD_TEMP
CHAR_TEMP
EQU
0x20
; temporary register store for character byte to be sent
EQU
0x21
; temporary count register for 125 microsecond delay
EQU
0x22
; temporary count register 5 and 30 millisecond delay
EQU
EQU
EQU
0x23
0x24
0x25
; Temporary count for long delay
; Temporary register for LCD_BUSY function
; Temporary storage for character comparisons
MS5
MS30
US125
LCD_LINE1
LCD_LINE2
EQU
EQU
EQU
EQU
EQU
0x27
0xe7
0x2a
0x00
0x40
;
;
;
;
;
PS_1
PS_2
PS_3
PS_4
PS_5
PS_6
PS_7
PS_8
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
0x30
0x31
0x32
0x33
0x34
0x35
0x36
0x37
; Registers to store the 8 character PS
CHARACTER
MAX_CHAR
MIN_CHAR
DECISION
POSITION
EQU
EQU
EQU
EQU
EQU
0x38
0x39
0x3a
0x3b
0x3c
;
;
;
;
;
CRC_HIGH
CRC_LOW
CRC_BUF1
CRC_BUF2
GXPOLY_HIGH
GXPOLY_LOW
ITERATIONS
CHAR_HIGH
CHAR_LOW
CHAR_BUF
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
0x3d
0x3e
0x3f
0x41
0x42
0x43
0x44
0x45
0x46
0x47
; CRC calculation registers
CHCKWRD_0_HIGH
CHCKWRD_0_LOW
CHCKWRD_1_HIGH
CHCKWRD_1_LOW
CHCKWRD_2_HIGH
CHCKWRD_2_LOW
CHCKWRD_3_HIGH
EQU
EQU
EQU
EQU
EQU
EQU
EQU
0x48
0x49
0x4a
0x4b
0x4c
0x4d
0x4e
; PS checkwords for 4 different groups
RDS Encoder Project
value to give a 5 millisecond delay in delay loop
value to give a 30 millisecond delay in delay loop
value to give a 125 microsecond delay in delay loop
Address of character 1, Line 1
Address of character 1, line 2
Character to be
The upper limit
The lower limit
The storage for
Position of the
displayed and changed on LCD
of the transmittable character range
of the transmittable character range
user decision
character on the LCD
Hamed Haddadi
38
CHCKWRD_3_LOW
EQU
0x4f
PI_LOW
PI_HIGH
PI_CHCK1_LOW
PI_CHCK1_HIGH
PI_CHCK3_LOW
PI_CHCK3_HIGH
EQU
EQU
EQU
EQU
EQU
EQU
0x50
0x51
0x52
0x53
0x54
0x55
; PI words
BLCK2_0HIGH
EQU
BLCK2_0LOW
EQU
BLCK2_0CHK_LOW EQU
BLCK2_0CHK_HIGH EQU
0x56
0x57
0x58
0x59
; Block 2 data, first group
BLCK2_1HIGH
EQU
BLCK2_1LOW
EQU
BLCK2_1CHK_LOW EQU
BLCK2_1CHK_HIGH EQU
0x5a
0x5b
0x5c
0x5d
; Block 2 data, second group
BLCK2_2HIGH
EQU
BLCK2_2LOW
EQU
BLCK2_2CHK_LOW EQU
BLCK2_2CHK_HIGH EQU
0x5e
0x5f
0x60
0x61
; Block 2 data, third group
BLCK2_3HIGH
EQU
BLCK2_3LOW
EQU
BLCK2_3CHK_LOW EQU
BLCK2_3CHK_HIGH EQU
0x62
0x63
0x64
0x65
; Block 2 data, fourth group
TRX_BUF
0x66
; Data buffer, for bit-by-bit ouput
EQU
; PI checkword with offset A for first block
; PI checkword with offset C' for third block
;**********************************************************************
org
goto
0x00
START
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
clrf
clrf
clrf
clrf
clrf
bsf
clrf
clrf
clrf
movlw
movwf
clrf
bsf
movlw
movwf
bcf
STATUS
; Do initialization, Select bank 0
PORTE
; ALL PORT output should output Low
PORTB
; LCD data Port
PORTC
; RDS signal IO port
PORTD
; Switch port
STATUS, RP0
; Select bank 1
TRISA
; just to save power!
TRISE
; PORT E output
TRISB
; RB7-0 outputs
0x40
; clear TRISC, apart from bit6 for 1187.5 input
TRISC
INTCON
OPTION_REG, NOT_RBPU
; disable pull-ups on port B
0xFF
ADCON1
; Port E is digital
STATUS, RP0
; Select bank 0
call
STORE_CONSTANT_DATA
;
call
INIT_LCD
; Initialise the LCD
;
;
;
movlw
call
call
LCD_LINE1
SET_ADDR
GREETING
; LCD set on Line 1, character 1
; Greets the USER
;
call
LONG_DELAY
;
;
movlw
call
call
LCD_LINE2
SET_ADDR
INTRODUCE
;
call
LONG_DELAY
;
call
LCD_CLEAR
; clear display
;
;
;
movlw
call
call
LCD_LINE1
SET_ADDR
DECIDE
; LCD set on line 1, character 1
; Makes decision
;
call
LONG_DELAY
;
;
;
movlw
call
call
LCD_LINE2
SET_ADDR
QUESTION
; LCD set on Line 2, character 1
;
;
call
call
CHECK_SWITCH
SWITCH_DELAY
; Check for answer
RESET
START
RDS Encoder Project
; LCD set on Line 2, character 1
Hamed Haddadi
39
;
;
;
;
;
;
call
movlw
call
btfsc
call
call
LCD_CLEAR
LCD_LINE1
SET_ADDR
DECISION,0
GET_PS
SWITCH_DELAY
; LCD cleared, line1
; Skip to restore previous settings
; Get and store the new PS
;
call
RESTORE_PS
; Restore PS from EEPROM
;
;
;
;
call
movlw
call
call
LCD_CLEAR
LCD_LINE1
SET_ADDR
CRC_BUSY
; LCD displays that CRC is being calculated
;
call
LONG_DELAY
call
CRC_CALC
call
movlw
call
call
LCD_CLEAR
LCD_LINE1
SET_ADDR
TRANSMIT_DISPLAY
movlw
call
call
LCD_LINE2
SET_ADDR
DISPLAY_PS
; Display the transmitted PS
goto
TRANSMIT
; Transmit the RDS groups
; calculate the CRC checkword values
;######################################################################
; FUNCTION LIST
;######################################################################
STORE_CONSTANT_DATA
; stores the values of constants for transmission
movlw
movwf
movlw
movwf
movlw
movwf
movlw
movwf
movlw
movwf
movlw
movwf
0xc0
PI_HIGH
0x00
PI_LOW
0x00
PI_CHCK1_HIGH
0xd5
PI_CHCK1_LOW
0x03
PI_CHCK3_HIGH
0x79
PI_CHCK3_LOW
movlw
movwf
movlw
movwf
movlw
movwf
movlw
movwf
0x08
; Block2 data for the first group
BLCK2_0HIGH
0x08
BLCK2_0LOW
0x01
BLCK2_0CHK_HIGH
; Checkword with offset B
0xc2
BLCK2_0CHK_LOW
movlw
movwf
movlw
movwf
movlw
movwf
movlw
movwf
0x08
; Block2 data for the second group
BLCK2_1HIGH
0x09
BLCK2_1LOW
0x00
; Checkword with offset B
BLCK2_1CHK_HIGH
0x6b
BLCK2_1CHK_LOW
movlw
movwf
movlw
movwf
movlw
movwf
movlw
movwf
0x08
; Block2 data for the third group
BLCK2_2HIGH
0x0a
BLCK2_2LOW
0x02
; Checkword with offset B
BLCK2_2CHK_HIGH
0xb0
BLCK2_2CHK_LOW
movlw
movwf
movlw
movwf
movlw
movwf
0x08
; Block2 data for the fourth group
BLCK2_3HIGH
0x0f
BLCK2_3LOW
0x00
; Checkword with offset B
BLCK2_3CHK_HIGH
RDS Encoder Project
; Move 11000000 to PI upper register
; Move 00000000 to PI lower register
; PI checkword with offset A for first block
; PI checkword with offset C' for third block
Hamed Haddadi
40
movlw
movwf
0x58
BLCK2_3CHK_LOW
return
;**********************************************************************
; INIT_LCD...... Module to initialise the display
;**********************************************************************
INIT_LCD
call
DELAY_30MS
movlw
call
call
0x38
LCD_CMND
DELAY_5MS
; 8-bit-interface, 2-lines... 0b00111000
movlw
call
call
0x38
LCD_CMND
DELAY_125US
; 8-bit-interface, 2-lines... 0b00111000
movlw
call
call
0x38
LCD_CMND
DELAY_125US
; 8-bit-interface, 2-lines... 0b00111000
movlw
call
call
0x0F
LCD_CMND
DELAY_5MS
; display On, curser On, blink On 0b00001111
movlw
call
0x01
LCD_CMND
; display clear, 0b00000001
return
GREETING
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
return
INTRODUCE
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
'U'
LCD_CHAR
'C'
LCD_CHAR
'L'
LCD_CHAR
' '
LCD_CHAR
' '
LCD_CHAR
'R'
LCD_CHAR
'D'
LCD_CHAR
'S'
LCD_CHAR
' '
LCD_CHAR
'E'
LCD_CHAR
'N'
LCD_CHAR
'C'
LCD_CHAR
'O'
LCD_CHAR
'D'
LCD_CHAR
'E'
LCD_CHAR
'R'
LCD_CHAR
'B'
LCD_CHAR
'Y'
LCD_CHAR
' '
LCD_CHAR
'H'
LCD_CHAR
'A'
LCD_CHAR
'M'
LCD_CHAR
'E'
LCD_CHAR
'D'
LCD_CHAR
' '
LCD_CHAR
'H'
LCD_CHAR
RDS Encoder Project
Hamed Haddadi
41
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
return
'A'
LCD_CHAR
'D'
LCD_CHAR
'D'
LCD_CHAR
'A'
LCD_CHAR
'D'
LCD_CHAR
'I'
LCD_CHAR
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
return
'R'
LCD_CHAR
'E'
LCD_CHAR
'S'
LCD_CHAR
'T'
LCD_CHAR
'O'
LCD_CHAR
'R'
LCD_CHAR
'E'
LCD_CHAR
' '
LCD_CHAR
'S'
LCD_CHAR
'E'
LCD_CHAR
'T'
LCD_CHAR
'T'
LCD_CHAR
'I'
LCD_CHAR
'N'
LCD_CHAR
'G'
LCD_CHAR
'S'
LCD_CHAR
QUESTION
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
return
'Y'
LCD_CHAR
'E'
LCD_CHAR
'S'
LCD_CHAR
'/'
LCD_CHAR
'N'
LCD_CHAR
'O'
LCD_CHAR
'?'
LCD_CHAR
DECIDE
CHECK_SWITCH
GET_IT btfsc
call
btfsc
call
got
btfss
goto
movf
andlw
btfsc
goto
return
; Polls switches for decision to restore setting
SWITCH_PORT,0
D0_SET
SWITCH_PORT,1
D1_SET
SWITCH_PORT,2
GET_IT
DECISION,W
; Check if D2 is not pressed
0xff
; without making a decision
STATUS,Z
GET_IT
; if yes, loop until decision is made
D0_SET
call
movlw
call
movlw
call
movlw
call
SWITCH_DELAY
0x48
SET_ADDR
'N'
LCD_CHAR
'O'
LCD_CHAR
RDS Encoder Project
; LCD set on Line 2, character 9
Hamed Haddadi
42
movlw
call
movlw
movwf
return
' '
LCD_CHAR
0x1
DECISION
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
movwf
return
SWITCH_DELAY
0x48
SET_ADDR
'Y'
LCD_CHAR
'E'
LCD_CHAR
'S'
LCD_CHAR
0x2
DECISION
D1_SET
PS_REQUEST
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
return
; LCD set on Line 2, character 9
'E'
LCD_CHAR
'N'
LCD_CHAR
'T'
LCD_CHAR
'E'
LCD_CHAR
'R'
LCD_CHAR
' '
LCD_CHAR
'P'
LCD_CHAR
'S'
LCD_CHAR
':'
GET_PS
call
movlw
movwf
movlw
movwf
PS_REQUEST
' '
MIN_CHAR
'Z'
MAX_CHAR
; ask for PS to be entered
movlw
movwf
call
movlw
movwf
call
call
movwf
0x40
POSITION
SET_ADDR
'A'
CHARACTER
LCD_CHAR
GET_PS1
PS_1
; Set position, line 2 character 0
bsf
bsf
btfsc
call
bcf
movwf
movlw
movwf
bsf
bcf
bsf
movlw
movwf
movlw
movwf
bsf
bcf
clrf
STATUS,RP1
STATUS,RP0
EECON1,WR
DELAY_5MS
STATUS,RP0
EEDATA
0x00
EEADR
STATUS,RP0
EECON1,EEPGD
EECON1,WREN
0x55
EECON2
0xaa
EECON2
EECON1,WR
EECON1,WREN
STATUS
; Store in EEPROM
call
SWITCH_DELAY
movlw
movwf
movf
call
call
movwf
bsf
bsf
btfsc
call
bcf
movwf
0x41
POSITION
CHARACTER,0
LCD_CHAR
GET_PS2
PS_2
STATUS,RP1
STATUS,RP0
EECON1,WR
DELAY_5MS
STATUS,RP0
EEDATA
RDS Encoder Project
; set the lower boundary
; set the upper boundary
; store in variable
; Make sure there is no other WRITE in progress
; Write data and destination
; Select bank 0
; Set position, line 2 character 1
; store in variable
; Store in EEPROM
; Make sure there is no other WRITE in progress
Hamed Haddadi
43
movlw
movwf
bsf
bcf
bsf
movlw
movwf
movlw
movwf
bsf
bcf
clrf
0x01
EEADR
STATUS,RP0
EECON1,EEPGD
EECON1,WREN
0x55
EECON2
0xaa
EECON2
EECON1,WR
EECON1,WREN
STATUS
call
SWITCH_DELAY
movlw
movwf
movf
call
call
movwf
bsf
bsf
btfsc
call
bcf
movwf
movlw
movwf
bsf
bcf
bsf
movlw
movwf
movlw
movwf
bsf
bcf
clrf
0x42
POSITION
CHARACTER,0
LCD_CHAR
GET_PS3
PS_3
STATUS,RP1
STATUS,RP0
EECON1,WR
DELAY_5MS
STATUS,RP0
EEDATA
0x02
EEADR
STATUS,RP0
EECON1,EEPGD
EECON1,WREN
0x55
EECON2
0xaa
EECON2
EECON1,WR
EECON1,WREN
STATUS
call
SWITCH_DELAY
movlw
movwf
movf
call
call
movwf
bsf
bsf
btfsc
call
bcf
movwf
movlw
movwf
bsf
bcf
bsf
movlw
movwf
movlw
movwf
bsf
bcf
clrf
0x43
POSITION
CHARACTER,0
LCD_CHAR
GET_PS4
PS_4
STATUS,RP1
STATUS,RP0
EECON1,WR
DELAY_5MS
STATUS,RP0
EEDATA
0x03
EEADR
STATUS,RP0
EECON1,EEPGD
EECON1,WREN
0x55
EECON2
0xaa
EECON2
EECON1,WR
EECON1,WREN
STATUS
call
SWITCH_DELAY
movlw
movwf
movf
call
call
movwf
bsf
bsf
btfsc
call
bcf
movwf
movlw
movwf
bsf
bcf
bsf
movlw
movwf
movlw
0x44
POSITION
CHARACTER,0
LCD_CHAR
GET_PS5
PS_5
STATUS,RP1
STATUS,RP0
EECON1,WR
DELAY_5MS
STATUS,RP0
EEDATA
0x04
EEADR
STATUS,RP0
EECON1,EEPGD
EECON1,WREN
0x55
EECON2
0xaa
RDS Encoder Project
; Select bank 0
; Set position, line 2 character 2
; store in variable
; Store in EEPROM
; Make sure there is no other WRITE in progress
; Select bank 0
; Set position, line 2 character 3
; store in variable
; Store in EEPROM
; Make sure there is no other WRITE in progress
; Select bank 0
; Set position, line 2 character 4
; store in variable
; Store in EEPROM
; Make sure there is no other WRITE in progress
Hamed Haddadi
44
movwf
bsf
bcf
clrf
EECON2
EECON1,WR
EECON1,WREN
STATUS
call
SWITCH_DELAY
movlw
movwf
movf
call
call
movwf
bsf
bsf
btfsc
call
bcf
movwf
movlw
movwf
bsf
bcf
bsf
movlw
movwf
movlw
movwf
bsf
bcf
clrf
0x45
POSITION
CHARACTER,0
LCD_CHAR
GET_PS6
PS_6
STATUS,RP1
STATUS,RP0
EECON1,WR
DELAY_5MS
STATUS,RP0
EEDATA
0x05
EEADR
STATUS,RP0
EECON1,EEPGD
EECON1,WREN
0x55
EECON2
0xaa
EECON2
EECON1,WR
EECON1,WREN
STATUS
call
SWITCH_DELAY
movlw
movwf
movf
call
call
movwf
bsf
bsf
btfsc
call
bcf
movwf
movlw
movwf
bsf
bcf
bsf
movlw
movwf
movlw
movwf
bsf
bcf
clrf
0x46
POSITION
CHARACTER,0
LCD_CHAR
GET_PS7
PS_7
STATUS,RP1
STATUS,RP0
EECON1,WR
DELAY_5MS
STATUS,RP0
EEDATA
0x06
EEADR
STATUS,RP0
EECON1,EEPGD
EECON1,WREN
0x55
EECON2
0xaa
EECON2
EECON1,WR
EECON1,WREN
STATUS
call
SWITCH_DELAY
movlw
movwf
movf
call
call
movwf
bsf
bsf
btfsc
call
bcf
movwf
movlw
movwf
bsf
bcf
bsf
movlw
movwf
movlw
movwf
bsf
bcf
clrf
0x47
POSITION
CHARACTER,0
LCD_CHAR
GET_PS8
PS_8
STATUS,RP1
STATUS,RP0
EECON1,WR
DELAY_5MS
STATUS,RP0
EEDATA
0x07
EEADR
STATUS,RP0
EECON1,EEPGD
EECON1,WREN
0x55
EECON2
0xaa
EECON2
EECON1,WR
EECON1,WREN
STATUS
; Select bank 0
; Set position, line 2 character 5
; store in variable
; Store in EEPROM
; Make sure there is no other WRITE in progress
; Select bank 0
; Set position, line 2 character 6
; store in variable
; Store in EEPROM
; Make sure there is no other WRITE in progress
; Select bank 0
; Set position, line 2 character 7
; store in variable
; Store in EEPROM
; Make sure there is no other WRITE in progress
; Select bank 0
return
RDS Encoder Project
Hamed Haddadi
45
GET_PS1 btfsc
call
btfsc
call
btfss
goto
return
SWITCH_PORT,0
CHAR_UP
SWITCH_PORT,1
CHAR_DOWN
SWITCH_PORT,2
GET_PS1
GET_PS2 btfsc
call
btfsc
call
btfss
goto
return
SWITCH_PORT,0
CHAR_UP
SWITCH_PORT,1
CHAR_DOWN
SWITCH_PORT,2
GET_PS2
GET_PS3 btfsc
call
btfsc
call
btfss
goto
return
SWITCH_PORT,0
CHAR_UP
SWITCH_PORT,1
CHAR_DOWN
SWITCH_PORT,2
GET_PS3
GET_PS4 btfsc
call
btfsc
call
btfss
goto
return
SWITCH_PORT,0
CHAR_UP
SWITCH_PORT,1
CHAR_DOWN
SWITCH_PORT,2
GET_PS4
GET_PS5 btfsc
call
btfsc
call
btfss
goto
return
SWITCH_PORT,0
CHAR_UP
SWITCH_PORT,1
CHAR_DOWN
SWITCH_PORT,2
GET_PS5
GET_PS6 btfsc
call
btfsc
call
btfss
goto
return
SWITCH_PORT,0
CHAR_UP
SWITCH_PORT,1
CHAR_DOWN
SWITCH_PORT,2
GET_PS6
GET_PS7 btfsc
call
btfsc
call
btfss
goto
return
SWITCH_PORT,0
CHAR_UP
SWITCH_PORT,1
CHAR_DOWN
SWITCH_PORT,2
GET_PS7
GET_PS8 btfsc
call
btfsc
call
btfss
goto
return
SWITCH_PORT,0
CHAR_UP
SWITCH_PORT,1
CHAR_DOWN
SWITCH_PORT,2
GET_PS8
; Increment Character if Switch 0 pressed
; Decrement Character if Switch 1 pressed
CHAR_UP
call
movf
call
movf
call
movf
call
return
check_max
movwf
movf
subwf
btfsc
goto
goto
SWITCH_DELAY
POSITION,0
SET_ADDR
CHARACTER,0
check_max
CHARACTER,0
LCD_CHAR
; move character to W register
; check if reached the upper boundary
CHAR_TEMP
MAX_CHAR,0
CHAR_TEMP,0
STATUS,Z
SET2MAX
INCREMENT
;
;
;
;
;
;
;
; set display position
it checks mor the upper character
store the character locally
now move MAX_CHAR to W register
subtract the two files
Is the result zero?? then we reached maximum
keep the character as it is
if not reached the max, increment the character
SET2MAX
movf
MAX_CHAR,0
return
; Keep MAX_CHAR as the character of chioce
INCREMENT
RDS Encoder Project
Hamed Haddadi
46
incf
CHARACTER,1
return
; increment the character
CHAR_DOWN
call
movf
call
movf
call
movf
call
return
SWITCH_DELAY
POSITION,0
SET_ADDR
CHARACTER,0
check_min
CHARACTER,0
LCD_CHAR
; move character to W register
; check if reached the lower boundary
check_min
movwf
movf
subwf
btfsc
goto
goto
CHAR_TEMP
MIN_CHAR,0
CHAR_TEMP,0
STATUS,Z
SET2MIN
DECREMENT
;
;
;
;
;
;
;
; set display position
it checks mor the lower character
store the character locally
now move MIN_CHAR to W register
subtract the two files
Is the result zero?? then we reached minimum
keep the character as it is
if not reached the min, decrement the character
SET2MIN
movf
MIN_CHAR,0
return
; Keep MIN_CHAR as the character of chioce
DECREMENT
decf
CHARACTER,1
return
; decrement the character
RESTORE_PS
; Restore the PS characters from EEPROM
bsf
bcf
movlw
movwf
bsf
bcf
bsf
bcf
movf
clrf
movwf
call
STATUS,RP1
STATUS,RP0
0x00
EEADR
STATUS,RP0
EECON1, EEPGD
EECON1, RD
STATUS,RP0
EEDATA,0
STATUS
PS_1
SWITCH_DELAY
bsf
bcf
movlw
movwf
bsf
bcf
bsf
bcf
movf
clrf
movwf
call
STATUS,RP1
STATUS,RP0
0x01
EEADR
STATUS,RP0
EECON1, EEPGD
EECON1, RD
STATUS,RP0
EEDATA,0
STATUS
PS_2
SWITCH_DELAY
bsf
bcf
movlw
movwf
bsf
bcf
bsf
bcf
movf
clrf
movwf
call
STATUS,RP1
STATUS,RP0
0x02
EEADR
STATUS,RP0
EECON1, EEPGD
EECON1, RD
STATUS,RP0
EEDATA,0
STATUS
PS_3
SWITCH_DELAY
bsf
bcf
movlw
movwf
bsf
bcf
bsf
bcf
movf
clrf
movwf
call
STATUS,RP1
STATUS,RP0
0x03
EEADR
STATUS,RP0
EECON1, EEPGD
EECON1, RD
STATUS,RP0
EEDATA,0
STATUS
PS_4
SWITCH_DELAY
RDS Encoder Project
; Select bank 0
; Select bank 0
; Select bank 0
Hamed Haddadi
47
bsf
bcf
movlw
movwf
bsf
bcf
bsf
bcf
movf
clrf
movwf
call
STATUS,RP1
STATUS,RP0
0x04
EEADR
STATUS,RP0
EECON1, EEPGD
EECON1, RD
STATUS,RP0
EEDATA,0
STATUS
PS_5
SWITCH_DELAY
bsf
bcf
movlw
movwf
bsf
bcf
bsf
bcf
movf
clrf
movwf
call
STATUS,RP1
STATUS,RP0
0x05
EEADR
STATUS,RP0
EECON1, EEPGD
EECON1, RD
STATUS,RP0
EEDATA,0
STATUS
PS_6
SWITCH_DELAY
bsf
bcf
movlw
movwf
bsf
bcf
bsf
bcf
movf
clrf
movwf
call
STATUS,RP1
STATUS,RP0
0x06
EEADR
STATUS,RP0
EECON1, EEPGD
EECON1, RD
STATUS,RP0
EEDATA,0
STATUS
PS_7
SWITCH_DELAY
bsf
bcf
movlw
movwf
bsf
bcf
bsf
bcf
movf
clrf
movwf
call
STATUS,RP1
STATUS,RP0
0x07
EEADR
STATUS,RP0
EECON1, EEPGD
EECON1, RD
STATUS,RP0
EEDATA,0
STATUS
PS_8
SWITCH_DELAY
; Select bank 0
; Select bank 0
; Select bank 0
; Select bank 0
return
CRC_BUSY
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
'C'
LCD_CHAR
'R'
LCD_CHAR
'C'
LCD_CHAR
' '
LCD_CHAR
'C'
LCD_CHAR
'A'
LCD_CHAR
'L'
LCD_CHAR
'C'
LCD_CHAR
'U'
LCD_CHAR
'L'
LCD_CHAR
'A'
LCD_CHAR
'T'
LCD_CHAR
'I'
LCD_CHAR
'O'
LCD_CHAR
'N'
RDS Encoder Project
Hamed Haddadi
48
call
LCD_CHAR
movlw
'.'
call
LCD_CHAR
return
CRC_CALC
call
call
call
call
return
CRC_0
CRC_1
CRC_2
CRC_3
CRC_0
;
;
;
;
;
CheckWord calculation for the PS
PS_1 and PS_2, for first transmission group
PS_3 and PS_4, for second transmission group
PS_5 and PS_6, for third transmission group
PS_7 and PS_8, for fourth transmission group
; Calculate the checkword for the first PS block
movf
movwf
movf
movwf
PS_1,0
CHAR_HIGH
PS_2,0
CHAR_LOW
; move PS_1 to the upper working register
call
call
CRC_INIT
CRC_GEN
; Initialise the registers
; Calculate CRC
movf
xorlw
movwf
movf
xorlw
movwf
return
CRC_HIGH,0
0x01
CHCKWRD_0_HIGH
CRC_LOW,0
0xb4
CHCKWRD_0_LOW
;
;
;
;
;
;
movf
movwf
movf
movwf
PS_3,0
CHAR_HIGH
PS_4,0
CHAR_LOW
call
call
CRC_INIT
CRC_GEN
; Initialise the registers
; Calculate CRC
movf
xorlw
movwf
movf
xorlw
movwf
return
CRC_HIGH,0
0x01
CHCKWRD_1_HIGH
CRC_LOW,0
0xb4
CHCKWRD_1_LOW
;
;
;
;
;
;
movf
movwf
movf
movwf
PS_5,0
CHAR_HIGH
PS_6,0
CHAR_LOW
call
call
CRC_INIT
CRC_GEN
; Initialise the registers
; Calculate CRC
movf
xorlw
movwf
movf
xorlw
movwf
return
CRC_HIGH,0
0x01
CHCKWRD_2_HIGH
CRC_LOW,0
0xb4
CHCKWRD_2_LOW
;
;
;
;
;
;
movf
movwf
movf
movwf
PS_7,0
CHAR_HIGH
PS_8,0
CHAR_LOW
; move PS_7 to the upper working register
call
call
CRC_INIT
CRC_GEN
; Initialise the registers
; Calculate CRC
movf
xorlw
movwf
movf
xorlw
movwf
return
CRC_HIGH,0
0x01
CHCKWRD_3_HIGH
CRC_LOW,0
0xb4
CHCKWRD_3_LOW
;
;
;
;
;
;
Load W with CRC upper part
Add upper part of offset D
Store in Checkword upper part
Load W with CRC lower part
Add lower part of offset D
Store in Checkword lower part
CHAR_BUF
STATUS,C
CHAR_LOW,1
CHAR_HIGH,1
CHAR_BUF,1
STATUS,C
;
;
;
;
;
;
;
Initialise the registers
rotate left twice, through carry,
so that the 10^X factor can correctly
be implemented, i.e. by adding an 8bit
all 0s register to the end of the data,
and shifting to left twice to have another
2 obits.
CRC_1
; move PS_2 to the lower working register
Load W with CRC upper part
Add upper part of offset D
Store in Checkword upper part
Load W with CRC lower part
Add lower part of offset D
Store in Checkword lower part
; Calculate the checkword for the second PS block
CRC_2
; move PS_3 to the upper working register
; move PS_4 to the lower working register
Load W with CRC upper part
Add upper part of offset D
Store in Checkword upper part
Load W with CRC lower part
Add lower part of offset D
Store in Checkword lower part
; Calculate the checkword for the third PS block
CRC_3
; move PS_5 to the upper working register
; move PS_6 to the lower working register
Load W with CRC upper part
Add upper part of offset D
Store in Checkword upper part
Load W with CRC lower part
Add lower part of offset D
Store in Checkword lower part
; Calculate the checkword for the fourth PS block
CRC_INIT
clrf
bcf
rlf
rlf
rlf
bcf
RDS Encoder Project
; move PS_8 to the lower working register
Hamed Haddadi
49
rlf
rlf
rlf
CHAR_LOW,1
CHAR_HIGH,1
CHAR_BUF,1
movlw
movwf
movf
movwf
movf
movwf
movf
movwf
movlw
movwf
0x10
ITERATIONS
CHAR_BUF,0
CRC_HIGH
CHAR_HIGH,0
CRC_LOW
CHAR_LOW,0
CRC_BUF1
0x00
CRC_BUF2
; 16 left shifts, for the CRC calculation
movlw
movwf
movlw
movwf
0x05
GXPOLY_HIGH
0xb9
GXPOLY_LOW
; Storing the g(x) polynomial in registers
; shifting all to the right place
; adding the last 8 zero's
return
CRC_GEN
bcf
rlf
rlf
rlf
rlf
STATUS,C
CRC_BUF2,1
CRC_BUF1,1
CRC_LOW,1
CRC_HIGH,1
btfsc
call
decfsz
goto
return
CRC_HIGH,2
DO_XOR
ITERATIONS,1
CRC_GEN
movf
xorwf
movf
xorwf
return
GXPOLY_LOW,0
CRC_LOW,1
GXPOLY_HIGH,0
CRC_HIGH,1
DO_XOR
;
;
;
;
;
CRC generator routine
clear the carry bit
left shift all the data by one bit,
using carry flag, so the carry 1 or 0
will go to the LSB of next byte
;
;
;
;
is the last bit a 1?
if yes, XOR the working registers with g(x)
Decrement iterations, more bits left?
if yes, do another bit
; Modulo 2 division with the g(x)
TRANSMIT_DISPLAY
movlw
'T'
call
LCD_CHAR
movlw
'R'
call
LCD_CHAR
movlw
'A'
call
LCD_CHAR
movlw
'N'
call
LCD_CHAR
movlw
'S'
call
LCD_CHAR
movlw
'M'
call
LCD_CHAR
movlw
'I'
call
LCD_CHAR
movlw
'T'
call
LCD_CHAR
movlw
'T'
call
LCD_CHAR
movlw
'I'
call
LCD_CHAR
movlw
'N'
call
LCD_CHAR
movlw
'G'
call
LCD_CHAR
return
DISPLAY_PS
movf
call
movf
call
movf
call
movf
call
movf
call
movf
call
movf
call
movf
; Displays the currently transmitted PS
PS_1,0
LCD_CHAR
PS_2,0
LCD_CHAR
PS_3,0
LCD_CHAR
PS_4,0
LCD_CHAR
PS_5,0
LCD_CHAR
PS_6,0
LCD_CHAR
PS_7,0
LCD_CHAR
PS_8,0
RDS Encoder Project
Hamed Haddadi
50
call
LCD_CHAR
return
TRANSMIT
call
call
call
call
goto
TRANSMIT_G0
TRANSMIT_G1
TRANSMIT_G2
TRANSMIT_G3
TRANSMIT
;
;
;
;
;
;
Transmit the RDS data-stream
Group 0
Group 1
Group 2
Group 3
Loop forever
TRANSMIT_G0
movlw
movwf
movf
movwf
call
; Transmit the first group, with PS_1 & PS_2
0x08
; Send the top byte of PI
ITERATIONS
PI_HIGH,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send the lower bye of PI
ITERATIONS
PI_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
swapf
rlf
rlf
call
0x02
; Send top two bits of PI checkword offset A
ITERATIONS
PI_CHCK1_HIGH,0
; Move the whole byte
TRX_BUF
TRX_BUF,1
; Swap nibbles
TRX_BUF,1
; Rotate left twice, to bring the first bit
TRX_BUF,1
; of the two bits to the MSB location
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send lower byte of PI checkword offset A
ITERATIONS
PI_CHCK1_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send upper part of block 2
ITERATIONS
BLCK2_0HIGH,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send lower byte of block 2
ITERATIONS
BLCK2_0LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
swapf
rlf
rlf
call
0x02
; Send the top two bits of Block 2 checkword
ITERATIONS
BLCK2_0CHK_HIGH,0
; Move the whole byte
TRX_BUF
TRX_BUF,1
; Swap nibbles
TRX_BUF,1
; Rotate left twice, to bring the first bit
TRX_BUF,1
; of the two bits to the MSB location
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send the lower byte of block2 checkword
ITERATIONS
BLCK2_0CHK_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send the top byte of PI
ITERATIONS
PI_HIGH,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send the lower bye of PI
ITERATIONS
PI_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
swapf
rlf
rlf
call
0x02
; Send top two bits of PI checkword offset C'
ITERATIONS
PI_CHCK3_HIGH,0
; Move the whole byte
TRX_BUF
TRX_BUF,1
; Swap nibbles
TRX_BUF,1
; Rotate left twice, to bring the first bit
TRX_BUF,1
; of the two bits to the MSB location
TRANSMIT_BUF_DATA
RDS Encoder Project
Hamed Haddadi
51
movlw
movwf
movf
movwf
call
0x08
; Send lower byte of PI checkword offset C'
ITERATIONS
PI_CHCK3_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send PS_1
ITERATIONS
PS_1,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send PS_2
ITERATIONS
PS_2,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
swapf
rlf
rlf
call
0x02
; Send the top two bits of PS checkword
ITERATIONS
CHCKWRD_0_HIGH,0
; Move the whole byte
TRX_BUF
TRX_BUF,1
; Swap nibbles
TRX_BUF,1
; Rotate left twice, to bring the first bit
TRX_BUF,1
; of the two bits to the MSB location
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send lower byte of PS checkword
ITERATIONS
CHCKWRD_0_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
return
TRANSMIT_G1
movlw
movwf
movf
movwf
call
; Transmit the first group, with PS_3 & PS_4
0x08
; Send the top byte of PI
ITERATIONS
PI_HIGH,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send the lower bye of PI
ITERATIONS
PI_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
swapf
rlf
rlf
call
0x02
; Send top two bits of PI checkword offset A
ITERATIONS
PI_CHCK1_HIGH,0
; Move the whole byte
TRX_BUF
TRX_BUF,1
; Swap nibbles
TRX_BUF,1
; Rotate left twice, to bring the first bit
TRX_BUF,1
; of the two bits to the MSB location
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send lower byte of PI checkword offset A
ITERATIONS
PI_CHCK1_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send upper part of block 2
ITERATIONS
BLCK2_1HIGH,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send lower byte of block 2
ITERATIONS
BLCK2_1LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
swapf
rlf
rlf
call
0x02
; Send the top two bits of Block 2 checkword
ITERATIONS
BLCK2_1CHK_HIGH,0
; Move the whole byte
TRX_BUF
TRX_BUF,1
; Swap nibbles
TRX_BUF,1
; Rotate left twice, to bring the first bit
TRX_BUF,1
; of the two bits to the MSB location
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send the lower byte of block2 checkword
ITERATIONS
BLCK2_1CHK_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
RDS Encoder Project
Hamed Haddadi
52
movlw
movwf
movf
movwf
call
0x08
; Send the top byte of PI
ITERATIONS
PI_HIGH,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send the lower bye of PI
ITERATIONS
PI_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
swapf
rlf
rlf
call
0x02
; Send top two bits of PI checkword offset C'
ITERATIONS
PI_CHCK3_HIGH,0
; Move the whole byte
TRX_BUF
TRX_BUF,1
; Swap nibbles
TRX_BUF,1
; Rotate left twice, to bring the first bit
TRX_BUF,1
; of the two bits to the MSB location
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send lower byte of PI checkword offset C'
ITERATIONS
PI_CHCK3_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send PS_1
ITERATIONS
PS_3,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send PS_2
ITERATIONS
PS_4,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
swapf
rlf
rlf
call
0x02
; Send the top two bits of PS checkword
ITERATIONS
CHCKWRD_1_HIGH,0
; Move the whole byte
TRX_BUF
TRX_BUF,1
; Swap nibbles
TRX_BUF,1
; Rotate left twice, to bring the first bit
TRX_BUF,1
; of the two bits to the MSB location
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send lower byte of PS checkword
ITERATIONS
CHCKWRD_1_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
return
TRANSMIT_G2
movlw
movwf
movf
movwf
call
; Transmit the first group, with PS_1 & PS_2
0x08
; Send the top byte of PI
ITERATIONS
PI_HIGH,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send the lower bye of PI
ITERATIONS
PI_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
swapf
rlf
rlf
call
0x02
; Send top two bits of PI checkword offset A
ITERATIONS
PI_CHCK1_HIGH,0
; Move the whole byte
TRX_BUF
TRX_BUF,1
; Swap nibbles
TRX_BUF,1
; Rotate left twice, to bring the first bit
TRX_BUF,1
; of the two bits to the MSB location
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send lower byte of PI checkword offset A
ITERATIONS
PI_CHCK1_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
0x08
ITERATIONS
BLCK2_2HIGH,0
TRX_BUF
RDS Encoder Project
; Send upper part of block 2
Hamed Haddadi
53
call
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send lower byte of block 2
ITERATIONS
BLCK2_2LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
swapf
rlf
rlf
call
0x02
; Send the top two bits of Block 2 checkword
ITERATIONS
BLCK2_2CHK_HIGH,0
; Move the whole byte
TRX_BUF
TRX_BUF,1
; Swap nibbles
TRX_BUF,1
; Rotate left twice, to bring the first bit
TRX_BUF,1
; of the two bits to the MSB location
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send the lower byte of block2 checkword
ITERATIONS
BLCK2_2CHK_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send the top byte of PI
ITERATIONS
PI_HIGH,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send the lower bye of PI
ITERATIONS
PI_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
swapf
rlf
rlf
call
0x02
; Send top two bits of PI checkword offset C'
ITERATIONS
PI_CHCK3_HIGH,0
; Move the whole byte
TRX_BUF
TRX_BUF,1
; Swap nibbles
TRX_BUF,1
; Rotate left twice, to bring the first bit
TRX_BUF,1
; of the two bits to the MSB location
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send lower byte of PI checkword offset C'
ITERATIONS
PI_CHCK3_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send PS_1
ITERATIONS
PS_5,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send PS_2
ITERATIONS
PS_6,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
swapf
rlf
rlf
call
0x02
; Send the top two bits of PS checkword
ITERATIONS
CHCKWRD_2_HIGH,0
; Move the whole byte
TRX_BUF
TRX_BUF,1
; Swap nibbles
TRX_BUF,1
; Rotate left twice, to bring the first bit
TRX_BUF,1
; of the two bits to the MSB location
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send lower byte of PS checkword
ITERATIONS
CHCKWRD_2_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
return
TRANSMIT_G3
movlw
movwf
movf
movwf
call
movlw
movwf
movf
; Transmit the first group, with PS_1 & PS_2
0x08
; Send the top byte of PI
ITERATIONS
PI_HIGH,0
TRX_BUF
TRANSMIT_BUF_DATA
0x08
ITERATIONS
PI_LOW,0
RDS Encoder Project
; Send the lower bye of PI
Hamed Haddadi
54
movwf
call
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
swapf
rlf
rlf
call
0x02
; Send top two bits of PI checkword offset A
ITERATIONS
PI_CHCK1_HIGH,0
; Move the whole byte
TRX_BUF
TRX_BUF,1
; Swap nibbles
TRX_BUF,1
; Rotate left twice, to bring the first bit
TRX_BUF,1
; of the two bits to the MSB location
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send lower byte of PI checkword offset A
ITERATIONS
PI_CHCK1_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send upper part of block 2
ITERATIONS
BLCK2_3HIGH,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send lower byte of block 2
ITERATIONS
BLCK2_3LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
swapf
rlf
rlf
call
0x02
; Send the top two bits of Block 2 checkword
ITERATIONS
BLCK2_3CHK_HIGH,0
; Move the whole byte
TRX_BUF
TRX_BUF,1
; Swap nibbles
TRX_BUF,1
; Rotate left twice, to bring the first bit
TRX_BUF,1
; of the two bits to the MSB location
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send the lower byte of block2 checkword
ITERATIONS
BLCK2_3CHK_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send the top byte of PI
ITERATIONS
PI_HIGH,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send the lower bye of PI
ITERATIONS
PI_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
swapf
rlf
rlf
call
0x02
; Send top two bits of PI checkword offset C'
ITERATIONS
PI_CHCK3_HIGH,0
; Move the whole byte
TRX_BUF
TRX_BUF,1
; Swap nibbles
TRX_BUF,1
; Rotate left twice, to bring the first bit
TRX_BUF,1
; of the two bits to the MSB location
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send lower byte of PI checkword offset C'
ITERATIONS
PI_CHCK3_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send PS_1
ITERATIONS
PS_7,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send PS_2
ITERATIONS
PS_8,0
TRX_BUF
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
swapf
0x02
; Send the top two bits of PS checkword
ITERATIONS
CHCKWRD_3_HIGH,0
; Move the whole byte
TRX_BUF
TRX_BUF,1
; Swap nibbles
RDS Encoder Project
Hamed Haddadi
55
rlf
rlf
call
TRX_BUF,1
; Rotate left twice, to bring the first bit
TRX_BUF,1
; of the two bits to the MSB location
TRANSMIT_BUF_DATA
movlw
movwf
movf
movwf
call
0x08
; Send lower byte of PS checkword
ITERATIONS
CHCKWRD_3_LOW,0
TRX_BUF
TRANSMIT_BUF_DATA
return
TRANSMIT_BUF_DATA
; Transmit the data byte held in the buffer
rlf
TRX_BUF,1
; Rotate left once, in itself
btfss
STATUS, C
; Test the carry flag value
call
TRANSMIT_0
; is carry 0? transmit a 0
btfsc
STATUS, C
call
TRANSMIT_1
; Is carry 1? transmit a 1
decfsz ITERATIONS,1
; Decrement iteration until it reaches 0
goto
TRANSMIT_BUF_DATA
return
TRANSMIT_0
;
call
btfss
goto
bcf
return
DELAY_125US
RDS_PORT,SIGNAL
; Is 1187.5 high?
TRANSMIT_0
; No? then loop until it goes high
RDS_PORT, RDS_DATA
; Clear the port bit, 0 will be modulated
TRANSMIT_1
;
call
btfss
goto
bsf
return
DELAY_125US
RDS_PORT,SIGNAL
; Is 1187.5 high?
TRANSMIT_1
; No? then loop until it goes high
RDS_PORT, RDS_DATA
; Set the port bit, 1 will be modulated
;=============================================================================
; LCD_CHAR
; Sends character to LCD
; Required character must be in W
;=============================================================================
LCD_CHAR
movwf
LCD_TEMP
; Character to be sent is in W
call
LCDBUSY
; Wait for LCD to be ready
bcf
LCD_CTRL, RW
; Set LCD in read mode
bsf
LCD_CTRL, RS
; Set LCD in data mode
bsf
LCD_CTRL, E
; LCD E-line High
movf
LCD_TEMP, W
movwf
LCD_DATA
; Send data to LCD
bcf
LCD_CTRL, E
; LCD E-line Low
return
;=============================================================================
; LCD_CMND
; Sends command to LCD
; Required command must be in W
;=============================================================================
LCD_CMND
movwf
call
bcf
bcf
bsf
movf
movwf
bcf
return
LCD_TEMP
LCDBUSY
LCD_CTRL,RS
LCD_CTRL,RW
LCD_CTRL,E
LCD_TEMP, W
LCD_DATA
LCD_CTRL,E
;
;
;
;
Wait for LCD to be ready
Set LCD in read mode
Set LCD in command mode
LCD E-line High
; Send data to LCD
; LCD E-line Low
;=============================================================================
; LCDBUSY
; Returns when LCD busy-flag is inactive
; OK
;=============================================================================
LCDBUSY
bsf
STATUS,RP0
; Select Register page 1
movlw
0xFF
; Set PORTB for input
movwf
TRISB
bcf
STATUS, RP0
; Select Register page 0
bcf
LCD_CTRL, RS
; Set LCD for command mode
bsf
LCD_CTRL, RW
; Setup to read busy flag
bsf
LCD_CTRL, E
; LCD E-line High
movf
LCD_DATA, W
; Read busy flag + DDram address
bcf
LCD_CTRL, E
; LCD E-line Low
RDS Encoder Project
Hamed Haddadi
56
andlw
0x80
; Check Busy flag, High = Busy
btfss
STATUS, Z
goto
LCDBUSY
; Loop back if busy
bcf
LCD_CTRL, RW
bsf
STATUS, RP0
; Select Register page 1
movlw
0x00
movwf
TRISB
; Set PORTB for output
bcf
INTCON, RBIF
bcf
STATUS, RP0
; Select Register page 0
return
;*************************************************************************************
***********
;* SET_ADDR
*
;* sets the start address in LCD DDRAM for writing characters to the LCD
*
;* Load the lcd address you wish to write to into the w register before calling
routine
*
;*************************************************************************************
***********
SET_ADDR
iorlw
0x80
call
LCD_CMND
call
DELAY_125US
return
;combine address(a) in w to give 1aaa aaaa
;send byte in w to LCD data lines
;delay 125 microsecond
;***********************************************************************
; LONG_DELAY
; Uses a very long delay to allow the user to see the data on the LCD
;***********************************************************************
LONG_DELAY
movlw
0x4f
; Decimal value to give a long delay
movwf
CNT_DELAY3
rep_3
call
DELAY_30MS
decfsz CNT_DELAY3,1
goto
rep_3
return
;***********************************************************************
; SWITCH_DELAY
; Uses a long delay to allow the switch to over-come debounce problems
;***********************************************************************
SWITCH_DELAY
movlw
movwf
rep_4
call
decfsz
goto
return
0x20
CNT_DELAY3
DELAY_30MS
CNT_DELAY3,1
rep_4
; Decimal value to give a long delay
;*************************************************************************************
***********
;* DELAY_125US
*
;* uses repeated instruction cycles to create approximate 125 microsecond delay
*
;* using a 4Mhz clock on the pic.(42x3 cycles of 1us)
*
;*************************************************************************************
***********
DELAY_125US
movlw
US125
movwf
CNT_DELAY1
repeat decfsz CNT_DELAY1,1
cycle)
goto
repeat
return
; decimal value 42 loaded into w register
; move 42 into cnt_delay1 register
; decrease count by 1 and check if zero (1 instruction
; decfsz will skip this if count was zero
;*************************************************************************************
***********
;* DELAY_5ms
*
;* uses repeated instruction cycles to create approximate 5ms delay (39x130x1 cycle of
1us)
*
;* using a 4Mhz clock on the pic. (130 because 125+5 cycles from this routine)
*
;*************************************************************************************
***********
DELAY_5MS
movlw
movwf
MS5
CNT_DELAY2
RDS Encoder Project
;decimal value 39 loaded into w register
;move 39 into count2 register
Hamed Haddadi
57
rep2
call
DELAY_125US
cycle)
decfsz CNT_DELAY2,F
cycle)
goto
rep2
cycle)
return
;call routine for 125 microsecond delay(2 instruction
;decrease count2 by 1 and check if zero (1 instruction
;decfsz will skip this if count2 was zero(2 instruction
;*************************************************************************************
***********
;* END OF DELAY_5ms
*
;*************************************************************************************
***********
;*************************************************************************************
***********
;* DELAY_30ms
*
;* uses repeated instruction cycles to create approximate 30ms delay (231x130x1 cycle
of 1us) *
;* using a 4Mhz clock on the pic. (130 because 125+5 cycles from this routine)
*
;*************************************************************************************
***********
DELAY_30MS
movlw
movwf
rep_2
call
decfsz
cycle)
goto
return
MS30
CNT_DELAY2
DELAY_125US
CNT_DELAY2,1
;
;
;
;
decimal value 231 loaded into w register
move 240 into cnt_delay2 register
call routine for 125 microsecond delay
decrease count2 by 1 and check if zero (1 instruction
rep_2
; decfsz will skip this if count2 was zero
;=============================================================================
; LCD_CLEAR
; Clears display and returns cursor to home position (upper-left corner).
;
;=============================================================================
LCD_CLEAR
movlw
0x01
; Move the value for lcd clear command
call
LCD_CMND
retlw
0x00
END
RDS Encoder Project
Hamed Haddadi
58
B. Bi-Phase.asm
;**********************************************************************
;
*
;
Filename: biphase.asm
*
;
Date:
05/03/03
*
;
*
;
Author: hhaddadi
*
;**********************************************************************
;
*
;
Notes: To generate biphase symbols from port B
*
;**********************************************************************
list
p=16c622
#include <p16c622.inc>
__CONFIG
; list directive to define processor
; processor specific variable definitions
_CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _XT_OSC
;***** VARIABLE DEFINITIONS********************************************
CLK11875
EQU
1
CLK2375
EQU
2
RDS
EQU
3
PULSEHIGH
PULSEDOWN
EQU
EQU
4
6
US51
CNT_DELAY1
MEMORY
EQU
EQU
EQU
0x21
0x22
0x23
; value to give a 51 microsecond in delay loop
; temporary count register for 51us delay routine
;**********************************************************************
RESET
org
goto
0x00
MAIN
MAIN
clrf
bsf
clrf
clrf
bsf
movlw
movwf
STATUS
clrf
STATUS
call
call
call
call
call
call
call
call
call
call
call
call
call
call
call
call
call
call
call
call
poll11875
signal_pulse
DELAY_51US
DELAY_51US
DELAY_51US
DELAY_51US
DELAY_51US
DELAY_51US
DELAY_51US
DELAY_51US
poll2375
clear_pulse
DELAY_51US
DELAY_51US
DELAY_51US
DELAY_51US
DELAY_51US
DELAY_51US
DELAY_51US
DELAY_51US
goto
generate
STATUS,RP0
TRISA
TRISB
OPTION_REG,NOT_RBPU
0x0E
TRISB
; Do initialization, Select bank 0
; Select Bank 1
; Port A as output to save power
; PORT B is output
; Disable week Pull ups
; Declare pins 0&1 of
port B as
inputs
generate
; To by-pass the clock's high-signal
; To by-pass the clock's high-signa
poll11875
btfss
PORTB,CLK11875
goto
poll11875
return
signal_pulse
btfss
goto
goto
PORTB, RDS
PULSE_DOWN
PULSE_HIGH
poll2375
btfss
PORTB, CLK2375
goto
poll2375
return
clear_pulse
btfsc
RDS Encoder Project
MEMORY,0
Hamed Haddadi
59
goto
goto
PULSE_DOWN
PULSE_HIGH
PULSE_HIGH
bsf
PORTB, PULSEHIGH
call
DELAY_51US
bcf
PORTB, PULSEHIGH
bsf
MEMORY,0
return
PULSE_DOWN
bsf
PORTB, PULSEDOWN
call
DELAY_51US
bcf
PORTB, PULSEDOWN
bcf
MEMORY,0
return
;******************************************************************************
;* DELAY_51US
*
;* uses repeated instruction cycles to create approximate 51 microsecond delay*
;* using a 10Mhz clock on the pic.(42x3 cycles of 0.4us)
*
;******************************************************************************
DELAY_51US
movlw
US51
; decimal value 42 loaded into w register
movwf
CNT_DELAY1
; move 42 into cnt_delay1 register
repeat decfsz CNT_DELAY1,1
; decrease count by 1 and check if zero (1 instruction
cycle)
goto
repeat
; decfsz will skip this if count was zero
return
END
RDS Encoder Project
; directive 'end of program'
Hamed Haddadi
60
C. Data source PCB
RDS Encoder Project
Hamed Haddadi
61
D. Project time plan
RDS Encoder Project
Hamed Haddadi
62
9. References
1. United States RBDS Standard, April 9, 1998
2. www.microchip.com for MPLAB IDE use
3. Microchip PIC 16F87X Data Sheet
4. Microchip PICmicro Mid-Range MCU Family reference Manual
4. RDS: The Radio Data System: Dietmar Kopitz, Bev Marks
5. How to use intelligent LCDs: Julyan Ilet
6. Hitachi HD44780 LCD Controller/Driver manual
7. Microchip AN587 Interfacing PICmicro to an LCD module
8. TRIMOD LCD Specification
9. Microchip EEPROM Memory Programming specification
10. A Painless guide to CRC error detection algorithm: Ross Williams
11. Microchip AN730 CRC Generating and Checking
12. RDS Encoder Project: Tim Shaw (of EE)
13. RDS Encoder Project: Richard Koch (of EE)
14. HC-49 Quarts Crystal data sheet
15. AV Series Push Button Switches data sheet
16: Basic Communication Theory: John Pearson
17: CRC, Easier said than done: Michael Barr
18: www.farnell.co.uk
19: Electronic circuits III: Paul V Brennan, EEE
20: Digital Circuits: Chris Pitt, EEE
21: Microchip PIC16C622 datasheet
Author:
Hamed Haddadi, Department of Electronics & Electrical Engineering UCL, Torrington Place,
London WC1E 7JE
[email protected]
12 Lionel House, 370 Portobello Rd, London W10 5RP
RDS Encoder Project
Hamed Haddadi
[email protected]
63
10. Component datasheets
RDS Encoder Project
Hamed Haddadi
64
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertisement