User Tools

Site Tools


milestone_3_task_2

This is an old revision of the document!


Milestone 3, Task 2: Implement the State Machines

Overview

In this task you will implement several state machines and test each of them separately to verify correct operation. You will be guided how to “connect” the state machines as needed later in this task and the next. See the system diagram below to see how the state machines will ultimately work together. You can ignore the “red” connections to the jumper block for now. Click the image to see a full-size version.

State Machines

  1. transmitter state machine: This state machine generates the square wave for each of the 10 specific frequencies.
  2. trigger state machine: this machine debounces the gun-trigger and activates the transmitter state machine.
  3. hitLedTimer state machine: this state machine lights up the hit-indication LED on the gun for 1/2 second each time a hit is detected.
  4. lockoutTimer state machine: this state machine provides a lock-out period used to ensure that you detect only one “hit” for each trigger firing by your opponent. Moreover, this approach ensures that you only detect a hit from one opponent at a time. Thus if you are simultaneously fired upon and actually “hit” by two different players, you only report the first detected “hit”.

General Requirements

  1. All functionality must be implemented as state machines using the techniques that were taught during ECEn 330. Please review the required approach for implementing and debugging state machines. Part of your grade will be derived from the quality of your code and your ability to follow these guidelines.
  2. Completely follow the specifications for each state machine.
  3. Call state machine init() functions from inside isr_init().
  4. All tick() functions may only be called from inside the isr_function(). They may not be called from anywhere else.
  5. You must follow the software coding standard. Exception: clang-format is not required. Ignore any clang-format rules.

General Notes

  • Assume a “tick” rate of 100 kHz for all state machines when making any assumptions about timing.
  • For this project, implement isr_init() and isr_function() in isr.c. The isr.h header file is included in the ecen390 project directory.
  • Interval timer 0 is used to measure cumulative time spent in the interrupt service routine. You cannot use it for anything else. However, interval timers 1 and 2 are available for your use.
  • In the next task, the provided code will use all of the interval timers so, if you use them now, remember to disable any code that uses the interval timers for the next task (Task 3).

Warnings

  1. Do not use any types other than integer types (uint16_t, uint32_t, int16_t, etc.) in any of the state machines. DO NOT USE ANY FLOATING TYPES SUCH AS float or double! The interrupt-service routine cannot handle them. If you use them in your state machines, you will likely see very strange behavior in your system.

Important Numbers

  1. Transmitter Frequencies: Use the tick counts that were provided in filter.h
  2. System “Tick” Rate: 100 kHz.
  3. Detector Lock Out Time: 1/2 second.
  4. Transmitter Waveform Length: 200 ms.

Resources

Pin Mapping Between ZYBO Header Pins and the Carrier Board

These mappings are noted on the carrier board (see the image above), but they are repeated here for convenience. Test pins have been added for some signals on the carrier board to make probing a bit easier.

  • JF-3 → Hit Detected
  • JF-2 → Trigger
  • JF-1 → Transmitter
  • JA-1 → ADC In +
  • JA-7 → ADC IN -

The MIO package pins on the processor map to the JF header on the ZYBO board. More details are available in the MIO section.


Source Code

Note that the following files are provided in your ecen390 project directory. Refer to the comments above each function for more details.

  • drivers/buttons.h
  • drivers/switches.h
  • include/leds.h
  • lasertag/main.c
  • lasertag/transmitter.h
  • lasertag/trigger.h
  • lasertag/hitLedTimer.h
  • lasertag/lockoutTimer.h
  • lasertag/isr.h

You are expected to create and implement the following files. See the provided header files (.h) for a description of each function.

  • lasertag/transmitter.c
  • lasertag/trigger.c
  • lasertag/hitLedTimer.c
  • lasertag/lockoutTimer.c
  • lasertag/isr.c

Specifications

