2 Software Design Considerations

Total Page:16

File Type:pdf, Size:1020Kb

2 Software Design Considerations

1 Introduction

The objective of this project is to construct a version of the popular game Laser

Tag. In order to accomplish this, it has to be possible to send and receive an IR signal from one unit to another. To transmit other data that cannot be sent over a simple narrow

IR beam, a disperse RF signal will be sent and received by the guns. Furthermore it is also necessary to provide feed back to the players. This will be done through a sound chip/speaker, an LCD readout, LEDs and vibrating motors. In order to connect all of these elements into a functional game, a decent microcontroller with proper imbedded software is also required.

2 Software Design Considerations

2.1 Memory Models

The microcontroller being used for this project is an Atmel ATmega16L. It has

16 kilobytes of on chip programmable flash memory. This memory is non-volatile and will be the place where the majority of the programming code and constants will be stored. In addition to this, the Atmel has 512 bytes of EEPROM for non-volatile variables and 1 kilobyte of SRAM for volatile variables. Due to the nature of the project, there is no real need for non-volatile variables but as with most software, there is a need for runtime variables. For this reason the EEPROM will be essentially unused and the

SRAM will be used to store all of the variables.

2.2 memory sections/mappings Because the code for this project is written in C and compiled into assembly by the Codevision AVR tool provided by Atmel, the majority of the details concerning the way that the memory is mapped into the microcontroller are essentially abstracted away.

That said the basic structure of the memory mapping is given in the data sheet (2). One thing that is says is that the flash memory is organized in to a hexadecimal vector that runs from 0x0000 to 0x1FFF. In this vector, the application code generally starts at

0x0000 and progresses forward. The bootstrap code on the other hand is at the very end of the vector. This is setup to avoid conflicts between the main application code and the boot loader.

2.3 startup code

One of the best things about the Atmel is the integrated development environment that is provided by the manufacture. Not only does this IDE allow a software architect to program in C but it also has built in code generation routines for generating and configuring the bootstrap program (1). Though this does a lot of things, like setup the skeleton for the interrupts being used and assign the proper values to the timers, it does not do things like initialize global variables that are used by the application code. This had to be done manually.

2.4 Application code organization

The application code for this project is organized in a command-driven manner.

That is to say that it is partially controlled by a polled program and partially controlled by interrupts. This is because some elements of this code, such as the IR transmission, are based on signals that are much slower than the speed that the microcontroller runs. If these elements were to be put into the main loop, they would essentially monopolize the

CPU. If this were to happen, other portions of the code would be neglected.

3 Software Narrative

3.1 Main Programming Loop (see flow chart 1)

3.1.1 Trigger Button:

This checks to see if the trigger is currently being depressed. If it is being

depressed, the program goes on to check whether or not the shot has already been

fired. If it is not being depressed, the program goes on to check whether or no the

clip button is being depressed.

3.1.2 Shot Fired:

This checks to see if the trigger is still being depressed after the gun has

fired. If the gun has already fired, the program skips ahead to check whether or

not the clip button is being depressed; otherwise the program checks the ammo

count to see if the clip is empty.

3.1.3 Clip Empty:

This checks to see if the ammo count is at zero. If it is, the program

moves on to check the clip button, otherwise the gun proceeds to fire the IR beam.

3.1.4 Fire Shot:

At this point the gun is set to fire it’s IR beam. Depending on which team

the player is on, the gun will either fire a 1 kHz signal modulated on 38 kHz

carrier or a 650 Hz signal also modulated on a 38 kHz signal. This is done by using an interrupt service routine on timer 0 to toggle TCCR2. Since OCR2 is kept constant at 105, it is continuously producing a 38 kHz carrier. The ISR used to accomplish this can be seen in Flow Chart 3. After the gun fires 50 pulses it goes on to update the ammo status.

3.1.5 Update ammo count (decrement):

At this stage, the gun goes on to decrement the ammo in the gun by one.

The ammo counter is an integer variable that is stored in the global scope. Once this is done, the program proceeds to update the LCD read out.

3.1.6 Update ammo LCD

At this point, the LCD is updated to display the new value of the ammo counter. Once this is done, the program goes on to check the clip button.

3.1.7 Clip Button:

At this junction, the program checks to see if the clip button is being depressed. If it is, the program goes into a 2 second delay. If it is not, the program goes on to check the team button.

3.1.8 Delay 2 Seconds:

This is a 2 second delay that occurs every time the clip button is pressed.

This is intended to simulate the time that it would actually take to change a clip.

Furthermore, since the hit detection is controlled through interrupts, the person changing their clip is still vulnerable during this 2 second period as would be the case in a real combat situation. Once this step is done, the gun goes on to update the ammo variable.

3.1.9 Update ammo count (Maximum): At this point, the program sets the ammo counter to 30, which is the maximum ammo the gun can have at any given time. Once this is done, the routine to update the ammo count on the LCD readout is called.

3.1.10 Update ammo LCD:

At this point, the LCD is updated to display the new value of the ammo counter. This is the same routine that is called after the ammo is decremented but it is followed by a different block because the main loop is at a different execution point. After the LCD readout is refreshed, the program goes on to check the team button.

