Adding buttons

9 May

Adding buttons
The LCD is a nice way for your TINI to display test messages, but what about a way to capture external events to trigger TINI software routines? In other words, how do we get input based on some external events? We can do this using the TINI external interrupt. The TINI stick has an /EXTINT line and the TINI API includes several classes for dealing with and managing these external interrupts. Figure 8-15 shows the external interrupt logic on the TINI E10/E20 socket board. This allows for two serial port interrupts and two auxiliary interrupts to control the TINI CPU /EXTINT line. To trigger an interrupt we need to take the /EXTINT line low. The TINI API class com.dalsemi.system.ExternalInterrupt and ExternalInterruptEvent are used for accessing the external interrupt and interrupt events.

External interrupt logic
We can trigger external interrupts by attaching a simple pushbutton to the /EXTINT line so that when the button is pressed it connects the /EXTINT line momentarily to ground. Something along the lines of that shown in Figure 8-16 will do nicely.

Figure 8-16: A button to trigger an external interrupt
The 10K resistor is a pull-up on the /EXTINT line. It holds this line at Vcc until someone (or some event) presses the button. When the button is closed it connects ground to the /EXTINT line and this triggers an interrupt on the TINI stick. If we have implemented an ExternalInterruptEvent then we can start a Java class executing with a button press. Note that this is a button and not a switch. TINI can be configured so the ExternalInterruptEvent is either falling-edge triggered or low-level triggered. The default is level triggering. If you use level triggering with a switch then TINI will be repeatedly sending interrupts while the switch is closed, leaving very little of the CPU to service the interrupt. Your interrupt should be short durations to avoid this.

Listing 8-8: ExtIntDemo.java

import  java.util.TooManyListenersException;
import com.dalsemi.system.*;

// Class ExtIntDemo provides a simple deonstration of implementing an
//  ExternalInterruptEventListener
class ExtIntDemo implements ExternalInterruptEventListener
{
int interruptions;
public void init() throws TooManyListenersException
{
ExternalInterrupt myInterrupt = new ExternalInterrupt();
myInterrupt.addEventListener(this);
try {
myInterrupt.setTrigger( true, this );
}
catch (ExternalInterruptException e) {
System.out.println( e );
}
}
public void externalInterruptEvent(ExternalInterruptEvent ev)
{
System.out.println(“Interruptions = “ + ++interruptions );
if (interruptions > 25) { System.exit(0); }
}
public static void main(String[] args) throws
TooManyListenersException
{
ExtIntDemo interrupt = new ExtIntDemo();
interrupt.init();
while (true) {
// do nothing
}
}
}

Compile this program:

C:\> javac -bootclasspath %TINI_HOME%\bin\tiniclasses.jar
-d bin src\ExtIntDemo.java
C:\> java -classpath %TINI_HOME%\bin\tini.jar;. BuildDependency
-p %TINI_HOME%\bin\owapi_dependencies_TINI.jar
-f bin
-x  %TINI_HOME%\bin\owapi_dep.txt
-o bin\ExtIntDemo.tini
-d %TINI_HOME%\bin\tini.db
Run this on your TINI. Note the triggering in the line
myInterrupt.setTrigger( true, this );

Try changing this to false and see how the program reacts to button presses. Notice that we are not doing any switch debouncing here. You can add that to your circuits as needed but for this example we can be content to ignore any switch bounce as being too short of a duration to register multiple interrupts, but that’s not always the case. Changing the triggering can help make this program a little more sensitive to keybounce. Appendix C (on the CD-ROM) provides a number of possible debounce circuits. To complicate this a little more, you can then connect multiple buttons or switches by combining their signals as shown in Figure 8-17. It’s worth noting that when the ExternalInterruptEvent is executing, TINI will be ignoring (not queuing) any additional external interrupts that occur. If this is a bad thing, you will need to keep the ExternalInterruptEvent method you implement as simple as possible so it can be executing quickly.