Transmitter State Machine

  • The transmitter state machine generates a square-wave waveform by driving a sequence of '1's and '0's onto the JF-1 pin of the ZYBO board. For instructions on accessing pin JF-1, see the section on MIO. JF-1 is connected to the “Transmitter” header pin. You will ultimately connect the gun's LED to the “Transmitter” pin.
  • Each time the transmitter state machine is activated with a call to transmitter_run(), it must generate the waveform for 200 ms.
  • The transmitter state machine must be able to generate the 10 frequencies shown in the filter.h file that you downloaded previously.
  • You set the waveform frequency with: transmitter_setFrequencyNumber(uint16_t frequencyNumber).
  • Minimum frequency is selected when frequencyNumber = 0, maximum frequency is selected when frequencyNumber = 9.
  • All waveforms must be 50% duty cycle.
  • You will set the waveform frequency by reading the ZYBO slide switches in a function called from main() and then calling transmitter_setFrequencyNumber(). Do not read the slide switches in the transmitter state machine.
  • Include the file “filter.h” so that you can have access to the frequency tick counts that are provided there. If you need half-period counts for your state machine, you can divide the values by 2.
  • The state machine must ensure that JF-1 is a '0' when inactive. Otherwise you will drain the battery because the gun's “shoot” LED will constantly illuminate.
  • Only send a single '1' or '0' to JF-1 when the waveform transitions from '1' to '0' or vice versa. Don't continually write a '1' or '0' to JF-1; just update the pin when the waveform transitions. Otherwise, your state machine may require too much CPU time. This sounds like a good use of a Mealy action :-).
  • In non-continuous mode (the default), the state machine must ignore requests to change the frequency while it is generating the waveform for 200 ms. The state machine should only change frequencies when it is inactive or after it has completed transmitting the waveform for 200 ms.
  • In continuous mode, the state machine repeatedly generates the waveform. When a 200 ms burst is finished in continuous mode, another burst is immediately started without waiting for another call to transmitter_run(). The transmitter will only respond to a frequency change in between 200 ms bursts based on the last call to transmitter_setFrequencyNumber().
  • The transmitter state machine must be capable of running in continuous mode (see transmitter.h).
  • transmitter_tick() must be invoked in isr_function(). If it is not, pass-off points will be subtracted.
  • You will connect an oscilloscope probe to the “Transmitter Probe” pin to display the output of the transmitter for debug and pass off.

Trigger State Machine

  • The trigger state machine must debounce both the press and the release of the gun trigger (see Debouncing Switches).
  • You read the current logic value of the trigger from pin JF-2 (MIO pin 10) which is connected to the “Trigger” on the development board. You will ultimately connect the gun's trigger to the “Trigger” pin. You can ignore the “Trigger” pin for now.
  • Push-button BTN0 will also function as a trigger, i.e., when you press BTN0, everything will operate just as if the gun were attached and the trigger was pulled (see Using BTN0 as a Trigger).
  • Tie the trigger state machine to the transmitter. A trigger pull will invoke transmitter_run().
  • The trigger state machine activates the transmitter state machine after the press of the trigger has been debounced.
  • The trigger state machine will not recognize another press of the trigger until the trigger has been released and debounced.
  • Each press/release of the trigger must activate the transmitter state machine only once.
  • trigger_tick() must be invoked in isr_function() and nowhere else. Pass-off points will be subtracted if trigger_tick() is invoked anywhere else.

Hit LED Timer State Machine

  • The hit-indicator LEDs must illuminate for 1/2 second when activated.
  • Use the JF-3 output pin to indicate a laser tag hit. This signal will eventually control an LED mounted on the laser tag gun which will provide feedback when you are hit by an opponent. JF-3 is routed to a connector on the development board and is labeled “Hit Detected”.
  • Since a gun is not yet attached to your system, use LED1 on the development board to debug and pass off the state machine. LED1 is connected to JF-3.
  • Concurrently illuminate LED LD0 (directly above slide-switch 0) on the ZYBO board when you signal a hit on JF-3 (this helps greatly during testing). See include/leds.h to find a function that will control the on-board LEDs.
  • hitLedTimer_tick() must be invoked in isr_function(). Pass off is not allowed if hitLedTimer_tick() is invoked anywhere else.