3.1.11 Team Button:

At this stage, the program checks to see if the team button is being depressed. If it is, the program goes on to check if the team has already been changed since the button was depressed. If it is not, the program goes back to the beginning of the main loop and checks the trigger.

3.1.12 Already Done:

This is a check to see if the person simply held onto the team change button for too long. If so, the program goes back to the beginning of the main loop and checks the trigger again. Otherwise it proceeds to change the team that the player is on.

3.1.13 Change Team Frequency:

In this stage of execution, OCR0 is either changed from 0x40 to 0x60 or vise-versa. This changes the amount of time between when counter 0 toggles timer 2’s output on or off, essentially changing the frequency at which the signal

will be sent. After this is done, the LCD is updated with the new team name.

3.1.14 Update Team Name

In this subroutine, the LCD either changes the Team column from “Team

1” to “Team 2” or vise-versa. In order to be a little more efficient with space all

that is really changed is the number. The string constant “Team” is used for both

readouts. This is the last possible stage in the main while loop. After this

command goes through, the program goes back to check the trigger.

3.2 Hit Detection (see flow chart 2)

3.2.1 Idle till next pulse:

In this state, the hit detection code isn’t even active. Once a hit occurs, an

interrupt is thrown and the program execution stops whatever it is doing and

jumps to the processed starting at “Pulse detected”.

3.2.2 Pulse Detected

Since the noise suppression is active, this stage can only be reached if a

pulse has been detected for 4 cycles, thus, the odds that the signal is composed of

random noise is very unlikely.

3.2.3 Save Time Stamp

When a pulse is detected on the timer 1 input capture port, the value is

automatically saved into the ICP1 register. However the next pulse that comes in

will wipe it out. In order to gauge the frequency of the incoming signal this value

needs to be saved. That is why at this point the ICP1 register is dumped into an

integer variable in the global scope but not before that integer is dumped into a different integer variable in the global scope. After this is done, the program moves on to see if enough pulses have been detected in order to constitute a hit.

3.2.4 Counter @ 30:

At this point, the program check to see if the requisite 30 pulses that are required to constitute a hit have been detected. If 30 pulses have not been detected yet, the program returns from the interrupt into its normal execution mode. If the 30 pulses have been detected, the program registers a hit and goes on to calculate the frequency of the gun that the player was hit by.

3.2.5 Calculate frequency:

Because the time stamps of the 2 most recent pulses have both been saved into integer values, the frequency of the gun that fired them can easily be calculated. After this is done, the program goes on to update the health counter.

3.2.6 Update Health Counter:

Like ammo, the value for the remaining health is stored in an integer variable in the global scope. Once a hit has been detected, the stored value will be decremented by one. After this happens, the program moves ahead to update the health value output to the LCD.

3.2.7 Update LCD health bar:

Unlike ammo, which is shown as an integer on the LCD readout, the player’s health is shown as a series of pipe characters. When a player loses a health point, one of the pipe characters is taken away until the bar has been completely depleted. After this update has been made, another update to a different part of the LCD readout takes place. 3.2.8 Update LCD Message:

Using the frequency calculated in step 3.2.5, the message column of the

LCD readout, is refreshed to show who the player was hit by. After this is done,

the program checks to see if the player was finished off by the hit that just

occurred.

3.2.9 Health Finished

At this step, the program checks to see if the player’s life has been

knocked down to zero. If it has not been, the program simply resumes its normal

course. If the player was killed by the last hit, the program proceeds to send out a

fallen player signal over the RF line.

3.2.10 Send death signal over USART

At this stage, the USART is activated and a death signal is sent out to all

other players in the vicinity. After this signal is sent, the program resumes normal

operation.

3.3 Other Interrupt Routines (see flow chart 3)

These are two simple ISRs that do not fit into any other place in the flow of control. The places that they are generated in have already been mentioned in 3.1.4 and

3.2.9. 4 Software Documentation

4.1 Flowcharts

Main Loop (flow chart 1) Fire Shot Trigge Shot Clip r Fired Empty Butto n

Update ammo count: dec Delay 2 Update Update Clip Butto seconds ammo ammo LCD n count: Max Update ammo LCD

Change Update Team Alrea Butto dy team freq. Team name n done LCD

Is a is a ‘1’ ‘2’ Check presen presen for RF t t

Update Update death 1 death 2 LCD LCD Hit Detection (Flow Chart 2)

Pulse detected

Save timestamp

Idle till Calculate Update Next Count Pulse er @ frequency health 30 counter

Update Update Health finish LCD LCD ed Message health bar

Check trigger Other Interrupt Routines (Flow Chart 3)

Idle till Timer 0 compare match

Set TCCR2 Set TCCR2 Check to 0x19 TCCR to 0x00 2

4.2 References

1. Automatic code generation routines from Atmel’s Codevision AVR toolkit

were used in the programming of this project.

2. Atmel ATmega16L data sheet:

http://www.atmel.com/dyn/resources/prod_documents/doc2466.pdf

Recommended publications