Figure 8-18: Switch state memory schematic
But if we want to add more than one button, how will we know which button was pressed? We only have one external interrupt line on the TINI stick, so we need a way to save the state of each button so we can query them after an interrupt is caught. The circuit in Figure 8-18 shows a 74ATC74, dual D-type flip-flop configured to store the on state of either button that’s pressed. We use a 75HC541, octal buffer, enabled by one of our chip selects from the address decoder to connect the stored button states to the data bus, and another chip select to clear the stored state after our interrupt service method has determined which of the buttons caused the external interrupt. Now we can support multiple buttons and know which button was pressed after we catch the interrupt. We can add additional 74ATC74 devices for more buttons as needed. The schematic also shows a keypad data available line (KBDA) connected to the data bus buffer. We will use it to determine if an interrupt was caused by the keypad in the next section. The Button class, below, provides methods for accessing the button state and clearing them.

Listing 8-9: Button.java

import com.dalsemi.system.*;
// Class Button provides methods for accessing push buttons
class Button                                                                               {
DataPort clearButtons;
DataPort readButtons;
public Button( int clearaddr, int buttonaddr ) {
clearButtons = new DataPort( clearaddr );
clearButtons.setStretchCycles(DataPort.STRETCH10);
readButtons                                                                                = new DataPort( buttonaddr );
readButtons.setStretchCycles(DataPort.STRETCH10);
}
public int read() {
int d=0;
try {
d = readButtons.read();
}
catch (IllegalAddressException e)
System.out.println( “Error in reading switches” );
System.out.println( e );
}
return( d );
}
public void clear() {
try {
clearButtons.write( 0×00 );
}
catch (IllegalAddressException e)
System.out.println( “Error in reading switches” );
System.out.println( e );
}
}
public boolean isButton1() {
int s = this.read();
return( (s & 0×01)>0 ? true : false );
}
public boolean isButton2() {
int s = this.read();
return( (s & 0×02)>0 ? true : false );
}
public boolean isButton3() {
int s = this.read();
return( (s & 0×04)>0 ? true : false );
}
public boolean isButton4() {
int s = this.read();
return( (s & 0×08)>0 ? true : false );
}
}

This is a summary of the methods in this class:

•  Button(  int,  int) is the constructor for this class, taking two parameters, the address of the clear dataport and the address of the read dataport.
•  read()  returns an integer that contains the state of buttons.
•  clear() clears the button states.
•  isButton1(),  isButton2(),  isButton3(),  isButton4() all return Boolean values of the individual button states.

The simple program below demonstrates the Button class and shows how to check the button status by simple polling. If any button (or several) is pressed, the program prints the result of a dataport read.

import com.dalsemi.system.*;
// Class pollButtons demonstrates how to poll the status of the buttons
public class pollButton {
public static void main(String[] args)                                    {
int state = 0;
int i=0;
Button mybutton = new Button(0×00800000, 0×00800004 );
mybutton.clear();
while (i<200) {
state = mybutton.read();
if (state > 0) {
if (mybutton.isButton1()) {
System.out.println( “Button: 1” );
}
if (mybutton.isButton2()) {
System.out.println( “Button: 2” );
}
if (mybutton.isButton3()) {
System.out.println( “Button: 3” );
}
if (mybutton.isButton4()) {
System.out.println( “Button: 4” );
}
}
mybutton.clear();
TINIOS.sleepProcess(50);
i++;
}
}
}

Compile this program:

C:\> cd src
C:\> javac -bootclasspath  %TINI_HOME%\bin\tiniclasses.jar
-d ..\bin pollButton.java
C:\> cd ..
C:\> java-classpath %TINI_HOME%\bin\tini.jar;. BuildDependency
-p  %TINI_HOME%\bin\owapi_dependencies_TINI.jar
-f bin
-x%TINI_HOME%\bin\owapi_dep.txt
-o bin\pollButton.tini
-d %TINI_HOME%\bin\tini.db

This works well when we don’t require the program to know about the button presses in a timely manner. A busy CPU may not get around to servicing this often enough for reasonable response time. We should use the ExternalInterrupt when we need better response. We will implement that in the next section with the keypad.

Random Posts

Comments are closed.