Lockout Timer State Machine

  • Lockout timer state machine is a simple timer.
  • The time interval for the lockout is 1/2 second.
  • lockoutTimer_tick() must be invoked in isr_function(). Pass-off points will be subtracted if it is invoked anywhere else.

Implementation Details

Debouncing Switches

Mechanical switches are imperfect. When pushed or released they often “bounce” between closed and open states for a short period of time (10 milliseconds or so). For example, assume that a push-button is wired such that it is read as a '1' when pressed and read as a '0' when released. If you continually read the switch when it is first pressed, you may read the switch initially as a '1' but then a few milliseconds later, read it as '0', then '1', then '0' and so forth. This process may repeat itself a few times until the output of the switch becomes completely stable. When a switch quickly changes values this way when it is initially pressed (or released), we say that the switch “bounces”.

Switch bouncing is problematic for us because we want our system to run reliably in single-shot mode, delivering exactly one shot for each press/release of the trigger. The easiest way to debounce a switch for us is to use a state machine that, in turn, uses a delay to determine when the switch has stopped bouncing. Here is a simple algorithm you can implement in a state machine and use to detect when a switch has stopped bouncing. It assumes that it will take no longer than 50 ms for the switch to stop bouncing. This is a reasonable assumption for a switch that is in good working order.

  • Step 1: Wait until you detect a press of the button.
  • Step 2: Once you detect the press of the button, start a counter that expires at 50 ms.
  • Step 3: If the button changes value before the counter expires, reset the counter and go back to Step 1.
  • Step 4: If the counter expires before the switch changes value, you can assume that the switch is debounced.

Note that you need to use this process for both the press and release of the switch or push-button.


Accessing External Pins via MIO

You access external pins on the JF PMOD connector via the MIO package. By using the functions in this package, you can designate specific pins as inputs and outputs, read input pins, drive values onto output pins and so forth. Here are some guidelines on how to use the mio package. Also, you can learn a lot about how mio works by reading the header file (include/mio.h).

  • First, make sure to invoke mio_init() before using any of the functions.
  • Read the comments in mio.h as these are pretty self-explanatory.
  • Use the mio pin numbers in all mio functions. Don't use the ZYBO PMOD numbers. For example, JF-1 refers to Pin 1 on the JF PMOD connector. However, it corresponds to mio pin-number 13. The code below shows how to set up and use the correct mio pin that connects to Pin 1 on the JF PMOD (JF-1). Note that the provided code is just an example of how to use some of the mio functions.

Here is some example code that you can use to setup the JF-1 pin and to set values on its output. These are just examples, you will need to do more than just what is shown below.

#include "mio.h"
#define TRANSMITTER_OUTPUT_PIN 13
#define TRANSMITTER_HIGH_VALUE 1
#define TRANSMITTER_LOW_VALUE 0
 
void transmitter_init() {
  mio_init(false);  // false disables any debug printing if there is a system failure during init.
  mio_setPinAsOutput(TRANSMITTER_OUTPUT_PIN);  // Configure the signal direction of the pin to be an output.
  // Other stuff...
}
 
void transmitter_set_jf1_to_one() {
  mio_writePin(TRANSMITTER_OUTPUT_PIN, TRANSMITTER_HIGH_VALUE); // Write a '1' to JF-1.
}

A full pin-mapping between the JF PMOD and the mio pins is given below (this is just a copy and paste from mio.c).

// The MIO system is the PS GPIO that communicates with the MIO pins on the ZYBO board.
// MIO pins: 13, 10, 11, 12, 0, 9, 14, 15 are connected to JF pins: 1, 2, 3, 4, 7, 8, 9, 10.

