Description
1. Introduction
In this assignment, you are required to write application/driver programs to generate sound using a buzzer
controlled by 4 buttons.
A buzzer has been physically connected with a Pulse Width Modulation (PWM) timer. By controlling the
PWM timer, we can produce different pulse waveforms (a series of 0-1 digits with a fixed pattern) that
can generate different sound effects via the buzzer. A pulse waveform is decided by two factors: (1) The
frequency that is the number of occurrences of a pulse wave (with fixed pattern) per second; (2) The
duty cycle that is the percentage of one period in which the signal is active (the value is 1). In other words,
the duty cycle is used to determine the pattern of a pulse wave, while the frequency is used to decide how
frequently we repeat this pattern. So you need to develop a device driver for the PWM timer so
application programs can turn on/off the buzzer and set up sound frequency accordingly.
Buttons are used by application programs to achieve the above operations. You also need to extend the
button device driver to make it be able to control 4 buttons (a device driver that can control 8 buttons is
provided for your reference, see button-led.zip). Basically, you can utilize GPH2(0), GPH2(1), GPH2(2)
and GPH2(3) that have been connected with four buttons. Write an application program so when a button
is pushed, the following functions can be implemented:
Button GPH2(0) GPH2(1) GPH2(2) GPH2(3)
Buzzer/PWM On/1000Hz On/1200Hz On/1400Hz Off
As shown above, you are required to use the buttons to control the sound of the PWM/Buzzer module.
For example, when the GPH2(0) button is pushed, let the buzzer sound with a frequency of 1000Hz;
when the button GPH2(3) is pushed, let the buzzer off.
2. Device Driver Development of PWM/Buzzer
(1) How to control the buzzer
Basically you need to set up GPD0 register (including a control register and a data register) in the device
driver, so a user program can let the buzzer make noise or stop.
Control register
Data register
The four bits of register GPD0CON ([3:0]) are used to control the work mode of the buzzer. The buzzer
can work in several modes (e.g., Input, Output, TOUT_1 …). To turn the buzzer on/off, one simple way
is to configure its control register as the Output mode (0001), and set 1 or 0 in its data register, namely,
GPD0DAT (1 is on and 0 is off).
There are not macro functions to help us configure registers. So we need to configure registers by
ourselves. For your reference, some sample code is provided as follows:
1) As physical memory addresses cannot be accessed directly, use the kernel function, ioremap, to
allocate a virtual address for the physical address of the register:
static void *ZL_GPD0_CON_ADDR;
ZL_GPD0_CON_ADDR = ioremap(0xE2000A0, 0x00000004);
2) Read the data stored in the address (the I/O register’s value) with the kernel function, readl:
unsigned int data;
data = readl(ZL_GPD0_CON_ADDR);
3) Set up the value of the data according to the requirement and using the kernel fuction, writel,
writes back to the address:
data = …; // change the value of the register according to the requirement
writel(data, ZL_GPD0_CON_ADDR);
For details, please check the sample driver/application programs in buzzer.zip, in which a buzzer driver
and an application program have been provided.
To let the buzzer generate sound, you need to use the PWM module to control the frequency and duty
cycle of the input pulse of the buzzer. As the buzzer has been physically connected with the PWM
timer0, the buzzer should be set up in the T_OUT0 (0010) mode in GPD0CON[0].
(2) How to control the PWM
The S5PV210 has five 32-bit Pulse Width Modulation (PWM) timers. These timers generate internal
interrupts for the ARM subsystem. In addition, Timers 0, 1, 2 and 3 include a PWM function, which
drives an external I/O signal. The output of PWM timer0 is connected to the buzzer.
As mentioned above, to play sound, we need to set up the sound frequency and the duty cycle. To
generate the pulse waveform with a given sound frequency (from application programs), we need to set
up several registers including TCFG0, TCFG1, and TCNTB0.
8BIT
PRESCALER
PCLK DIVIDER
1/2/4/6/8/16
Control
Logic PRE/DIV Feq
TCFG0 TCFG1 TCNTB0 TCMPB0
Buzzer GPD0CON GPD0DAT
T_OUT1
Default value 65
Default value 16 TCON
Fig. 1: The working process of the PWM/Buzzer module
As shown in Fig. 1, the timer uses PCLK as the source clock, and PRE/DIV Feq is the timer input
frequency obtained by
PRE/DIV Feq = PCLK / (PRESCALER value + 1) / (DIVIDER value)
where PRESCALER value can be obtained from TCFG0 (its initial value should be set as 65),
DIVIDER value can be obtained from TCFG1 (its initial value should be set as 16), and PCLK can be
obtained by the following program segment:
unsigned long pclk;
struct clk *clk_p;
clk_p = clk_get(NULL, “pclk”)
pclk = clk_get_rate(clk_p);
In order to generate the given sound frequency F, we then need to set up the value in TCNTB0 that will
be loaded into the a “down” counter (used to count how many times we need in order to achieve the
frequency F with the input frequency PRE/DIV Freq). The value of TCNTB0 should be the result of
dividing the cycle period of the sound by the cycle period of the input clock, i.e.,
(1/F) / (1/ PRE/DIV Freq)
The duty cycle is determined by TCMPB0, and is equal to TCMPB0/TCNTB0. So if TCMPB0 =
TCNTB0 /2, then the duty cycle is 50% (that is the value you should use in the development).
After TCFG0, TCFG1, TCNTB0 and TCMPB0 have been set up, we can turn on the PWM module by
setting up its control register, namely, TCON. Basically, we should let PWM Timer0 work in “AutoReload Mode” with “dead zone generator disable”. Please check the table attached blow for details.
Next, please find all registers you need to set up in order to control the PWM model. Note that we only
use PWM timer0.
Note: Prescaler 0 should be set up as 65
Note: Divider MUX0 should be set up as “0100”
Note: Timer 0 Count Buffer should be set up as (1/F) /(1/ PRE/DIV Freq)
Note: Timer 0 Compare Register should be set up as TCNTB0/2
Note: Dead Zone Generator should be “disable” (its value shoud be 0), Time0 Auto Reload should be
“on” (its value should be 1); Timer 0 Output Inverter should be “off” (its value should be 0); Timer 0
Manual Update should be “0”.
What to submit: A zip file that contains:
1) The source code for the device driver and the application program. (90 marks)
2) A report (with screen snapshots) for how you compile your program, how you create files
(if there is any), and how you test it. (10 marks)