Remember tutorial 2? There were 3 flashing LEDs. And we had to write led1.setOutput(Pin.LOW)
to turn on the LED. The more convenient way is to create LED object and write something like led.setState(Led.State.ON)
With LED the difference is not large, but for complex devices (like LCD) code become easier, safer and more flexible.
User objects work in different way than microcontroller classes and listeners. User object's code is compiled and executed on computer, not interpreted. In fact, user classes are translators. So, they can throw exceptions and use other Java langauge features. Here's a template:
//packages for user objects
import mcujavasource.transformer.instance.*;
import mcujavasource.transformer.userclass.*;
class MyObject extends AbstractInstanceUser
{
private SourceInstance pin;
public MyObject(Pin pin)
{ //only for running on PC
}
public MyObject(InstanceContext context, SourceInstance pin)
{ super(context);
this.pin = pin;
invoke(pin, "setDirection", Pin.OUT);
}
public void method()
{ invoke(pin, "pinMethod", args);
}
}
mcujavasource.transformer.userclass.AbstractInstanceUser
InstanceContext context
argument is added to beginning, and all object arguments turn to SourceInstance type. The first statement in translator constructor must be super(context);
invoke(SourceInstance si, String methodName, Object... args);
For example, pin.setOutput(Pin.LOW);
become invoke(pin, "setOutput", Pin.LOW);
in user class.include(String name)
, name is a string to write in #include "name"
statement. Files with patterns "**/*.c,**/*.cpp,**/*.h,**/*.s,**/*.S,**/*.asm" are copied from src to build directory in NetBeans project. To call a function defined in native code, use callFunction(String functionName, Object... args)
This program works in the same way as tutorial 2. The C code (main.c file) is absolutely equal.
import mcujavasource.mcu.*;
//packages for user objects
import mcujavasource.transformer.instance.*;
import mcujavasource.transformer.userclass.*;
/** Tutorial 7: simple user object.
* It's tutorial 2, rewritten with SimpleLed object.
* Three LEDs flash one after another.
* Default 8-bit timer and its overflow interrupt is used for delay.
* LED's anode is connected to +5V through 330 Ohm resistor,
* cathode - to MCU port.
*/
public class Main extends Microcontroller
{
/** Pin of the first LED, PB1 */
private final Pin led1Pin = getHardware().getPort("B").getPin(1);
/** Pin of the second LED, PB0 */
private final Pin led2Pin = getHardware().getPort("B").getPin(0);
/** Pin of the third LED, PB2 */
private final Pin led3Pin = getHardware().getPort("B").getPin(2);
private SimpleLed led1;
private SimpleLed led2;
private SimpleLed led3;
private Timer timer;
private volatile int currentLed = 0;
public void init()
{ //register initialization on startup
getHardware().setAllPortsDirection(Pin.IN);
getHardware().setAllPortsPullUp(true);
led1 = new SimpleLed(led1Pin);
led2 = new SimpleLed(led2Pin);
led3 = new SimpleLed(led3Pin);
// led1 is initially turned on
led1.setState(SimpleLed.State.ON);
// getting default 8-bit timer
timer = getHardware().getDefaultTimer(8);
timer.setMode(TimerMode.NORMAL);
// no prescaling
timer.setPrescaling(1);
timer.setEnabled(true);
LedSwitcher ledSwitcher = new LedSwitcher();
timer.addTimerListener(ledSwitcher);
timer.setTimerOverflowedFired(true); //this enables interrupt
}
public void start()
{ //main program
getHardware().setInterruptsEnabled(true);
}
private class LedSwitcher implements TimerListener
{
public void timerOverflowed()
{ currentLed++;
if(currentLed >= 3) currentLed = 0;
switch(currentLed)
{ case 0:
led3.setState(SimpleLed.State.OFF); //turn off led3
led1.setState(SimpleLed.State.ON); //turn on led1
break;
case 1:
led1.setState(SimpleLed.State.OFF);
led2.setState(SimpleLed.State.ON);
break;
case 2:
led2.setState(SimpleLed.State.OFF);
led3.setState(SimpleLed.State.ON);
break;
}
}
}
}
class SimpleLed extends AbstractInstanceUser
{
public enum State { ON, OFF };
private SourceInstance pin;
/** Creates a SimpleLed from the given pin.
* Initial state is OFF.
*/
public SimpleLed(Pin pin)
{ //only for running on PC
}
//Pin class turned into SourceInstance, and InstanceContext context added
public SimpleLed(InstanceContext context, SourceInstance pin)
{ super(context);
this.pin = pin;
invoke(pin, "setDirection", Pin.OUT);
invoke(pin, "setOutput", true);
}
public void setState(State state)
{ boolean value = (state == State.OFF);
invoke(pin, "setOutput", value);
}
}