Using BTN0 as a Trigger

For testing purposes and for general convenience, you must be able to “fire” the transmitter using either the trigger on the gun or BTN0 on the ZYBO board. Here's a good way to do that.

In general, it is always a good idea to “wrap up” or encapsulate behavior inside functions. For example, in the trigger state machine, I need to know when the trigger is pressed, but I don't necessarily need to know “what” was pressed, e.g., either the gun trigger or the push-button, BTN0. Here is a simple example from my code that shows how I did it. You may also want to take a similar approach.

In the code below, I have written a function called triggerPressed() that returns '1' (true) whenever the trigger is pressed. As you can see, I take the OR of the gun-trigger and the push-buttons. The nice thing about this approach, is that I can say something like: if (triggerPressed())… in my state machine code and I have something that is very readable and understandable. However, if I decide to change the triggerPressed() code for some reason, I don't have to make any changes to my state machine. Note: see the discussion directly below that explains the ignoreGunInput variable.

// Trigger can be activated by either btn0 or the external gun that is attached to TRIGGER_GUN_TRIGGER_MIO_PIN
// Gun input is ignored if the gun-input is high when the init() function is invoked.
bool triggerPressed() {
	return ((!ignoreGunInput & (mio_readPin(TRIGGER_GUN_TRIGGER_MIO_PIN) == GUN_TRIGGER_PRESSED)) || 
                (buttons_read() & BUTTONS_BTN0_MASK));
}

During trigger_init() (this gets called as soon as main() starts to execute), I check to see if the “trigger” is currently pressed. If it is, I presume that the gun cable is not connected as pins “float” to a high logic value when they are left unconnected. Otherwise, the OR of the push-button and the actual gun-trigger will always evaluate to '1' when you run the program with the gun-cable unconnected. Note that the variable ignoreGunInput is a static bool variable that initialized to 0 (false). This allows me to perform all of my testing with the BTN0 pushbutton but also allows me to test with the gun. I just have to make sure that the gun is connected when I start or download the program and then I can use either the gun-trigger or BTN0.

// Configure the trigger-pin as an input.
// Ignore the gun if the trigger is high at init (means that it is not connected).
void trigger_init() {
  mio_setPinAsInput(TRIGGER_GUN_TRIGGER_MIO_PIN);
  // If the trigger is pressed when trigger_init() is called, assume that the gun is not connected and ignore it.
  if (triggerPressed()) {
    ignoreGunInput = true;
  }
}

Source Code to Enable Interrupts

#include "interrupts.h"
 
int main() {
  ...
  isr_init(); // Calls state machine init functions
 
  interrupts_initAll(true); // Initializes but does not start interrupts.
  interrupts_enableTimerGlobalInts(); // Enable interrupts at the timer.
  interrupts_startArmPrivateTimer();  // Start the private ARM timer running.
  interrupts_enableArmInts(); // ARM will now see interrupts after this.
  // Default interrupt frequency is 100 kHz.
}

Where do I Put My Tick Functions?

In your laser-tag system there are two kinds of code: timing-aware code and non-timing-aware code. Examples of non-timing-aware code include: all of your filtering functions, the code that computes power, etc. The functions that implement filtering, power-computation, etc., need not know anything about elapsed time. These functions simply accept numerical input and compute values.

Examples of timing-aware code include all of your state machines: transmitter, trigger, hitLedTimer, and lockoutTimer. To work correctly, the tick() functions for each of these state machines must be executed at a precise rate. Otherwise, it would be impossible for the transmitter state machine to generate the transmitter outputs at the desired frequency or for the hitLed-timer and lockout-timer to precisely time intervals, for example.

As the laser tag system is currently structured, there are essentially two places where you can insert any of your code: inside (or called from) main(), or inside isr_function(). Precise, timing-critical functions such as the “tick” functions for your state machines go inside isr_function(). See the code-snippet for isr_function() below. Note that the invocation order of your “tick” functions does not matter unless you have bugs in your code.

isr_function() is guaranteed to be precisely invoked at 100 kHz, or 100,000 times per second. When it is time for this function to execute, the CPU stops whatever else it is doing, executes isr_function() and the quickly returns back to whatever else it was doing. You can assume that any functions that are invoked in the body of isr_function() are guaranteed to execute at the 100 kHz rate.

Note: It is critical that any functions that you insert into isr_function() execute very quickly or timer interrupts will be missed. You should verify (using the interval_timer package, for example) that the functions that you put inside isr_function() collectively complete execution in much less time than 1 period of 100 kHz. If the total execution time of all of your functions exceeds the period, you will miss timer interrupts and introduce noise and jitter into your system. Actually, if you consume too much time in isr_function there won't be any time to run your filters. Be careful here.

void isr_init() {
  // Insert initialization code (e.g. state machine init functions) here.
}
 
void isr_function() {
  // Insert timing-critical code (e.g. state machine tick functions) here.
}

Keyword volatile

As a recommendation, declare all of your state machine global variables volatile, even the current state variable. Otherwise, you will need to analyze each of your global variables for the condition explained below to see if they need to be volatile. This condition potentially applies to all state machine global variables (uint32_t, etc.), not just boolean variables.

In some cases it is necessary to add the keyword volatile to a variable declaration. Consider an example with the hitLedTimer state machine. The variable timerStartFlag, when set to true, starts the hitLedTimer state machine. Later, when the state machine is finished, it will set timerStartFlag to false. In the partial example shown below, you can see that the keyword, volatile has been added to the declaration for the variable, timerStartFlag.

// When true, the timer starts running.
volatile static bool timerStartFlag = false;
 
void hitLedTimer_start() {
  timerStartFlag = true;
}

The volatile keyword essentially tells the compiler to avoid optimizing code that accesses this variable. Here is the principle at work. Specifically, if a variable is written to by a function called from isr_function() (e.g., your tick functions), and that same variable is read by a function called from main(), you must use the volatile keyword in the declaration for that variable. The volatile keyword informs the compiler that it should not attempt to optimize read access to the variable.


Macros for Debug and Pass off

The following DPRINTF macro is a helpful alternative to the normal printf function call since it can be switched off by making sure DEBUG is not defined. If you have many DPRINTFs sprinkled throughout your code, you can turn them all off at once while still leaving them in your code for later use.

The DPCHAR macro is a low-overhead way to print a character to the console and is useful for passing off the trigger state machine. The macros can be left in the code for later test and debug, but all of them can be disabled when running under normal use by not having DEBUG defined (commended out).

Place the following code in your .c file near the top, but below other #include lines.

// Uncomment for debug prints
// #define DEBUG
 
#if defined(DEBUG)
#include <stdio.h>
#include "xil_printf.h"
#define DPRINTF(...) printf(__VA_ARGS__)
#define DPCHAR(ch) outbyte(ch)
#else
#define DPRINTF(...)
#define DPCHAR(ch)
#endif

Note: When hardware interrupts are enabled, make sure debug prints called from your state machines are not enabled. Otherwise, you will get interrupt overruns and unusual behavior. The only exception is when DPCHAR() is selectively used (e.g. when passing off your trigger state machine).

For more ideas on getting visibility into the operation of your code, here's a link to a page describing how to debug state machines.


Developing the Transmitter State Machine

It may be easier to test/develop the transmitter state machine without using interrupts. Here is one approach I would suggest.

  1. Use a while-loop with the utils_msDelay() function to provide a slow test period. 10 ms should provide enough time for reasonable debug prints.
  2. Use a transmitter_statePrint() function to print out states of the state machine as you transition.
  3. Print out the values that would be appearing on the pins. Use a printf() to achieve this.

Here is a test-function that I used with my own code. You would need to either modify this code or add a transmitter_enableTestMode() function to your transmitter code. In my case, transmitter_enableTestMode() turns on my debug prints and shortens my waveform to 200 so I don't have to wade through too much output. During normal operation, I don't use this test mode.

Once you have verified that your transmitter state machine is working properly, you can disable the test mode, put the transmitter_tick() function into isr_function() and verify proper operation with an oscilloscope.

// Prints out the clock waveform to stdio. Terminates when BTN1 is pressed.
// Prints out one line of 1s and 0s that represent one period of the clock signal, in terms of ticks.
#define TRANSMITTER_TEST_TICK_PERIOD_IN_MS 10
#define BOUNCE_DELAY 5
void transmitter_runTest() {
  printf("starting transmitter_runTest()\n");
  mio_init(false);
  buttons_init();                                         // Using buttons
  switches_init();                                        // and switches.
  transmitter_init();                                     // init the transmitter.
  transmitter_enableTestMode();                           // Prints diagnostics to stdio.
  while (!(buttons_read() & BUTTONS_BTN1_MASK)) {         // Run continuously until BTN1 is pressed.
    uint16_t switchValue = switches_read() % FILTER_FREQUENCY_COUNT;  // Compute a safe number from the switches.
    transmitter_setFrequencyNumber(switchValue);          // set the frequency number based upon switch value.
    transmitter_run();                                    // Start the transmitter.
    while (transmitter_running()) {                       // Keep ticking until it is done.
      transmitter_tick();                                 // tick.
      utils_msDelay(TRANSMITTER_TEST_TICK_PERIOD_IN_MS);  // short delay between ticks.
    }
    printf("completed one test period.\n");
  }
  transmitter_disableTestMode();
  do {utils_msDelay(BOUNCE_DELAY);} while (buttons_read());
  printf("exiting transmitter_runTest()\n");
}

My printed console output looks as follows (the printed output changes depending upon the current switch value).

starting transmitter_runTest()
init_st
wait_for_startFlag_st
output_low_st
0000000000000000000000000000000000
output_high_st
1111111111111111111111111111111111
output_low_st
0000000000000000000000000000000000
output_high_st
1111111111111111111111111111111111
output_low_st
0000000000000000000000000000000000
output_high_st
1111111111111111111111111111111111
completed one test period.
wait_for_startFlag_st
output_low_st
0000000000000
output_high_st
1111111111111
output_low_st
0000000000000
output_high_st
1111111111111
output_low_st
0000000000000
output_high_st
1111111111111
output_low_st
0000000000000
output_high_st
1111111111111
output_low_st
0000000000000
output_high_st
1111111111111
output_low_st
0000000000000
output_high_st
1111111111111
output_low_st
0000000000000
output_high_st
1111111111111
output_low_st
0000000000000
output_high_st
1111111111111
completed one test period.

Test and Pass Off

For each of your state machines, you will write a runTest() function and demonstrate its operation for pass off. You will need to run each of the runTest() functions separately. One option is to modify and recompile main.c to run each of these functions individually. If you don't like recompiling between each of your tests, you can use Button 3 to signal when to exit each individual test and move to the next test. The required operation for each test is described below.

Transmitter

The goal is to prove that your transmitter state machine accurately and reliably produces the correct waveform at JF-1. You will test both continuous and non-continuous mode. Non-continuous mode should be the default. In non-continuous mode, the transmitter state machine generates a single 200 ms square wave at the selected frequency when transmitter_run() is invoked. In continuous mode (used for testing), the transmitter continuously generates a waveform at the pin until transmitter_setContinuousMode() is invoked with an argument value of false. You must test both non-continuous and continuous modes of operation.

Testing Non-Continuous Mode

You can access this signal at the “Transmitter Probe” pin on the development board. To test the transmitter state machine, do the following in a while-loop in transmitter_runTest. In an endless loop in transmitter_runTest() do the following:

  1. Read the slide switches and use the numerical value of the switches as the frequency index. When all switches are in the down position (closest to the bottom of the board), you should generate the waveform for frequency 0. Sliding switch (SW0) upward would select frequency 1, and so forth.
  2. Set the frequency using the transmitter_setFrequencyNumber() function.
  3. Invoke transmitter_run().
  4. Use the utils_msDelay() function to delay for approximately 400 ms, long enough to demonstrate the operation of the transmitter on the oscilloscope.

Demonstrate to the TA, using an oscilloscope probe attached to “Transmitter Probe” pin, that the waveform is the correct shape and frequency for each of the 10 slide-switch settings. You should be able to see that the waveform is generated for 200 ms with a “dead time” of about 400 ms where the output goes to 0 between each successive generation of the waveform.

Testing Continuous mode

Access and display the transmitter output as described above. In your test function, do the following:

  1. Invoke transmitter_init(), transmitter_setContinuousMode(true), transmitter_run() prior to entering an endless loop.
  2. In an endless while-loop:
    1. Set the frequency using the transmitter_setFrequencyNumber() function.

Demonstrate to the TA that the waveform that is displayed is continuous and changes to the correct frequency as the slide switches are changed.

Trigger

Goal: Demonstrate that the trigger state machine correctly debounces the trigger (BTN0 for this test). To perform this test, use a debug print inside your state machine.

As you transition to the state when the “press” of the trigger has been successfully debounced, print the 'D' character to the console using the DPCHAR() macro shown above. Make sure that you only print the 'D' character once as you enter the state when the trigger switch has been successfully debounced. Similarly, print out a 'U' character when the release of the trigger has been debounced. If you only print out a single 'D' and a single 'U' for each press-release of BTN0, the trigger is probably getting debounced properly.

In trigger_runTest(), enable the trigger state machine and demonstrate the required behavior to the TA.

Hit LED Timer

Goal: demonstrate that your hitLedTimer state machine illuminates LD0 and drives a '1' onto the JF-3 pin for 1/2 second each time it is activated. You will see LED1 blink on and off at 1/2-second intervals if this is working correctly. LED1 is directly connected to JF-3 and is provided for debug and pass off.

In your hitLedTimer_runTest() function do the following inside a while-loop:

  • Step 1: invoke hitLedTimer_start(),
  • Step 2: wait until hitLedTimer_running() is false (use another while-loop for this).
  • Delay for 300 ms using utils_msDelay().
  • Go back to Step 1.

Demonstrate to the TA that LD0 and LED1 is blinking at a rate of 1/2 second (this will be approximate because this will be a visual inspection). Also show the TA that pin “Hit Detected” has the appropriate waveform by attaching an oscilloscope probe to the “Hit Detected” pin.

Lock Out Timer

Goal: prove that the lock out timer is accurate and that the functions work as specified.

In lockoutTimer_runTest() do the following:

  1. Start an interval timer,
  2. Invoke lockoutTimer_start(),
  3. Wait while lockoutTimer_running() is true (another while-loop),
  4. Once lockoutTimer_running() is false, stop the interval timer,
  5. Print out the time duration from the interval timer.

Show the TA the execution of lockoutTimer_runTest().

Code Submission

  1. From the top-level directory (e.g. ecen390), run the check_and_zip program: ”./check_and_zip.py 390m3-2”.
  2. The resulting .zip file will be in the top-level directory. Submit that to Learning Suite.
  3. Submit only one .zip file per team. Both team members will receive credit.

Notes to the TAs

TAs: please pay attention to the following during pass off and when you are grading source code.

  1. Verify that the state machine init() and tick() functions are called in isr.c prior to performing any kind of pass off.
  2. Carefully check that each run test is functioning properly.
milestone_3_task_2.1676938683.txt.gz · Last modified: 2023/02/20 17:18 by scott