Welcome to TiddlyWiki created by Jeremy Ruston; Copyright © 2004-2007 Jeremy Ruston, Copyright © 2007-2011 UnaMesa Association
''Use with extra care!''
|!|!Type|!Size (bits)|!Example|!Minimum Value|!Maximum Value|
||byte|8|byte b = 65;|-128|127|
||char([[*|Configurable 16 or 8 bit char type]])|16|char c = 'A'; char c = 65;|0|65535|
||short|16|short s = 65;|-32768|32767|
||int|16|int i = 65;|-32768|32767|
||long|16|long l = 65L;|-32768|32767|
||[[float|half precision float]]|16|float f = 65f;|-65504.0|65504.0|
||[[double|half precision double]]|16|double d = 65.55;|-65504.0|65504.0|
||boolean|8|boolean b = true;|>|true or false|
''Remark''
Stack size of ''double'' and ''long'' is 2 * 16 Bit.
Recommended mode for 16 Bit micros.
|!|!Type|!Size (bits)|!Example|!Minimum Value|!Maximum Value|
||byte|8|byte b = 65;|-128|127|
||char([[*|Configurable 16 or 8 bit char type]])|16|char c = 'A'; char c = 65;|0|65535|
||short|16|short s = 65;|-32768|32767|
||int|16|int i = 65;|-32768|32767|
||long|32|long l = 65L;|-2147483648|2147483647|
||[[float|half precision float]]|16|float f = 65f;|-65504.0|65504.0|
||[[double|double 32]]|32|double d = 65.55;|>|+/- 1.4023x10^-45 to 3.4028x10^+38|
||boolean|8|boolean b = true;|>|true or false|
|!|!Type|!Size (bits)|!Example|!Minimum Value|!Maximum Value|
||byte|8|byte b = 65;|-128|127|
||char([[*|Configurable 16 or 8 bit char type]])|16|char c = 'A'; char c = 65;|0|65535|
||short|16|short s = 65;|-32768|32767|
||int|32|int i = 65;|-2147483648|2147483647|
||long|32|long l = 65L;|-2147483648|2147483647|
||float|32|float f = 65f;|>|+/- 1.4023x10^-45 to 3.4028x10^+38|
||[[double|double 32]]|32|double d = 65.55;|>|+/- 1.4023x10^-45 to 3.4028x10^+38|
||boolean|8|boolean b = true;|>|true or false|
''Remark''
Stack size of ''double'' and ''long'' is 2 * 32 Bit.
|!|!Type|!Size (bits)|!Example|!Minimum Value|!Maximum Value|
||byte|8|byte b = 65;|-128|127|
||char([[*|Configurable 16 or 8 bit char type]])|16|char c = 'A'; char c = 65;|0|65535|
||short|16|short s = 65;|-32768|32767|
||int|32|int i = 65;|-2147483648|2147483647|
||long|64|long l = 65L;|-9223372036854775808|9223372036854775807|
||float|32|float f = 65f;|>|+/- 1.4023x10^-45 to 3.4028x10^+38|
||double|64|double d = 65.55;|>|+/- 4.9406x10^-324 to 1.7977x10^+308|
||boolean|8|boolean b = true;|>|true or false|
''Remark 1:''
~HaikuVM maps all primitive data types to corresponding C data types. For example JAVA type ''double'' is mapped to C type ''double''. This sounds obvious but may cause problems. ([[More ...|double and float support]])
''Remark 2:''
~HaikuVM makes extra effort to map the JAVA type ''long'' to a C type which has 64Bit precision. (Using C types 'long long' or 'int64_t' where possible).
!Meaning of the Directories
~HaikuVM comes with a set of directories as a conglomeration of multiple single-purpose projects. First ~HaikuVM consists of a couple of Java and C++ projects. Here I'll shed some light on the directories in haikuVM and what they are for:
''haikuVM''
*''bin''<br>For Windows and Linux commands (e.g. like haikulink) to be used with ~HaikuVM. ([[More...|Commands]])
*''bootstrap''<br>A collection of ~MicroKernels and usefull microcontroller platform specific Java classes/libs. Often used (import) from the Java examples (see below).
*''config''<br>Central place for the configuration file '~HaikuVM.properties'. ([[More...|HaikuVM.properties]])
*''examples''<br>Serves as a pool of example java files to be used as simple starter for your projects.
*''gallerie''<br>Short examples shared with the ~HaikuVM community. (Just send it via e-mail or use other ways.)
*''haikuBench''<br>Benchmarks and ~JUnits (mostly) for internal use.
*''haikufier''<br>Implementation of all the ~HaikuVM commands. This is the machine room of ~HaikuVM during compile and link time.
*''haikuRT''<br>This is the special ~HaikuVM runtime. The leJOS runtime is prefered but some core classes (like Thread, String, etc.) have to be tweeked/substituted for ~HaikuVM and ~AVRs and small RAM footprint. So haikuRT (haikuRT.jar) will precede classes.jar (see lib) in every classpath used with your project.
*''haikuVM''<br>C file templates used to be copied into your (empty) project directory to be cross compiled for your micro. This is the machine room, the Java VM, of ~HaikuVM during runtime on the target micro itself.
*''hardware''<br>Service only for Windows users. Consists of WINAVR, AVRDUDE, AVR libs and include files. (Linux users have to install this separately, see [[here|Linux]].)
*''lib''<br>All this ~JAR-files needed for the commands in bin.
**classes.jar -> Java runtime as borrowed from the leJOS project.
**bootstrap.jar -> Class files build from sources in bootstrap.
**haikuRT.jar -> Class files build from sources in haikuRT.
**haikutools.jar -> Central place of all the ~HaikuVM commands as used in bin. Build from sources in haikufier.
**bcel-5.2.jar -> The BCEL project used in haikulink to disassemble class files.
*''myCProject''<br>A template directory for your project (and tutorials). Any other empty directory, elsewhere on your disk, will do as well. ([[More...|Your Project on Disk and at Runtime]])
This is how to program an Arduino in JAVA to let the LED blink (using Threads just for example).
<code java>
package arduino.tutorial;
import static haiku.avr.lib.arduino.WProgram.*;
public class BlinkWithThread extends Thread {
static byte ledPin = 13; // LED connected to digital pin 13
public void run() // run over and over again
{
while (true) {
digitalWrite(ledPin, HIGH); // sets the LED on
delay(1000); // waits for a second
digitalWrite(ledPin, LOW); // sets the LED off
delay(1000); // waits for a second
}
}
public static void main(String[] args) {
pinMode(ledPin, OUTPUT); // sets the digital pin as output
new BlinkWithThread().start();
}
}
</code>
After you have installed all needed software (see GettingStarted) you can proceed with the following 2 steps to let the ~BlinkWithThread program run on your Arduino:
<code bash>
cd C:\haikuVM\myCProject
C:\haikuVM\bin\haiku -v --Config arduino -o BlinkWithThread.hex C:\haikuVM\examples\src\main\java\arduino\tutorial\BlinkWithThread.java
</code>
*[[haiku]] first calls [[haikuc]] which calls javac to compile ''~BlinkWithThread.java'' into ''~BlinkWithThread.class'' (bytecode).
*[[haiku]] second calls [[haikulink]] which first translates the ''~BlinkWithThread.class'' into a ''C program'' and adds the Haiku VM (which is written also in C). Second it cross compiles and links all C sources into the file ''~BlinkWithThread.hex'' by calling 'make all' of WINAVR.
*[[haiku]] third calls [[haikuupload]] which finally uploads ''~BlinkWithThread.hex'' to the Arduino by calling avrdude.
Most of this steps are configurable in the file [[HaikuVM.properties]] or can be modified by giving other [[command line options]]. For instance [[HaikuVM.properties]] assumes that your ARDUINO is connected on port com17. Change the following line of [[HaikuVM.properties]] to adapt to your configuration:
{{{
arduino.Port = \\\\\\.\\com17
}}}
Or call [[haiku]] with a port name like this:
{{{
C:\haikuVM\bin\haiku -v --Config arduino --Config:Port \\\.\com5 -o BlinkWithThread.hex C:\haikuVM\examples\src\main\java\arduino\tutorial\BlinkWithThread.java
}}}
For those who are curious to see how an ARDUINO can be programmed with JAVA and the ''wiring'' philosophy follow this [[link|Wiring]].
After you have installed all needed software (see GettingStarted) you can alternativly proceed with the following 4 steps to let the ~BlinkWithThread program run on your Arduino:
{{{
cd C:\haikuVM\myCProject
C:\haikuVM\bin\haikuc C:\haikuVM\examples\src\main\java\arduino\tutorial\BlinkWithThread.java
C:\haikuVM\bin\haikulink -v --Config arduino -o BlinkWithThread.hex C:\haikuVM\examples\src\main\java\arduino\tutorial\BlinkWithThread
C:\haikuVM\bin\haikuupload BlinkWithThread.hex
}}}
*[[haikuc]] calls javac to compile ''~BlinkWithThread.java'' into ''~BlinkWithThread.class'' (bytecode).
*[[haikulink]] first translates the ''~BlinkWithThread.class'' into a ''C program'' and adds the Haiku VM (which is written also in C). Second it cross compiles and links all C sources into the file ''~BlinkWithThread.hex'' by calling make of WINAVR.
*[[haikuupload]] finally uploads ''~BlinkWithThread.hex'' to the Arduino by calling avrdude.
Most of this steps are configurable in the file [[HaikuVM.properties]] or can be modified by giving other [[command line options]]. For instance [[HaikuVM.properties]] assumes that your ARDUINO is connected on port com17. Change the following line of [[HaikuVM.properties]] to adapt to your configuration:
{{{
arduino.Port = \\\\\\.\\com17
}}}
This is how to program an Asuro robot in JAVA (using the JAVA ported ~AsuroLib 2.8.0 rc1 [[which is originaly written in C|https://sourceforge.net/projects/asuro/]]).
<code java>
package asuro.tutorial;
import static haiku.avr.lib.asuro.lib2_8_0_rc1.AsuroLib2_8_0_rc1.*;
public class Blink {
public static void main(String[] args) {
Init(); // initialize the ASURO
while (true) {
StatusLED(GREEN);
Msleep(1000);
StatusLED(RED);
Msleep(1000);
}
}
}
</code>
After you have installed all needed software (see GettingStarted) you can proceed with the following 5 steps to let the Blink program run on your ASURO:
{{{
cd C:\haikuVM\myCProject
C:\haikuVM\bin\haiku -v --Config asuro -o Blink.hex C:\haikuVM\examples\src\main\java\arduino\tutorial\Blink.java
}}}
([[See an alternativ approach.|Asuro Details]])
*[[haiku]] first calls [[haikuc]] which calls javac to compile ''Blink.java'' into ''Blink.class'' (bytecode).
*[[haiku]] second calls [[haikulink]] which first translates the ''Blink.class'' into a ''C program'' and adds the Haiku VM (which is written also in C). Second it cross compiles and links all C sources into the file ''Blink.hex'' by calling make of WINAVR.
*[[haiku]] third calls [[haikuupload]] which finally uploads ''Blink.hex'' to the ASURO by calling ~ASUROFlash155.
Most of this steps are configurable in the file [[HaikuVM.properties|HaikuVM.properties]] or can be modified by giving other [[command line options|command line options]]. For instance [[HaikuVM.properties]] assumes that your ASURO code is uploaded with ~ASUROFlash155.exe (not shipped with ~HaikuVM). Change the following line of [[HaikuVM.properties]] to adapt to your configuration:
{{{
asuro.Upload = cmd /c start ASUROFlash155
}}}
If you curious to see how the blinking can be achieved by ''using threads'', take a look into './examples/src/main/java/asuro/tutorial/~BlinkWithThread.java' and/or proceed like this:
{{{
C:\haikuVM\bin\haiku -v --Config asuro -o BlinkWithThread.hex C:\haikuVM\examples\src\main\java\arduino\tutorial\BlinkWithThread.java
}}}
After you have installed all needed software (see GettingStarted) you can alternativly proceed with the following 4 steps to let the Blink program run on your ASURO:
{{{
cd C:\haikuVM\myCProject
}}}
{{{
C:\haikuVM\bin\haikuc C:\haikuVM\examples\src\main\java\arduino\tutorial\Blink.java
C:\haikuVM\bin\haikulink -v --Config asuro -o Blink.hex C:\haikuVM\examples\src\main\java\arduino\tutorial\Blink
C:\haikuVM\bin\haikuupload Blink.hex
}}}
*[[haikuc]] calls javac to compile ''Blink.java'' into ''Blink.class'' (bytecode).
*[[haikulink]] first translates the ''Blink.class'' into a ''C program'' and adds the Haiku VM (which is written also in C). Second it cross compiles and links all C sources into the file ''Blink.hex'' by calling make of WINAVR.
*[[haikuupload]] finally uploads ''Blink.hex'' to the ASURO by calling ~ASUROFlash155.
Most of this steps are configurable in the file [[HaikuVM.properties|HaikuVM.properties]] or can be modified by giving other [[command line options|command line options]]. For instance [[HaikuVM.properties]] assumes that your ASURO code is uploaded with ~ASUROFlash155.exe (not shipped with ~HaikuVM). Change the following line of [[HaikuVM.properties]] to adapt to your configuration:
{{{
asuro.Upload = cmd /c start ASUROFlash155
}}}
If you curious to see how the blinking can be achieved by ''using threads'', take a look into './examples/src/main/java/asuro/tutorial/~BlinkWithThread.java' and/or proceed like this:
{{{
C:\haikuVM\bin\haikuc C:\haikuVM\examples\src\main\java\arduino\tutorial\BlinkWithThread.java
C:\haikuVM\bin\haikulink -v --Config asuro -o BlinkWithThread.hex C:\haikuVM\examples\src\main\java\arduino\tutorial\BlinkWithThread
C:\haikuVM\bin\haikuupload BlinkWithThread.hex
}}}
After you have installed all needed software (see GettingStarted) you are prepared to proceed with the following 4 steps to let the ''~BlinkSimple'' program run on your AVR:
{{{
cd C:\haikuVM\myCProject
}}}
{{{
C:\haikuVM\bin\haikuc C:\haikuVM\examples\src\main\java\avr\tutorial\BlinkSimple.java
C:\haikuVM\bin\haikulink -v --Config simple010 -o BlinkSimple.hex C:\haikuVM\examples\src\main\java\avr\tutorial\BlinkSimple
C:\haikuVM\bin\haikuupload BlinkSimple.hex
}}}
*[[haikuc]] calls javac to compile ''~BlinkSimple.java'' into ''~BlinkSimple.class'' (bytecode).
*[[haikulink]] first translates the ''~BlinkSimple.class'' into a ''C program'' and adds the Haiku VM (which is written also in C). Second it cross compiles and links all C sources into the file ''~BlinkSimple.hex'' by calling make of WINAVR.
*[[haikuupload]] finally uploads ''~BlinkSimple.hex'' to the AVR by calling avrdude.
Most of this steps are configurable in the file [[HaikuVM.properties|HaikuVM.properties]] or can be modified by giving other [[command line options|command line options]]. For instance [[HaikuVM.properties]] assumes that your AVR code is uploaded with avrdude. Change the following line of [[HaikuVM.properties]] to adapt to your configuration:
{{{
simple010.Upload = ...
}}}
This code of ''~BlinkSimple.java'' uses a simple busy-wait delay loop to let the LED blink.
From here you might proceed with 'C:\haikuVM\examples\src\main\java\avr\tutorial\Blink.java'. Which uses Thread.sleep(..), which in turn relies on timer 0 overflow interrupt (resulting in non-busy-wait).
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
When it comes to the commands, ~HaikuVM doesn't re-event the wheel. Instead commands and their meaning is analog to leJOS.
This are the leJOS NXJ tools for compiling, linking and uploading of programs:
* nxjc
* nxjlink
* nxjupload
* nxj
Corresponding to this the ~HaikuVM tools are:
* [[haikuc]]
* [[haikulink]]
* [[haikuupload]]
* [[haiku]]
For a more detailed description you can follow the desciption of the leJOS commands which can be found [[here|http://lejos.sourceforge.net/nxt/nxj/tutorial/Preliminaries/CompileAndRun.htm]].
If you take a look at the following JAVA code:
<code java>
package haikuvm.bench;
public class Fibonacci32Bit {
static int fib(int n) {
if(n < 2)
return 1;
else
return fib(n-2) + fib(n-1);
}
public static void main(String[] args) {
long t0 = System.currentTimeMillis();
for(int i=0;i<=30;i++)
System.out.println("Fibonacci of "+i+" is "+fib(i)+" in "+(System.currentTimeMillis()-t0)+" ms");
}
}
</code>
Then javap says:
{{{
javap -c -classpath C:\haikuVM\haikuBench\bin haikuvm\bench\Fibonacci32Bit
}}}
That the bytecode in ~Fibonacci32Bit.class sums up to 97 bytes:
{{{
Compiled from "Fibonacci32Bit.java"
public class haikuvm.bench.Fibonacci32Bit extends java.lang.Object{
public haikuvm.bench.Fibonacci32Bit();
Code:
0: aload_0
1: invokespecial #8; //Method java/lang/Object."<init>":()V
4: return
static int fib(int);
Code:
0: iload_0
1: iconst_2
2: if_icmpge 7
5: iconst_1
6: ireturn
7: iload_0
8: iconst_2
9: isub
10: invokestatic #16; //Method fib:(I)I
13: iload_0
14: iconst_1
15: isub
16: invokestatic #16; //Method fib:(I)I
19: iadd
20: ireturn
public static void main(java.lang.String[]);
Code:
0: invokestatic #23; //Method java/lang/System.currentTimeMillis:()J
3: lstore_1
4: iconst_0
5: istore_3
6: goto 64
9: getstatic #29; //Field java/lang/System.out:Ljava/io/PrintStream;
12: new #33; //class java/lang/StringBuilder
15: dup
16: ldc #35; //String Fibonacci of
18: invokespecial #37; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
21: iload_3
22: invokevirtual #40; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
25: ldc #44; //String is
27: invokevirtual #46; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
30: iload_3
31: invokestatic #16; //Method fib:(I)I
34: invokevirtual #40; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
37: ldc #49; //String in
39: invokevirtual #46; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
42: invokestatic #23; //Method java/lang/System.currentTimeMillis:()J
45: lload_1
46: lsub
47: invokevirtual #51; //Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
50: ldc #54; //String ms
52: invokevirtual #46; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
55: invokevirtual #56; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
58: invokevirtual #60; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
61: iinc 3, 1
64: iload_3
65: bipush 30
67: if_icmple 9
70: return
}
}}}
^^For those who are curious to know how this is coded in ~HaikuVM should take a look [[here|Compact HaikuVM Code]].^^
If you compare this with a corresponding C program:
<code c>
int32_t fib(int32_t n) {
if(n < 2)
return 1;
else
return fib(n-2) + fib(n-1);
}
int fib_main() {
int32_t i;
long t0 = millis();
for(i=0;i<=30;i++) {
printf("Fibonacci of %ld is %ld in %ld ms\n", i, fib(i), (long)(millis()-t0));
}
return 0;
}
</code>
Then a disassembly listing says:
{{{
000001e0 <fib>:
1e0: af 92 push r10
1e2: bf 92 push r11
1e4: cf 92 push r12
1e6: df 92 push r13
1e8: ef 92 push r14
1ea: ff 92 push r15
1ec: 0f 93 push r16
1ee: 1f 93 push r17
1f0: 7b 01 movw r14, r22
1f2: 8c 01 movw r16, r24
1f4: aa 24 eor r10, r10
1f6: bb 24 eor r11, r11
1f8: 65 01 movw r12, r10
1fa: 82 e0 ldi r24, 0x02 ; 2
1fc: e8 16 cp r14, r24
1fe: f1 04 cpc r15, r1
200: 01 05 cpc r16, r1
202: 11 05 cpc r17, r1
204: b4 f0 brlt .+44 ; 0x232 <fib+0x52>
206: 8e ef ldi r24, 0xFE ; 254
208: 9f ef ldi r25, 0xFF ; 255
20a: af ef ldi r26, 0xFF ; 255
20c: bf ef ldi r27, 0xFF ; 255
20e: e8 0e add r14, r24
210: f9 1e adc r15, r25
212: 0a 1f adc r16, r26
214: 1b 1f adc r17, r27
216: c8 01 movw r24, r16
218: b7 01 movw r22, r14
21a: 0e 94 f0 00 call 0x1e0 ; 0x1e0 <fib>
21e: 08 94 sec
220: e1 1c adc r14, r1
222: f1 1c adc r15, r1
224: 01 1d adc r16, r1
226: 11 1d adc r17, r1
228: a6 0e add r10, r22
22a: b7 1e adc r11, r23
22c: c8 1e adc r12, r24
22e: d9 1e adc r13, r25
230: e4 cf rjmp .-56 ; 0x1fa <fib+0x1a>
232: a6 01 movw r20, r12
234: 95 01 movw r18, r10
236: 2f 5f subi r18, 0xFF ; 255
238: 3f 4f sbci r19, 0xFF ; 255
23a: 4f 4f sbci r20, 0xFF ; 255
23c: 5f 4f sbci r21, 0xFF ; 255
23e: b9 01 movw r22, r18
240: ca 01 movw r24, r20
242: 1f 91 pop r17
244: 0f 91 pop r16
246: ff 90 pop r15
248: ef 90 pop r14
24a: df 90 pop r13
24c: cf 90 pop r12
24e: bf 90 pop r11
250: af 90 pop r10
252: 08 95 ret
...
000002d0 <fib_main>:
2d0: 2f 92 push r2
2d2: 3f 92 push r3
2d4: 4f 92 push r4
2d6: 5f 92 push r5
2d8: 6f 92 push r6
2da: 7f 92 push r7
2dc: 8f 92 push r8
2de: 9f 92 push r9
2e0: af 92 push r10
2e2: bf 92 push r11
2e4: cf 92 push r12
2e6: df 92 push r13
2e8: ef 92 push r14
2ea: ff 92 push r15
2ec: 0f 93 push r16
2ee: 1f 93 push r17
2f0: cf 93 push r28
2f2: df 93 push r29
2f4: 0e 94 b0 00 call 0x160 ; 0x160 <millis>
2f8: 1b 01 movw r2, r22
2fa: 2c 01 movw r4, r24
2fc: ee 24 eor r14, r14
2fe: ff 24 eor r15, r15
300: 87 01 movw r16, r14
302: 66 24 eor r6, r6
304: 77 24 eor r7, r7
306: 43 01 movw r8, r6
308: c0 e0 ldi r28, 0x00 ; 0
30a: d1 e0 ldi r29, 0x01 ; 1
30c: 5c c0 rjmp .+184 ; 0x3c6 <fib_main+0xf6>
30e: 22 e0 ldi r18, 0x02 ; 2
310: e2 16 cp r14, r18
312: f1 04 cpc r15, r1
314: 01 05 cpc r16, r1
316: 11 05 cpc r17, r1
318: b4 f0 brlt .+44 ; 0x346 <fib_main+0x76>
31a: 8e ef ldi r24, 0xFE ; 254
31c: 9f ef ldi r25, 0xFF ; 255
31e: af ef ldi r26, 0xFF ; 255
320: bf ef ldi r27, 0xFF ; 255
322: e8 0e add r14, r24
324: f9 1e adc r15, r25
326: 0a 1f adc r16, r26
328: 1b 1f adc r17, r27
32a: c8 01 movw r24, r16
32c: b7 01 movw r22, r14
32e: 0e 94 f0 00 call 0x1e0 ; 0x1e0 <fib>
332: 08 94 sec
334: e1 1c adc r14, r1
336: f1 1c adc r15, r1
338: 01 1d adc r16, r1
33a: 11 1d adc r17, r1
33c: a6 0e add r10, r22
33e: b7 1e adc r11, r23
340: c8 1e adc r12, r24
342: d9 1e adc r13, r25
344: e4 cf rjmp .-56 ; 0x30e <fib_main+0x3e>
346: 0e 94 b0 00 call 0x160 ; 0x160 <millis>
34a: ad b7 in r26, 0x3d ; 61
34c: be b7 in r27, 0x3e ; 62
34e: 1e 97 sbiw r26, 0x0e ; 14
350: 0f b6 in r0, 0x3f ; 63
352: f8 94 cli
354: be bf out 0x3e, r27 ; 62
356: 0f be out 0x3f, r0 ; 63
358: ad bf out 0x3d, r26 ; 61
35a: ed b7 in r30, 0x3d ; 61
35c: fe b7 in r31, 0x3e ; 62
35e: 31 96 adiw r30, 0x01 ; 1
360: 12 96 adiw r26, 0x02 ; 2
362: dc 93 st X, r29
364: ce 93 st -X, r28
366: 11 97 sbiw r26, 0x01 ; 1
368: 62 82 std Z+2, r6 ; 0x02
36a: 73 82 std Z+3, r7 ; 0x03
36c: 84 82 std Z+4, r8 ; 0x04
36e: 95 82 std Z+5, r9 ; 0x05
370: 08 94 sec
372: a1 1c adc r10, r1
374: b1 1c adc r11, r1
376: c1 1c adc r12, r1
378: d1 1c adc r13, r1
37a: a6 82 std Z+6, r10 ; 0x06
37c: b7 82 std Z+7, r11 ; 0x07
37e: c0 86 std Z+8, r12 ; 0x08
380: d1 86 std Z+9, r13 ; 0x09
382: 62 19 sub r22, r2
384: 73 09 sbc r23, r3
386: 84 09 sbc r24, r4
388: 95 09 sbc r25, r5
38a: 62 87 std Z+10, r22 ; 0x0a
38c: 73 87 std Z+11, r23 ; 0x0b
38e: 84 87 std Z+12, r24 ; 0x0c
390: 95 87 std Z+13, r25 ; 0x0d
392: 0e 94 2a 01 call 0x254 ; 0x254 <jprintf>
396: 84 01 movw r16, r8
398: 73 01 movw r14, r6
39a: 08 94 sec
39c: e1 1c adc r14, r1
39e: f1 1c adc r15, r1
3a0: 01 1d adc r16, r1
3a2: 11 1d adc r17, r1
3a4: 2d b7 in r18, 0x3d ; 61
3a6: 3e b7 in r19, 0x3e ; 62
3a8: 22 5f subi r18, 0xF2 ; 242
3aa: 3f 4f sbci r19, 0xFF ; 255
3ac: 0f b6 in r0, 0x3f ; 63
3ae: f8 94 cli
3b0: 3e bf out 0x3e, r19 ; 62
3b2: 0f be out 0x3f, r0 ; 63
3b4: 2d bf out 0x3d, r18 ; 61
3b6: 3f e1 ldi r19, 0x1F ; 31
3b8: e3 16 cp r14, r19
3ba: f1 04 cpc r15, r1
3bc: 01 05 cpc r16, r1
3be: 11 05 cpc r17, r1
3c0: 31 f0 breq .+12 ; 0x3ce <fib_main+0xfe>
3c2: 37 01 movw r6, r14
3c4: 48 01 movw r8, r16
3c6: aa 24 eor r10, r10
3c8: bb 24 eor r11, r11
3ca: 65 01 movw r12, r10
3cc: a0 cf rjmp .-192 ; 0x30e <fib_main+0x3e>
3ce: df 91 pop r29
3d0: cf 91 pop r28
3d2: 1f 91 pop r17
3d4: 0f 91 pop r16
3d6: ff 90 pop r15
3d8: ef 90 pop r14
3da: df 90 pop r13
3dc: cf 90 pop r12
3de: bf 90 pop r11
3e0: af 90 pop r10
3e2: 9f 90 pop r9
3e4: 8f 90 pop r8
3e6: 7f 90 pop r7
3e8: 6f 90 pop r6
3ea: 5f 90 pop r5
3ec: 4f 90 pop r4
3ee: 3f 90 pop r3
3f0: 2f 90 pop r2
3f2: 08 95 ret
}}}
that the binary size for only this two functions (not including library code) sums up to 407 bytes for an AVR ~ATmega328p.
Conclusion: This ~HaikuVM program is ''about 4 times more compact'' than a plain C program (without counting library overhead).
Given, for example, the following JAVA code:
<code java>
package haikuvm.bench;
public class Fibonacci32Bit {
static int fib(int n) {
if(n < 2)
return 1;
else
return fib(n-2) + fib(n-1);
}
public static void main(String[] args) {
long t0 = System.currentTimeMillis();
for(int i=0;i<=30;i++)
System.out.println("Fibonacci of "+i+" is "+fib(i)+" in "+(System.currentTimeMillis()-t0)+" ms");
}
}
</code>
Then [[haikulink]] transformes the resulting bytecode into initialized plain C structs like this:
<code c>
/**
static int fib(int n)
Code(max_stack = 3, max_locals = 1, code_length = 21)
*/
const haikuvm_bench_Fibonacci32Bit_fib_II_t haikuvm_bench_Fibonacci32Bit_fib_II PROGMEM ={
3+1 +2, 0, 1, // max_stack, purLocals, purParams
OP_ILOAD_0, // 0: iload_0
OP_ICONST_2, // 1: iconst_2
OP_IF_ICMPGE, TARGET(7), // 2: if_icmpge #7
OP_ICONST_1, // 5: iconst_1
OP_IRETURN, // 6: ireturn
OP_ILOAD_0, // 7: iload_0
OP_ICONST_2, // 8: iconst_2
OP_ISUB, // 9: isub
OP_INVOKESHORT_haikuvm_bench_Fibonacci32Bit_fib_II, // 10: invokestatic haikuvm.bench.Fibonacci32Bit.fib (I)I (16)
OP_ILOAD_0, // 13: iload_0
OP_ICONST_1, // 14: iconst_1
OP_ISUB, // 15: isub
OP_INVOKESHORT_haikuvm_bench_Fibonacci32Bit_fib_II, // 16: invokestatic haikuvm.bench.Fibonacci32Bit.fib (I)I (16)
OP_IADD, // 19: iadd
OP_IRETURN, // 20: ireturn
};
/**
public static void main(String[] args)
Code(max_stack = 6, max_locals = 4, code_length = 71)
*/
const haikuvm_bench_Fibonacci32Bit_main_YLjava_lang_String_V_t haikuvm_bench_Fibonacci32Bit_main_YLjava_lang_String_V PROGMEM ={
6+4 +2, 3, 1, // max_stack, purLocals, purParams
OP_INVOKESHORT_java_lang_System_currentTimeMillis_J, // 0: invokestatic java.lang.System.currentTimeMillis ()J (23)
OP_LSTORE_1, // 3: lstore_1
OP_ICONST_0, // 4: iconst_0
OP_ISTORE_3, // 5: istore_3
OP_GOTO, TARGET(64), // 6: goto #64
OP_GETSTATIC_L, SADR(java_lang_System_out), // 9: getstatic java.lang.System.out Ljava/io/PrintStream; (29)
OP_NEW, ADR(java_lang_StringBuilder__class), // 12: new <java.lang.StringBuilder> (33)
OP_DUP, // 15: dup
OP_LDC_S, CADR(Const0005), // 16: ldc "Fibonacci of " (35)
OP_INVOKESHORT_java_lang_StringBuilder__init__Ljava_lang_String_V, // 18: invokespecial java.lang.StringBuilder.<init> (Ljava/lang/String;)V (37)
OP_ILOAD_3, // 21: iload_3
OP_INVOKEVIRTUAL, B(1), LB(MSG_append__I_Ljava_lang_StringBuilder),
// 22: invokevirtual java.lang.StringBuilder.append (I)Ljava/lang/StringBuilder; (40)
OP_LDC_S, CADR(Const0006), // 25: ldc " is " (44)
OP_INVOKEVIRTUAL, B(1), LB(MSG_append__Ljava_lang_String__Ljava_lang_StringBuilder),
// 27: invokevirtual java.lang.StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; (46)
OP_ILOAD_3, // 30: iload_3
OP_INVOKESHORT_haikuvm_bench_Fibonacci32Bit_fib_II, // 31: invokestatic haikuvm.bench.Fibonacci32Bit.fib (I)I (16)
OP_INVOKEVIRTUAL, B(1), LB(MSG_append__I_Ljava_lang_StringBuilder),
// 34: invokevirtual java.lang.StringBuilder.append (I)Ljava/lang/StringBuilder; (40)
OP_LDC_S, CADR(Const0007), // 37: ldc " in " (49)
OP_INVOKEVIRTUAL, B(1), LB(MSG_append__Ljava_lang_String__Ljava_lang_StringBuilder),
// 39: invokevirtual java.lang.StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; (46)
OP_INVOKESHORT_java_lang_System_currentTimeMillis_J, // 42: invokestatic java.lang.System.currentTimeMillis ()J (23)
OP_LLOAD_1, // 45: lload_1
OP_LSUB, // 46: lsub
OP_INVOKEVIRTUAL, B(2), LB(MSG_append__J_Ljava_lang_StringBuilder),
// 47: invokevirtual java.lang.StringBuilder.append (J)Ljava/lang/StringBuilder; (51)
OP_LDC_S, CADR(Const0008), // 50: ldc " ms" (54)
OP_INVOKEVIRTUAL, B(1), LB(MSG_append__Ljava_lang_String__Ljava_lang_StringBuilder),
// 52: invokevirtual java.lang.StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; (46)
OP_INVOKEVIRTUAL, B(0), LB(MSG_toString___Ljava_lang_String), // 55: invokevirtual java.lang.StringBuilder.toString ()Ljava/lang/String; (56)
OP_INVOKEVIRTUAL, B(1), LB(MSG_println__Ljava_lang_String__V), // 58: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (60)
OP_IINC1, B(3), // 61: iinc %3 1
OP_ILOAD_3, // 64: iload_3
OP_BIPUSH, B(30), // 65: bipush 30
OP_IF_ICMPLE, TARGET(9), // 67: if_icmple #9
OP_RETURN, // 70: return
};
const class_t haikuvm_bench_Fibonacci32Bit__class PROGMEM = {
& java_lang_Object__class,
sizeof(haikuvm_bench_Fibonacci32Bit),
0,
};
</code>
~HaikuVM supports two char type sizes for char arrays:
*~HAIKU_CHAR_16 (for JAVA compliants)
*~HAIKU_CHAR_8 (default and most convenient for ~AVRs)
The used char type size for arrays can be configured in the [[HaikuVM.properties]] file or as [[command line option|command line options]].
This will ''not'' affect the size of a basic char type when not stored in an array. This flag was invented only to reduce the size of char arrays.
~HaikuVM supports four memory modes:
#[[32/64 (for JAVA compliants)]]
#[[32/32]]
#[[16/32 (default and most convenient for micros)]]
#[[16/16]]
|!Overview|>|>|>|>|>|>|
|!Type|!32/64|!32/32|!16/32|!16/16|
|byte| 8 |>|>|>|
|char([[*|Configurable 16 or 8 bit char type]])| 16 |>|>|>|
|short| 16 |>|>|>|
|int|32|32|16|16|
|long|64|32|32|16|
|float|32|32|16|16|
|double|64|32|32|16|
|boolean| 8 |>|>|>|>|
The used memory mode can be configured in the [[HaikuVM.properties]] file or as [[command line option|command line options]].
!Step 1 - Import from subversion repository at sourceforge
After this step your eclipse IDE should show something like this:
[img[images/eclipse_step1.png]]
!Step 2 - Setup 'haiku' as external tool
Configure 'haiku.bat' (if on Windows) or 'haiku' (if on Linux) as external tool like this:
[img[images/eclipse_step2.png]]
-v ${file_prompt: a java file}
On Linux, if the first time, don't forget to change shell scripts to have execute permission like this:
<code bash>
chmod +x haikuVM/bin/*
</code>
!Step 3 - Run external tool 'haiku'
When prompted pick a ~JAVA-file (for example 'Blink.java') in:
./haikuVM/examples/src/main/java/arduino/tutorial/Blink.java
Type the text for 'Exceptions'
''Do I need the Arduino Uno Firmware on my ~ATMega328P or/and the Arduino IDE to run ~HaikuVM?''
No, virtually everthing you need for ~HaikuVM comes with the download. (For Linux user see [[here|Linux]].) One critical point is the flash tool. If your device needs an other tool than avrdude, you have to download it from elsewhere.
''All appears to go well, but the program doesn't appear to be running on the ~ATmega. It just sits there silently. Any idea?''
I suggest to start with a basic and simple busy-wait example for AVR which you will find in './haikuVM/examples/src/main/java/avr/tutorial/~BlinkSimple.java'.
Caution: First you have to edit and change it to your needs because this example assumes that the LED is on PORTB.
<code bash>
cd haikuVM/myCProject
/home/bob/haikuVM/bin/haikuc /home/bob/haikuVM/examples/src/main/java/avr/tutorial/BlinkSimple.java
/home/bob/haikuVM/bin/haikulink -v --Config simple010 -o BlinkSimple.hex /home/bob/haikuVM/examples/src/main/java/avr/tutorial/BlinkSimple.java
</code>
''Is it possible to save the output of the command haiku into a trace file?''
Yes, two ways I can think of:
<code bash>
c:\haikuVM\bin\haiku -v --Config simple010 -o BlinkSimple.hex C:\haikuVM\examples\src\main\java\avr\tutorial\BlinkSimple.java >std.out 2>std.err
or
c:\haikuVM\bin\haiku -v --Config simple010 -o BlinkSimple.hex C:\haikuVM\examples\src\main\java\avr\tutorial\BlinkSimple.java >std.outerr 2>&1
</code>
''Is AVRISPMKII supported?''
Not direct. You have to install libusbWin32 first. Then, when using 'usb' as port, has a chance to do the job.
<code bash>
c:\haikuVM\bin\haiku -v --Config simple010 --Config:Port usb -o BlinkSimple.hex C:\haikuVM\examples\src\main\java\avr\tutorial\BlinkSimple.java >std.out 2>std.err
</code>
''Are interrupts enabled?''
Yes, interrupts are enabled by default.
''Is it possible to write my own interrupt routines?''
Yes, see the tutorial about interrupts. Keep in mind that '~TIMER0_OVF_vect' interrupt is reserved for ~HaikuVM.
''I want to change ~HaikuVM code (e.g. '~SimpleOS.c'), what is the best place?''
There are three answers:
#If your change is very project specific then './myCProject/haikuvM/~SimpleOS.c' is the best place.
#If the change is more general then './haikuvM/~SimpleOS.c' is the best place. But this will be overwritten with the download of the next ~HaikuVM version.
#If the change is an enhancment of ~HaikuVM then send it to me or join the project as a developer.
''The probem is, that avr-gcc needs include files (p.e. stdio.h).''
#What's your avr-gcc version? The command 'avr-gcc -version' will print the current version. Compare this with commited versions [[here|Reported Usage]].
#Is your avr-gcc proper installed? Please, do an isolated test of avr-gcc with a simple ~HelloWorld.c program.
* Preemptive threads ([[More ...|Preemptive threads]])
* Exceptions ([[More ...|Exceptions]])
* Synchronization
* double and float support ([[More ...|double and float support]])
* Arrays, including multidimensional ones
* Recursion
* Garbage collection ([[More ...|Garbage collection]])
* Supports inheritance and interfaces
* Runs on AVR ~ATmega8, AVR ~ATmega328p (and Windows, UNIX) ([[More ...|Runs on AVR ATmega8, AVR ATmega328p (and Windows, UNIX)]])
* Configurable 64, 32 or 16 bit data types including [[half precision float]] ([[More ...|Configurable 64, 32 or 16 bit data types]])
* Configurable 16 or 8 bit type for char arrays ([[More ...|Configurable 16 or 8 bit char type]])
* Tested with Suns JAVA 1.6
* Zero Assembler Code ([[More ...|Zero Assembler Code]])
* Compact: Requires only down to 5k Bytes of code memory which includes ~HaikuVM ''and'' your Java program. ([[More ...|Compact]])
* Fast: About 55k Java opcodes per second on 8 Mhz AVR ~ATmega8 ([[More ...|Performance]])
* Needs only 250 Bytes RAM (the rest is for your JAVA application)
* Direct access to memory ([[More ...|Memory Access]])
* Native Interface ([[More ...|Native JAVA Methods]])
!Limitations
* Does not support reflection
* Does not call static class initializers in lazy order (instead they are all called before your main method is called)
* Garbage collection without compacting
* Array objects have no type information
* No typechecking in the bytecode handlers for ASTORE
~HaikuVM uses a simple mark & sweep conservative garbage collector (GC). I chosed this algorithm because of its simplicity. A downside is that non-compacting collectors typically cause fragmentation on the heap. Another is that the mark phase is usually implemented using recursion, which can potentially cause stack overflows. I therefore implemented a slower but non-recursive marking algorithm. Until now ~HaikuVM supports three modes of this GC:
#Stop the world GC (default)
#Incremental GC (slices of work of the GC are done between interpretation of bytecodes)
#No GC (no garbage collection at all)
The GC mode can be configured in the [[HaikuVM.properties]] file or as [[command line option|command line options]].
~HaikuVM at its core is just another JAVA VM for micros (I began with ~AVRs). I decided to go without building an own JAVA runtime. Instead ~HaikuVM is tailor made to use the JAVA runtime coming with [[leJOS]]. ~HaikuVM works by compiling JAVA bytecode to C structs to be compiled by a C cross compiler for your target platform. So, the resulting code is small and fast. ([[More ...|Architecture]])
Software which you need:
#JAVA 1.6
#[[download|https://sourceforge.net/projects/haiku-vm/files/downloads]] and unzip ~HaikuVM into C:\haikuVM
The download includes:
#~HaikuVM
#[[leJOS]] runtime
#~WinAVR 20100110 (Windows C cross compiler for ~AVRs)
''Remark'': On LINUX you have to install a C cross compiler for ~AVRs by hand.
As an option I recommend the Eclipse IDE for development. ([[More ...|Eclipse]])
~HaikuVM just should work out of the box. Unlike other JAVA ~VMs for microcontrollers it adapts automatically to the needs of your JAVA program. For example if your program don't uses doubles then bytecodes and C code for doubles are eliminated automatically. If your program don't uses multi-threading then bytecodes and C code for multi-threading are eliminated automatically. And so on. This means that virtually no fiddling with configurations is needed and memory consumption of ~HaikuVM is always squeezed down to the minimum.
Comments and questions are welcome ([[Contact]]). Keep in mind, this is still a work in progress, so there is more to come: both in terms of features and in terms of optimizations...
//HaikuVM// - A Java VM for ARDUINO and other micros using the leJOS runtime.
These are the currently configured targets:
#pc
#unix
#arduino (default)
#wiring
#asuro
#nanovm
The file ~HaikuVM.properties is looked up in the following two pathes:
*<myCProject>\~HaikuVM.properties
*<~HaikuVM_HOME>\config\~HaikuVM.properties
If you follow the guidelines given here, then this will evaluate to:
*C:\haikuVM\myCProject\~HaikuVM.properties
*C:\haikuVM\config\~HaikuVM.properties
This is how the ~HaikuVM.properties file currently looks like to cover the targets above with default values:
{{{
# Configuration
Config = arduino
aliases.for.Mode = (HAIKU_16_16 16/16) (HAIKU_16_32 16/32) (HAIKU_32_64 32/64) (HAIKU_32_32 32/32)
aliases.for.Char = (HAIKU_CHAR_8 HAIKU_CHAR_1 1 8) (HAIKU_CHAR_16 HAIKU_CHAR_2 2 16)
aliases.for.Target = (atmega328p ATmega328p ATmega328P) (atmega8)
aliases.for.GC = (HAIKU_NoGC) (HAIKU_StopTheWorldGC) (HAIKU_IncrementalGC)
root4c.Extends = root
root4c.MemorySize = 30000
root4c.InitialMainThreadStackSize = 500
root4c.InitialOtherThreadStackSize = 100
root4c.Mode = 32/64
root4c.Char = 16
root4c.GC = HAIKU_StopTheWorldGC
# IncrementalGCSlice is only used if GC=HAIKU_IncrementalGC
root4c.IncrementalGCSlice = 10
root4c.InternalExceptionEnable = NullPointerException | NoSuchMethodError | OutOfMemoryError | ClassCastException | VirtualMachineError | ArrayIndexOutOfBoundsException | StackOverflowError
root4c.InternalExceptionThrow = 1
root4c.Extension = undefined Extension
# relative to HAIKUVM_HOME/target/<Config>/
root4c.VM_BASE = ../../haikuVM
# relative to HAIKUVM_HOME/
root4c.HAIKUVM4C = ./haikuVM
root4c.Output = $(HAIKU_APP_NAME).$(HAIKU_EXTENSION)
#
# Windows
#
pc.Extends = root4c
pc.MicroKernel = haiku.pc.lib.HaikuMicroKernel
#
# Unix with gcc
#
unix.Extends = root4c
unix.MicroKernel = haiku.pc.lib.HaikuMicroKernel
unix.CC_OPT = -DUNIX -O3 -Wall -c -fmessage-length=0 -fpack-struct=1 -MMD -MP
avr.Extends = root4c
avr.MemorySize = 1540
avr.InitialMainThreadStackSize = 142
avr.InitialOtherThreadStackSize = 45
avr.Mode = 16/32
avr.Char = 8
avr.InternalExceptionEnable = NullPointerException | NoSuchMethodError | OutOfMemoryError | ClassCastException | VirtualMachineError
avr.InternalExceptionThrow = 0
avr.CC_OPT = -Wall -Os -fpack-struct -fshort-enums -std=gnu99 -funsigned-char -funsigned-bitfields -ffunction-sections -fdata-sections -mmcu=$(HAIKU_TARGET) -DF_CPU=$(HAIKU_CLOCK)UL -MMD -MP
avr.Extension = hex
#
# ARDUINO wiring: setup(); loop();
#
wiring.Extends = avr
wiring.Target = atmega328p
wiring.Clock = 16000000
wiring.MicroKernel = haiku.avr.lib.arduino.HaikuMicroKernel
# a lot of \ are needed just to get the following:
# avrdude -pm328p -cstk500v1 -P\\\.\\com17 -b57600 -Uflash:w:SimpleThreading.hex:a
# ugly but works:
wiring.Port = \\\\\\.\\com17
wiring.Upload = avrdude -pm328p -cstk500v1 -P$(HAIKU_PORT) -b57600 -Uflash:w:$(HAIKU_OUTPUT):a
#
# ARDUINO: main(); init(); 57600 baud; System.in/out
#
#
arduino.Extends = avr
arduino.Target = atmega328p
arduino.Clock = 16000000
arduino.MicroKernel = haiku.avr.lib.arduino.HaikuMicroKernelEx
# a lot of \ are needed just to get the following:
# avrdude -pm328p -cstk500v1 -P\\\.\\com17 -b57600 -Uflash:w:SimpleThreading.hex:a
# ugly but works:
arduino.Port = \\\\\\.\\com17
arduino.Upload = avrdude -pm328p -cstk500v1 -P$(HAIKU_PORT) -b57600 -Uflash:w:$(HAIKU_OUTPUT):a
#
# ASURO Retro
#
# A little ASURO retro feeling. Here JAVA is very close to program with C and ASURO lib 2.8.0rc1.
#
# Caution:
# - Don't forget the to call Init() in main(..)!
# - No System.out.println(..)!! Instead PrintInt(..), PrintLong(..), SerPrint(..) etc. from ASURO lib!
asuro.Extends = avr
asuro.MemorySize = 700
asuro.Target = atmega8
asuro.Clock = 8000000
asuro.Upload = cmd /c start ASUROFlash155
asuro.MicroKernel = haiku.avr.lib.asuro.lib2_8_0_rc1.HaikuMicroKernel
#
# ASURO NanoVM
#
nanovm.Extends = asuro
nanovm.MicroKernel = haiku.avr.lib.asuro.nanovm.HaikuMicroKernel
}}}
[[leJOS|http://en.wikipedia.org/wiki/LeJOS]] (and [[tinyVM|http://tinyvm.sourceforge.net/]])
[[nanoVM|http://www.harbaum.org/till/nanovm/index.shtml]]
The ~NanoVM is a java virtual machine for the Atmel AVR ~ATmega8 CPU, the member of the AVR CPU family used e.g. in the DLR Asuro robot, manufactured by AREXX engineering. With the ~NanoVM, the Asuro can be programmed in the popular Java language using the standard Sun JDK.
[[Darjeeling|http://darjeeling.sourceforge.net/]]
Darjeeling is a Virtual Machine (VM) for Micro Controller Units (MCU). It can execute a large subset of the Java language on 8- and 16-bit platforms, such as Atmega128 or ~MSP430.
[[Harissa: a compiler from Java bytecode to C|http://www.usenix.org/publications/library/proceedings/coots97/full_papers/muller/muller_html/node3.html]]
[[Toba: A Java-to-C translator|http://www.cs.arizona.edu/projects/sumatra/toba/doc/]]
[[Vishia: java to C translator|http://www.vishia.org/Java2C/]]
[[jcgo: a Java source to C code|http://www.ivmaisoft.com/jcgo/demos.htm]]
[[jc|http://jcvm.sourceforge.net/]]
[[Soot: a Java Optimization Framework|http://www.sable.mcgill.ca/soot/]]
[[gnu classpath|http://www.gnu.org/software/classpath/stories.html]]
[[FLEX is a compiler infrastructure written in Java for Java|http://flex.cscott.net/]]
[[SlimVM: A Small Footprint Java Virtual Machine for Connected Embedded Systems (loads JAVA Lib chunks on demand from a server)|http://www.christianwimmer.at/Publications/Kerschbaumer09a/Kerschbaumer09a.pdf]]
[[dalvik|http://5963581449325967972-a-1802744773732722657-s-sites.googlegroups.com/site/io/dalvik-vm-internals/2008-05-29-Presentation-Of-Dalvik-VM-Internals.pdf?attachauth=ANoY7coivl317Iz9z-vk_afdBjSK6peZRoJRihQ9LLzPR3xEdKyZC7zToSfwFZfSCwsTFNtBp9x4UddWlIlExgrdGV0WIQFkHpXaBatDLur3GWnEV5HjS1k9EKJm_WmCHHPxYY0eEneX038ZcGdwUQi2dYvmGCReR2jBNykZbHkgJov1pfPT1uqz-HEd-3Rwef2x_al4ag5xZ43nsvwXjx5nVIi_I7Dx7MjXVBVrj1-gtoSojMlvv4a-qCyW4aa7PZVrsWzCOfDB&attredirects=0]]
[[jop|http://www.jopdesign.com/perf.jsp]] includes FPGA hardware: picoJAVA, femtoJAVA
[[bajos|http://code.google.com/p/bajos/wiki/FeaturesAndLimits]]
[[Javolution|http://javolution.org/]] real time JAVA
[[JNode|http://www.jnode.org/]]
[[uJ|http://dmitry.co/index.php?p=./04.Thoughts/11. uJ - a micro JVM]]
http://en.wikipedia.org/wiki/List_of_Java_virtual_machines
[[ProGuard|http://proguard.sourceforge.net/]]
~ProGuard is a free Java class file shrinker, optimizer, obfuscator, and preverifier. It detects and removes unused classes, fields, methods, and attributes. It optimizes bytecode and removes unused instructions.
My Linux is UBUNTU 12.04 LTS. And this is what I did as some user 'bob'.
After downloading of haikuVM into '/home/bob/haikuVM' I had to do minor preparation:
<code bash>
# I changed some shell scripts to have execute permission
chmod +x haikuVM/bin/*
# Sorry some scripts may still have '\r\n' instead of '\n' only
dos2unix haikuVM/bin/*
# I found that javac and the AVR tool chain was missing on my UBUNTU
sudo apt-get install openjdk-6-jdk
sudo apt-get install gcc-avr binutils-avr gdb-avr avr-libc avrdude
# I plugged in my ARDUINO Duemilanove and found out that it came on /dev/ttyUSB0
ls -ltr /dev
#sudo usermod -aG dialout bob # does not work for me
sudo chmod a+rw /dev/ttyUSB0
ls -ltr /dev/ttyUSB0
</code>
''Important Note 1''
Until now I have reported success for gcc-avr 4.5.1 and 4.5.3. But no success with 4.6.2.
I then had to modify [[HaikuVM.properties]] to adapt to '/dev/ttyUSB0' by changing this two lines for arduino:
{{{
...
arduino.Port = /dev/ttyUSB0
arduino.Upload = avrdude -pm328p -cstk500v1 -P$(HAIKU_PORT) -b57600 -Uflash:w:$(HAIKU_OUTPUT):a
...
}}}
Finally, I first proceeded step by step:
<code bash>
cd haikuVM/myCProject
/home/bob/haikuVM/bin/haikuc /home/bob/haikuVM/examples/src/main/java/arduino/tutorial/BlinkWithThread.java
/home/bob/haikuVM/bin/haikulink -v --Config arduino -o BlinkWithThread.hex /home/bob/haikuVM/examples/src/main/java/arduino/tutorial/BlinkWithThread
/home/bob/haikuVM/bin/haikuupload BlinkWithThread.hex
</code>
Then I did it again but now, as an alternative, with a one-liner:
<code bash>
/home/bob/haikuVM/bin/haiku -v --Config arduino -o BlinkWithThread.hex /home/bob/haikuVM/examples/src/main/java/arduino/tutorial/BlinkWithThread
</code>
''Important Note 2''
Before you call any of these scripts mentioned above (haikuc, haikulink, haikuupload or haiku) make sure you are in an empty directory! Any empty directory will work, but I suggest to move (cd) into the empty directory 'haikuVM/myCProject' which comes with the download.
Version 1.0.2
[[GettingStarted]]
[[Features]]
[[Code Size|Compact]]
[[Speed|Performance]]
[[Support|http://sourceforge.net/p/haiku-vm/tickets/]]
[[Arduino]]
[[Wiring]]
[[Asuro Robot|Asuro]]
[[leJOS]]
[[Download|https://sourceforge.net/projects/haiku-vm/files/latest/download]]
[[Tutorials]]
[[Reported Usage]]
[[FAQ]]
[[Sourceforge]]
[[Links]]
[[Contact]]
When it comes to microcontroller programming it is often necessary to have direct access to memory and microcontroler registers. Although against the spirit of JAVA but, having methods for memory access is convenient. ~HaikuVM supports two different techniques to access memory:
#Classic: ~HaikuVM offers native getter and setter methods to access memory.
#Annotational: ~HaikuVM allows to annotate static fields as ''@~NativeCVariable#''
!Classic
~HaikuVM offers native getter and setter methods to access memory.
<code java>
package haiku.vm;
public class MemoryAccess {
public static native void setMemory8(int adr, int int8);
public static native void setMemory16(int adr, int int16);
public static native int getMemory8(int adr);
public static native int getMemory16(int adr);
...
}
</code>
Armed with this set of methods and if you know the wanted memory addresses, it's easy to read out e.g. analog data from an ~ATmega8, without being forced to fall back to C code:
<code java>
...
public static final long F_CPU = 8000000L;
public static final int REFS0 = 6;
public static final int ADSC = 6;
public static final int ADIF = 4;
public static final int ADC = (((0x04) + 0x20)); //16Bit
public static final int ADCSRA = (((0x06) + 0x20));
public static final int ADMUX = (((0x07) + 0x20));
...
public static int ReadADC(int mux) {
setMemory8(ADMUX, (1 << REFS0) | mux); // voltage reference with external capacity
setMem(ADCSRA, (1 << ADSC)); // start the AD conversion
while ((getMemory8(ADCSRA) & (1 << ADIF)) == 0) // wait for the end of the AD conversion
;
return getMemory16(ADC); // read 16Bit result
}
</code>
Remark: It's not always easy to find out the proper addresses which are needed for the getter and setter methods.
!Annotational
Static variables annotated with ''@~NativeCVariable#'' (where # is one of 8, 16, 32 or 64) are directly mapped to (equal named and existing) C Variables. So ~HaikuVM will not allocate memory for this variables in the JAVA static memory space.
The example given for the 'Classic' technique may now be rewritten like this:
<code java>
...
public static final long F_CPU = 8000000L;
public static final int REFS0 = 6;
public static final int ADSC = 6;
public static final int ADIF = 4;
@NativeCVariable16
public static volatile int ADC;
@NativeCVariable8
public static volatile int ADCSRA;
@NativeCVariable8
public static volatile int ADMUX;
...
public static int ReadADC(int mux) {
ADMUX = (1 << REFS0) | mux; // voltage reference with external capacity
ADCSRA |= (1 << ADSC); // start the AD conversion
while ((ADCSRA & (1 << ADIF)) == 0) // wait for the end of the AD conversion
;
return ADC; // read 16Bit result
}
</code>
Here the variables ADC, ADCSRA and ADMUX (with exactly this names) have to exist in the underlying C code or libraries. (This condition is fullfilled for AVR projects because this variables are declared somewhere in include files given for ~AVRs.)
Using this technique allows you to copy&past many C examples to JAVA.
I have to mention a common pitfall. Reading a 8Bit C variable into a JAVA int variable is possible. ~HaikVM handles the incoming 8Bit C value as a (signed) byte type which causes the sign to be propagated to the int. If this is not what you want then mask with 0xff. Like shown in the following snippet from a Two Wire module:
<code java>
...
public static final int TWEA = 0x06;
public static final int TWINT = 0x07;
public static final int TWEN = 0x02;
@NativeCVariable8
public static volatile int TWCR;
@NativeCVariable8
public static volatile int TWDR;
...
static int i2c_read_byte() {
TWCR = (1 << TWINT) | (1 << TWEA) | (1 << TWEN); // start data reception, transmit ACK
while (((TWCR & (1 << TWINT))==0));
return TWDR & 0xff; // mask with 0xff to unmask sign
}
</code>
!A Word of Warning
#The size of ~HaikuVM JAVA types like int and long depends on your [[Memory Mode|Configurable 64, 32 or 16 bit data types]]. Where these memory access methods don't depend on this. For example, if you call getMemory16(..) the result is always truncated to 16 Bit independent of your selected [[Memory Mode|Configurable 64, 32 or 16 bit data types]]. In other words, type sizes of ~HaikuVM JAVA variables and C variables are independent.
#Native C variables are out of scope for the garbage collector. This means, be extra careful if you store object pointers into C variables.
For example currentTimeMillis() is defined as ''native'' in java.lang.System:
<code java>
package java.lang;
...
public class System {
...
/**
* Returns the current time in milliseconds.
* This is the number of milliseconds since the AVR has been on.
*/
public static native long currentTimeMillis();
...
}
</code>
~HaikuVM produces the following snippet in file ./haikuC/haikuJNI.c for you.
<code c>
/**
* currentTimeMillis()J
*/
void native_java_lang_System_currentTimeMillis_J(void) {
pushTop(); // Save variable top onto stack.
{
jobject obj = NULL;
JNIEnv *env = NULL;
top.j = Java_java_lang_System_currentTimeMillis(env, obj);
}
// Variable top holds the long return value. We only need to push the lower half.
pushTop0();
}
</code>
In this case C function //native_java_lang_~System_currentTimeMillis_J(void)// interfaces between the native JAVA method (and the JAVA stack) and the JNI C function //~Java_java_lang_System_currentTimeMillis(~JNIEnv *env, jobject obj)// which has to implement it.
So, file ./haikuC/haikuJNI.c is a good resource for your C function templates because ~HaikuVM produces a snippet for ''every'' native JAVA method found in your program.
!!2013/03/03: Version 1.0.2 is released.
Including a tutorial about JNI. ([[More ...|Tutorials]])
!!2013/02/09: Better Linux support.
Tested on UBUNTU 12.04 LTE. ([[More ...|Linux]])
!!2012/01/01: Single line command interface
Enter one line to compile, upload and run your JAVA program (let's say '~BlinkWithThread') to an Arduino connected on port com5:
<code bash>
cd haikuVM\myCProject
C:\haikuVM\bin\haiku -v --Config arduino --Config:Port \\\.\com5 -o BlinkWithThread.hex C:\haikuVM\examples\src\main\java\arduino\tutorial\BlinkWithThread.java
</code>
Or Linux:
<code bash>
cd haikuVM/myCProject
/home/bob/haikuVM/bin/haiku -v --Config arduino --Config:Port /dev/ttyUSB0 /home/bob/haikuVM/examples/src/main/java/arduino/tutorial/BlinkWithThread.java
</code>
!!2012/01/01: Direct access to memory and microcontroller registers
Static fields annotated with ''@~NativeCVariable#'' (where # is one of 8, 16, 32 or 64) are directly mapped to (equal named and existing) C variables. ([[More ...|Memory Access]])
<code java>
...
public static final int UDRE0 = 5;
@NativeCVariable8 // tells HaikuVM to map UCSR0A to a 8Bit C variable called UCSR0A
public static volatile int UCSR0A;
@NativeCVariable8 // tells HaikuVM to map UDR0 to a 8Bit C variable called UDR0
public static volatile int UDR0;
...
public void write(int b) {
while ( (UCSR0A & (1 << UDRE0)) == 0 ) /*poll*/ ;
UDR0=b;
};
</code>
Most of the code written for microcontrollers was originally written in C. This direct access to memory technique allows you to virtually copy&past this to JAVA.
!Performance of ~HaikuVM (Revision 52)
The performance test was made on an ''Atmega328p'' 16Mhz with the following JAVA program:
<code java>
public class Fibonacci32Bit {
static int fib(int n) {
if(n < 2)
return 1;
else
return fib(n-2) + fib(n-1);
}
public static void main(String[] args) {
long t0 = System.currentTimeMillis();
for(int i=0;i<=30;i++)
System.out.println("Fibonacci of "+i+" is "+fib(i)+" in "+(System.currentTimeMillis()-t0)+" ms");
}
}
</code>
The program was compiled, linked und uploaded as follows:
{{{
C:\haikuVM\bin\haiku --Config arduino --Mode 32/64 C:\haikuVM\haikuBench\src\main\java\haikuvm\bench\Fibonacci32Bit
}}}
During cross compiling with ~WinAVR 20100110 the optimization level was set for size: -Os
Result:
{{{
Fibonacci of 0 is 1 in 73 ms
Fibonacci of 1 is 1 in 127 ms
Fibonacci of 2 is 2 in 194 ms
Fibonacci of 3 is 3 in 261 ms
Fibonacci of 4 is 5 in 326 ms
Fibonacci of 5 is 8 in 391 ms
Fibonacci of 6 is 13 in 458 ms
Fibonacci of 7 is 21 in 535 ms
Fibonacci of 8 is 34 in 610 ms
Fibonacci of 9 is 55 in 694 ms
Fibonacci of 10 is 89 in 787 ms
Fibonacci of 11 is 144 in 888 ms
Fibonacci of 12 is 233 in 1010 ms
Fibonacci of 13 is 377 in 1167 ms
Fibonacci of 14 is 610 in 1369 ms
Fibonacci of 15 is 987 in 1653 ms
Fibonacci of 16 is 1597 in 2046 ms
Fibonacci of 17 is 2584 in 2633 ms
Fibonacci of 18 is 4181 in 3538 ms
Fibonacci of 19 is 6765 in 4934 ms
Fibonacci of 20 is 10946 in 7133 ms
Fibonacci of 21 is 17711 in 10643 ms
Fibonacci of 22 is 28657 in 16259 ms
Fibonacci of 23 is 46368 in 25300 ms
Fibonacci of 24 is 75025 in 39851 ms
Fibonacci of 25 is 121393 in 63353 ms
Fibonacci of 26 is 196418 in 101303 ms
Fibonacci of 27 is 317811 in 162640 ms
Fibonacci of 28 is 514229 in 261832 ms
Fibonacci of 29 is 832040 in 422249 ms
Fibonacci of 30 is 1346269 in 681731 ms
}}}
So this JAVA program running with ~HaikuVM Revision 52 needed ''681731 ms'' for fib(30). ([[Compare with results from newer revisions.|Performance History]])
!!Compared with plain C running on ARDUINO Due
This is the competing C program for fib(30):
<code c>
int32_t fib(int32_t n) {
if(n < 2)
return 1;
else
return fib(n-2) + fib(n-1);
}
int main() {
int32_t i;
long t0 = millis();
for(i=0;i<=30;i++) {
printf("Fibonacci of %ld is %ld in %ld ms\n", i, fib(i), (long)(millis()-t0));
}
return 0;
}
</code>
This C program, again compiled with ~WinAVR 20100110 -Os (optimize for size), needed ''19494 ms''.
Compiled with -O3 (optimize for speed) needed ''16825 ms''.
Conclusion: This (specific) JAVA program runnning with ~HaikuVM is a ''factor 35 (or 41) slower'' than the corresponding plain C program.
!!Compared with leJOS
Because ~HaikuVM is not ported on NXJ (until now), I had to compare it in an indirect way. For this I put a question about performance into the leJOS forum ([[see ...|http://lejos.sourceforge.net/forum/viewtopic.php?f=7&t=2989&p=14800&hilit=performance#p14800]]).
Thankfully I got this answer:
"Anyway it turns out that ~RobotC like NXC does not support recursion so the fib test is not looking like a good test case. But I ran it anyway in Java the total time taken for up to and including fib 30 is ''197566'', the same code in gcc based C takes ''3432ms'', so the native C code in this instance is 57 times faster."
So there is a chance that ~HaikuVM would be faster than leJOS by a factor of 1,6 (or 1,4). But this comparision must be taken with care.
!!Compared with JAVA 1.6 under Windows XP 32Bit
The program was compiled and linked as follows:
{{{haiku -target WIN32 -r Fibonacci32Bit}}}
I used the Microsoft Visual C++ 2005 compiler. The final runtime was ''1204 ms'' on my computer.
Pure JAVA 1.6 needed ''656 ms''. To be fair I ran it in pure interpreter mode like this:
{{{java -Xint Fibonacci32Bit}}}
Conclusion: ~HaikuVM is about a factor of 2 slower than pure JAVA (interpreting). Not bad for an application not using assembler and using a data alignment set to 1 byte.
Because I was curious I ran it with JAVA 1.6 Hotspot and it needed only ''47ms'' for fib(30) on my computer.
Cross compiled with ~WinAVR 20100110 the optimization level was set for size: -Os
!Revision 232 fib(30)
Program: 19656 bytes (60.0% Full)
Data: 1834 bytes (89.6% Full)
{{{
Fibonacci of 0 is 1 in 87 ms
Fibonacci of 1 is 1 in 147 ms
Fibonacci of 2 is 2 in 207 ms
Fibonacci of 3 is 3 in 268 ms
Fibonacci of 4 is 5 in 331 ms
Fibonacci of 5 is 8 in 392 ms
Fibonacci of 6 is 13 in 459 ms
Fibonacci of 7 is 21 in 527 ms
Fibonacci of 8 is 34 in 597 ms
Fibonacci of 9 is 55 in 672 ms
Fibonacci of 10 is 89 in 755 ms
Fibonacci of 11 is 144 in 863 ms
Fibonacci of 12 is 233 in 976 ms
Fibonacci of 13 is 377 in 1117 ms
Fibonacci of 14 is 610 in 1282 ms
Fibonacci of 15 is 987 in 1508 ms
Fibonacci of 16 is 1597 in 1839 ms
Fibonacci of 17 is 2584 in 2316 ms
Fibonacci of 18 is 4181 in 3023 ms
Fibonacci of 19 is 6765 in 4126 ms
Fibonacci of 20 is 10946 in 5855 ms
Fibonacci of 21 is 17711 in 8580 ms
Fibonacci of 22 is 28657 in 12938 ms
Fibonacci of 23 is 46368 in 19941 ms
Fibonacci of 24 is 75025 in 31202 ms
Fibonacci of 25 is 121393 in 49355 ms
Fibonacci of 26 is 196418 in 78669 ms
Fibonacci of 27 is 317811 in 126030 ms
Fibonacci of 28 is 514229 in 202598 ms
Fibonacci of 29 is 832040 in 326417 ms
Fibonacci of 30 is 1346269 in 526701 ms
}}}
!Revision 180 fib(30)
Program: 19636 bytes (59.9% Full)
Data: 1834 bytes (89.6% Full)
{{{
Fibonacci of 0 is 1 in 99 ms
Fibonacci of 1 is 1 in 163 ms
Fibonacci of 2 is 2 in 229 ms
Fibonacci of 3 is 3 in 293 ms
Fibonacci of 4 is 5 in 354 ms
Fibonacci of 5 is 8 in 420 ms
Fibonacci of 6 is 13 in 484 ms
Fibonacci of 7 is 21 in 562 ms
Fibonacci of 8 is 34 in 636 ms
Fibonacci of 9 is 55 in 713 ms
Fibonacci of 10 is 89 in 815 ms
Fibonacci of 11 is 144 in 912 ms
Fibonacci of 12 is 233 in 1026 ms
Fibonacci of 13 is 377 in 1181 ms
Fibonacci of 14 is 610 in 1360 ms
Fibonacci of 15 is 987 in 1598 ms
Fibonacci of 16 is 1597 in 1943 ms
Fibonacci of 17 is 2584 in 2432 ms
Fibonacci of 18 is 4181 in 3173 ms
Fibonacci of 19 is 6765 in 4312 ms
Fibonacci of 20 is 10946 in 6084 ms
Fibonacci of 21 is 17711 in 8912 ms
Fibonacci of 22 is 28657 in 13429 ms
Fibonacci of 23 is 46368 in 20669 ms
Fibonacci of 24 is 75025 in 32314 ms
Fibonacci of 25 is 121393 in 51088 ms
Fibonacci of 26 is 196418 in 81401 ms
Fibonacci of 27 is 317811 in 130386 ms
Fibonacci of 28 is 514229 in 209579 ms
Fibonacci of 29 is 832040 in 337641 ms
Fibonacci of 30 is 1346269 in 544781 ms
}}}
~HaikuVM implements preemptive multithreading with atomic JVM instructions. Timeslicing is done by performing a context switch every 4 shedule-instructions (listed below). ~HaikuVM is preemptive on bytecode level not on machine instruction level. As a consequence every bytecode is executed atomar (and so are all native methods). ~HaikuVM supports thread synchronization with the Java ''synchronized'' keyword. Because the vast majority of objects will never act as monitors, monitor counters are not stored in the object headers (as in some other implementations) but rather live in a separate construct to further save space.
~HaikuVM shedules threads after selected bytecodes and specific native methods (called shedule-instructions):
* at branch bytecodes (either backward or forward)
* any invoke* bytecode (e.g. invokestatic)
* any *return bytecode (e.g. ireturn)
* Thread.yield()
* Thread.sleep(..)
* Thread.join()
* wait(..)
* synchronized methods or synchronized blocks
!Version 1.0.2 (Revision: 311) (Date: 2013/03/03)
#Bug fixed: ldc() for ints (~LDC_I) stored an int at wrong place in top.
#Bug fixed: now C #includes follow JAVA nested static scopes.
#JNI is now prepared to go public. ([[More ...|Tutorial JNI]])
#Correct millisecond timing now works for a wider range of Mz. ([[More ...|Tutorial Timing]])
#Bug fixed: Stdout and Stderr of shell commands were merged characterwise.
#Linux: No need for dos2unix any more.
!Version 1.0.1 (Revision: 285) (Date: 2013/02/11)
#Bug fixed: synchronized method failed if it had more then one RETURN.
#Entering com ports is more homogen between Windows and Linux now.
!Version 1.0.0 (Revision: 277) (Date: 2013/02/09)
#Better Linux support. ([[More ...|Linux]])
#Less C compiler warnings during cross compile phase
#~JUnits for many major features
#Basic AVR tutorial
!Version 0.9.5 (Revision: 258) (Date: 2013/01/01)
#Support for annotational [[Memory Access]]
#Support for numeric constrains for adapt to Memory models (~DBL_CNSTR, ~FLT_CNSTR, ~LONG_CNSTR, ~INT_CNSTR)
#First (remote) ~JUnit
#Bug fixed: Support for synchronized non-void methods
#Bug fixed: a quote in a String "'" is now supported.
#Less cross compiler warnings.
!Version 0.9.4 (Revision: 232) (Date: 2012/12/02)
#~WinAVR 20100110 included in download
#Support for arduino-1.0.2
#[[haiku]] command now supports {{{--Config:Port <port>}}}
#Reduced compiler warnings
#Moved available() and read() to ~HardwareSerial.
#Added AVR Two Wire constants
*OS
**Windows
**UBUNTU 12.04 LTS; 12.10
**Mac OS X Mountain Lion
*Microcontroller
**~ATmega328p
**Atmega8
**Atmega16
*Plattforms
**arduino
**ASURO
**NIBOBEE
**Gertboard
*Software
**Java
***oracle jdk1.6.0
***java 7
**Crosscompiler
***avr-gcc
****4.5.1
****4.5.3
****4.3.3 (~WinAVR 20100110)
**** (4.6.2 has a reported failure)
**Flash Tools
***avrdude
***~ASUROFlash155
***~Nibobee-Programmer
Until now ~HaikuVM is successfully testet against the following targets:
#AVR ~ATmega8
#AVR ~ATmega328p
#Windows XP 32Bit
#UNIX (Ubuntu 64Bit)
A Java VM for ARDUINO and other micros using the leJOS runtime.
[[Summary|http://sourceforge.net/projects/haiku-vm/]]
[[Download|https://sourceforge.net/projects/haiku-vm/files/downloads/]]
Subversion [[RO|https://sourceforge.net/p/haiku-vm/code/]] [[HTTPS|https://svn.code.sf.net/p/haiku-vm/code/trunk]]
.tiddler {padding:1em 1em 0; font-size:1.2em;border-bottom-style:solid; border-width:5px;border-color:#04b;}
.viewer pre {padding:0.5em; margin-left:0.5em; font-size:.9em; line-height:0.9em; overflow:auto;}
div.tiddler .subtitle {font-size: 7pt;}
h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::Foreground]]; background:transparent;}
.title {color:[[ColorPalette::Foreground]];}
[[StyleSheetSyntaxHighlighter]]
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}
h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}
.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}
.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}
.tabSelected {color:[[ColorPalette::PrimaryDark]];
background:[[ColorPalette::TertiaryPale]];
border-left:1px solid [[ColorPalette::TertiaryLight]];
border-top:1px solid [[ColorPalette::TertiaryLight]];
border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}
#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}
.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}
.wizard .notChanged {background:transparent;}
.wizard .changedLocally {background:#80ff80;}
.wizard .changedServer {background:#8080ff;}
.wizard .changedBoth {background:#ff8080;}
.wizard .notFound {background:#ffff80;}
.wizard .putToServer {background:#ff80ff;}
.wizard .gotFromServer {background:#80ffff;}
#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}
.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}
.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}
.tiddler .defaultCommand {font-weight:bold;}
.shadow .title {color:[[ColorPalette::TertiaryDark]];}
.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}
.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}
.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}
.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}
.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}
.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}
.imageLink, #displayArea .imageLink {background:transparent;}
.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}
.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}
.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}
.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}
.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}
.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}
.readOnly {background:[[ColorPalette::TertiaryPale]];}
#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:alpha(opacity=60);}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}
body {font-size: .75em; font-family:arial,helvetica; margin:0; padding:0;}
h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}
hr {height:1px;}
a {text-decoration:none;}
dt {font-weight:bold;}
ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}
.txtOptionInput {width:11em;}
#contentWrapper .chkOptionInput {border:0;}
.externalLink {text-decoration:underline;}
.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}
.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}
/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}
#mainMenu .tiddlyLinkExisting,
#mainMenu .tiddlyLinkNonExisting,
#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}
.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0 1em 1em; left:0; top:0;}
.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}
#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}
#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 0.3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}
.wizard {padding:0.1em 1em 0 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0; margin:0.4em 0 0.2em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0 0; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0;}
.wizardFooter .status {padding:0 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em;}
#messageArea {position:fixed; top:2em; right:0; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em;}
#messageArea a {text-decoration:underline;}
.tiddlerPopupButton {padding:0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em; margin:0;}
.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}
.tabset {padding:1em 0 0 0.5em;}
.tab {margin:0 0 0 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}
#contentWrapper {display:block;}
#splashScreen {display:none;}
#displayArea {margin:1em 17em 0 14em;}
.toolbar {text-align:right; font-size:.9em;}
.tiddler {padding:1em 1em 0;}
.missing .viewer,.missing .title {font-style:italic;}
.title {font-size:1.6em; font-weight:bold;}
.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}
.tiddler .button {padding:0.2em 0.4em;}
.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}
.footer {font-size:.9em;}
.footer li {display:inline;}
.annotation {padding:0.5em; margin:0.5em;}
* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0 0.25em; padding:0 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}
.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0 3px 0 3px;}
.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}
.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0; font-size:.9em;}
.editorFooter .button {padding-top:0; padding-bottom:0;}
.fieldsetFix {border:0; padding:0; margin:1px 0px;}
.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}
* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0; right:0;}
#backstageButton a {padding:0.1em 0.4em; margin:0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; width:90%; margin-left:3em; padding:1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}
.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for ~SyntaxHighlighter
***/
/*{{{*/
.dp-highlighter
{
font-family: "Consolas", "Courier New", Courier, mono, serif;
font-size: 12px;
background-color: #E7E5DC;
width: 99%;
overflow: auto;
margin: 18px 0 18px 0 !important;
padding-top: 1px; /* adds a little border on top when controls are hidden */
}
/* clear styles */
.dp-highlighter ol,
.dp-highlighter ol li,
.dp-highlighter ol li span
{
margin: 0;
padding: 0;
border: none;
}
.dp-highlighter a,
.dp-highlighter a:hover
{
background: none;
border: none;
padding: 0;
margin: 0;
}
.dp-highlighter .bar
{
padding-left: 45px;
}
.dp-highlighter.collapsed .bar,
.dp-highlighter.nogutter .bar
{
padding-left: 0px;
}
.dp-highlighter ol
{
list-style: decimal; /* for ie */
background-color: #fff;
margin: 0px 0px 1px 45px !important; /* 1px bottom margin seems to fix occasional Firefox scrolling */
padding: 0px;
color: #5C5C5C;
}
.dp-highlighter.nogutter ol,
.dp-highlighter.nogutter ol li
{
list-style: none !important;
margin-left: 0px !important;
}
.dp-highlighter ol li,
.dp-highlighter .columns div
{
list-style: decimal-leading-zero; /* better look for others, override cascade from OL */
list-style-position: outside !important;
border-left: 3px solid #6CE26C;
background-color: #F8F8F8;
color: #5C5C5C;
padding: 0 3px 0 10px !important;
margin: 0 !important;
line-height: 14px;
}
.dp-highlighter.nogutter ol li,
.dp-highlighter.nogutter .columns div
{
border: 0;
}
.dp-highlighter .columns
{
background-color: #F8F8F8;
color: gray;
overflow: hidden;
width: 100%;
}
.dp-highlighter .columns div
{
padding-bottom: 5px;
}
.dp-highlighter ol li.alt
{
background-color: #FFF;
color: inherit;
}
.dp-highlighter ol li span
{
color: black;
background-color: inherit;
}
/* Adjust some properties when collapsed */
.dp-highlighter.collapsed ol
{
margin: 0px;
}
.dp-highlighter.collapsed ol li
{
display: none;
}
/* Additional modifications when in print-view */
.dp-highlighter.printing
{
border: none;
}
.dp-highlighter.printing .tools
{
display: none !important;
}
.dp-highlighter.printing li
{
display: list-item !important;
}
/* Styles for the tools */
.dp-highlighter .tools
{
padding: 3px 8px 3px 10px;
font: 9px Verdana, Geneva, Arial, Helvetica, sans-serif;
color: silver;
background-color: #f8f8f8;
padding-bottom: 10px;
border-left: 3px solid #6CE26C;
}
.dp-highlighter.nogutter .tools
{
border-left: 0;
}
.dp-highlighter.collapsed .tools
{
border-bottom: 0;
}
.dp-highlighter .tools a
{
font-size: 9px;
color: #a0a0a0;
background-color: inherit;
text-decoration: none;
margin-right: 10px;
}
.dp-highlighter .tools a:hover
{
color: red;
background-color: inherit;
text-decoration: underline;
}
/* About dialog styles */
.dp-about { background-color: #fff; color: #333; margin: 0px; padding: 0px; }
.dp-about table { width: 100%; height: 100%; font-size: 11px; font-family: Tahoma, Verdana, Arial, sans-serif !important; }
.dp-about td { padding: 10px; vertical-align: top; }
.dp-about .copy { border-bottom: 1px solid #ACA899; height: 95%; }
.dp-about .title { color: red; background-color: inherit; font-weight: bold; }
.dp-about .para { margin: 0 0 4px 0; }
.dp-about .footer { background-color: #ECEADB; color: #333; border-top: 1px solid #fff; text-align: right; }
.dp-about .close { font-size: 11px; font-family: Tahoma, Verdana, Arial, sans-serif !important; background-color: #ECEADB; color: #333; width: 60px; height: 22px; }
/* Language specific styles */
.dp-highlighter .comment, .dp-highlighter .comments { color: #008200; background-color: inherit; }
.dp-highlighter .string { color: blue; background-color: inherit; }
.dp-highlighter .keyword { color: #069; font-weight: bold; background-color: inherit; }
.dp-highlighter .preprocessor { color: gray; background-color: inherit; }
/*}}}*/
/***
!Metadata:
|''Name:''|SyntaxHighlighterPlugin|
|''Description:''|Code Syntax Highlighter Plugin for TiddlyWiki.|
|''Version:''|1.1.3|
|''Date:''|Oct 24, 2008|
|''Source:''|http://www.coolcode.cn/show-310-1.html|
|''Author:''|Ma Bingyao (andot (at) ujn (dot) edu (dot) cn)|
|''License:''|[[GNU Lesser General Public License|http://www.gnu.org/licenses/lgpl.txt]]|
|''~CoreVersion:''|2.4.1|
|''Browser:''|Firefox 1.5+; InternetExplorer 6.0; Safari; Opera; Chrome; etc.|
!Syntax:
{{{
<code options>
codes
</code>
}}}
!Examples:
{{{
<code java>
public class HelloWorld {
public static void main(String args[]) {
System.out.println("HelloWorld!");
}
}
</code>
}}}
!Revision History:
|''Version''|''Date''|''Note''|
|1.1.2|Oct 15, 2008|Optimize Highlight|
|1.0.0|Oct 13, 2008|Initial release|
!Code section:
***/
//{{{
var dp={sh:{Toolbar:{},Utils:{},RegexLib:{},Brushes:{},Strings:{AboutDialog:"<html><head><title>About...</title></head><body class=\"dp-about\"><table cellspacing=\"0\"><tr><td class=\"copy\"><p class=\"title\">dp.SyntaxHighlighter</div><div class=\"para\">Version: {V}</p><p><a href=\"http://www.dreamprojections.com/syntaxhighlighter/?ref=about\" target=\"_blank\">http://www.dreamprojections.com/syntaxhighlighter</a></p>©2004-2007 Alex Gorbatchev.</td></tr><tr><td class=\"footer\"><input type=\"button\" class=\"close\" value=\"OK\" onClick=\"window.close()\"/></td></tr></table></body></html>"},ClipboardSwf:null,Version:"1.5.1"}};dp.SyntaxHighlighter=dp.sh;dp.sh.Toolbar.Commands={ExpandSource:{label:"+ expand source",check:function($){return $.collapse},func:function($,_){$.parentNode.removeChild($);_.div.className=_.div.className.replace("collapsed","")}},ViewSource:{label:"view plain",func:function($,_){var A=dp.sh.Utils.FixForBlogger(_.originalCode).replace(/</g,"<"),B=window.open("","_blank","width=750, height=400, location=0, resizable=1, menubar=0, scrollbars=0");B.document.write("<textarea style=\"width:99%;height:99%\">"+A+"</textarea>");B.document.close()}},CopyToClipboard:{label:"copy to clipboard",check:function(){return window.clipboardData!=null||dp.sh.ClipboardSwf!=null},func:function($,A){var B=dp.sh.Utils.FixForBlogger(A.originalCode).replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&");if(window.clipboardData)window.clipboardData.setData("text",B);else if(dp.sh.ClipboardSwf!=null){var _=A.flashCopier;if(_==null){_=document.createElement("div");A.flashCopier=_;A.div.appendChild(_)}_.innerHTML="<embed src=\""+dp.sh.ClipboardSwf+"\" FlashVars=\"clipboard="+encodeURIComponent(B)+"\" width=\"0\" height=\"0\" type=\"application/x-shockwave-flash\"></embed>"}alert("The code is in your clipboard now")}},PrintSource:{label:"print",func:function($,B){var _=document.createElement("IFRAME"),A=null;_.style.cssText="position:absolute;width:0px;height:0px;left:-500px;top:-500px;";document.body.appendChild(_);A=_.contentWindow.document;dp.sh.Utils.CopyStyles(A,window.document);A.write("<div class=\""+B.div.className.replace("collapsed","")+" printing\">"+B.div.innerHTML+"</div>");A.close();_.contentWindow.focus();_.contentWindow.print();alert("Printing...");document.body.removeChild(_)}},About:{label:"?",func:function(_){var A=window.open("","_blank","dialog,width=300,height=150,scrollbars=0"),$=A.document;dp.sh.Utils.CopyStyles($,window.document);$.write(dp.sh.Strings.AboutDialog.replace("{V}",dp.sh.Version));$.close();A.focus()}}};dp.sh.Toolbar.Create=function(B){var A=document.createElement("DIV");A.className="tools";for(var _ in dp.sh.Toolbar.Commands){var $=dp.sh.Toolbar.Commands[_];if($.check!=null&&!$.check(B))continue;A.innerHTML+="<a href=\"#\" onclick=\"dp.sh.Toolbar.Command('"+_+"',this);return false;\">"+$.label+"</a>"}return A};dp.sh.Toolbar.Command=function(_,$){var A=$;while(A!=null&&A.className.indexOf("dp-highlighter")==-1)A=A.parentNode;if(A!=null)dp.sh.Toolbar.Commands[_].func($,A.highlighter)};dp.sh.Utils.CopyStyles=function(A,_){var $=_.getElementsByTagName("link");for(var B=0;B<$.length;B++)if($[B].rel.toLowerCase()=="stylesheet")A.write("<link type=\"text/css\" rel=\"stylesheet\" href=\""+$[B].href+"\"></link>")};dp.sh.Utils.FixForBlogger=function($){return(dp.sh.isBloggerMode==true)?$.replace(/<br\s*\/?>|<br\s*\/?>/gi,"\n"):$};dp.sh.RegexLib={MultiLineCComments:new RegExp("/\\*[\\s\\S]*?\\*/","gm"),SingleLineCComments:new RegExp("//.*$","gm"),SingleLinePerlComments:new RegExp("#.*$","gm"),DoubleQuotedString:new RegExp("\"(?:\\.|(\\\\\\\")|[^\\\"\"\\n])*\"","g"),SingleQuotedString:new RegExp("'(?:\\.|(\\\\\\')|[^\\''\\n])*'","g")};dp.sh.Match=function(_,$,A){this.value=_;this.index=$;this.length=_.length;this.css=A};dp.sh.Highlighter=function(){this.noGutter=false;this.addControls=true;this.collapse=false;this.tabsToSpaces=true;this.wrapColumn=80;this.showColumns=true};dp.sh.Highlighter.SortCallback=function($,_){if($.index<_.index)return-1;else if($.index>_.index)return 1;else if($.length<_.length)return-1;else if($.length>_.length)return 1;return 0};dp.sh.Highlighter.prototype.CreateElement=function(_){var $=document.createElement(_);$.highlighter=this;return $};dp.sh.Highlighter.prototype.GetMatches=function(_,B){var $=0,A=null;while((A=_.exec(this.code))!=null)this.matches[this.matches.length]=new dp.sh.Match(A[0],A.index,B)};dp.sh.Highlighter.prototype.AddBit=function($,A){if($==null||$.length==0)return;var C=this.CreateElement("SPAN");$=$.replace(/ /g," ");$=$.replace(/</g,"<");$=$.replace(/\n/gm," <br>");if(A!=null){if((/br/gi).test($)){var _=$.split(" <br>");for(var B=0;B<_.length;B++){C=this.CreateElement("SPAN");C.className=A;C.innerHTML=_[B];this.div.appendChild(C);if(B+1<_.length)this.div.appendChild(this.CreateElement("BR"))}}else{C.className=A;C.innerHTML=$;this.div.appendChild(C)}}else{C.innerHTML=$;this.div.appendChild(C)}};dp.sh.Highlighter.prototype.IsInside=function(_){if(_==null||_.length==0)return false;for(var A=0;A<this.matches.length;A++){var $=this.matches[A];if($==null)continue;if((_.index>$.index)&&(_.index<$.index+$.length))return true}return false};dp.sh.Highlighter.prototype.ProcessRegexList=function(){for(var $=0;$<this.regexList.length;$++)this.GetMatches(this.regexList[$].regex,this.regexList[$].css)};dp.sh.Highlighter.prototype.ProcessSmartTabs=function(E){var B=E.split("\n"),$="",D=4,A="\t";function _(A,E,_){var B=A.substr(0,E),C=A.substr(E+1,A.length),$="";for(var D=0;D<_;D++)$+=" ";return B+$+C}function C(B,C){if(B.indexOf(A)==-1)return B;var D=0;while((D=B.indexOf(A))!=-1){var $=C-D%C;B=_(B,D,$)}return B}for(var F=0;F<B.length;F++)$+=C(B[F],D)+"\n";return $};dp.sh.Highlighter.prototype.SwitchToList=function(){var C=this.div.innerHTML.replace(/<(br)\/?>/gi,"\n"),B=C.split("\n");if(this.addControls==true)this.bar.appendChild(dp.sh.Toolbar.Create(this));if(this.showColumns){var A=this.CreateElement("div"),_=this.CreateElement("div"),E=10,G=1;while(G<=150)if(G%E==0){A.innerHTML+=G;G+=(G+"").length}else{A.innerHTML+="·";G++}_.className="columns";_.appendChild(A);this.bar.appendChild(_)}for(var G=0,D=this.firstLine;G<B.length-1;G++,D++){var $=this.CreateElement("LI"),F=this.CreateElement("SPAN");$.className=(G%2==0)?"alt":"";F.innerHTML=B[G]+" ";$.appendChild(F);this.ol.appendChild($)}this.div.innerHTML=""};dp.sh.Highlighter.prototype.Highlight=function(C){function A($){return $.replace(/^\s*(.*?)[\s\n]*$/g,"$1")}function $($){return $.replace(/\n*$/,"").replace(/^\n*/,"")}function _(B){var E=dp.sh.Utils.FixForBlogger(B).split("\n"),C=new Array(),D=new RegExp("^\\s*","g"),$=1000;for(var F=0;F<E.length&&$>0;F++){if(A(E[F]).length==0)continue;var _=D.exec(E[F]);if(_!=null&&_.length>0)$=Math.min(_[0].length,$)}if($>0)for(F=0;F<E.length;F++)E[F]=E[F].substr($);return E.join("\n")}function D(A,$,_){return A.substr($,_-$)}var F=0;if(C==null)C="";this.originalCode=C;this.code=$(_(C));this.div=this.CreateElement("DIV");this.bar=this.CreateElement("DIV");this.ol=this.CreateElement("OL");this.matches=new Array();this.div.className="dp-highlighter";this.div.highlighter=this;this.bar.className="bar";this.ol.start=this.firstLine;if(this.CssClass!=null)this.ol.className=this.CssClass;if(this.collapse)this.div.className+=" collapsed";if(this.noGutter)this.div.className+=" nogutter";if(this.tabsToSpaces==true)this.code=this.ProcessSmartTabs(this.code);this.ProcessRegexList();if(this.matches.length==0){this.AddBit(this.code,null);this.SwitchToList();this.div.appendChild(this.bar);this.div.appendChild(this.ol);return}this.matches=this.matches.sort(dp.sh.Highlighter.SortCallback);for(var E=0;E<this.matches.length;E++)if(this.IsInside(this.matches[E]))this.matches[E]=null;for(E=0;E<this.matches.length;E++){var B=this.matches[E];if(B==null||B.length==0)continue;this.AddBit(D(this.code,F,B.index),null);this.AddBit(B.value,B.css);F=B.index+B.length}this.AddBit(this.code.substr(F),null);this.SwitchToList();this.div.appendChild(this.bar);this.div.appendChild(this.ol)};dp.sh.Highlighter.prototype.GetKeywords=function($){return"\\b"+$.replace(/ /g,"\\b|\\b")+"\\b"};dp.sh.BloggerMode=function(){dp.sh.isBloggerMode=true};dp.sh.HighlightAll=function(N,B,K,I,O,E){function A(){var $=arguments;for(var _=0;_<$.length;_++){if($[_]==null)continue;if(typeof($[_])=="string"&&$[_]!="")return $[_]+"";if(typeof($[_])=="object"&&$[_].value!="")return $[_].value+""}return null}function J($,_){for(var A=0;A<_.length;A++)if(_[A]==$)return true;return false}function L(A,B,C){var _=new RegExp("^"+A+"\\[(\\w+)\\]$","gi"),$=null;for(var D=0;D<B.length;D++)if(($=_.exec(B[D]))!=null)return $[1];return C}function C(B,A,_){var $=document.getElementsByTagName(_);for(var C=0;C<$.length;C++)if($[C].getAttribute("name")==A)B.push($[C])}var T=[],P=null,M={},$="innerHTML";C(T,N,"pre");C(T,N,"textarea");if(T.length==0)return;for(var R in dp.sh.Brushes){var F=dp.sh.Brushes[R].Aliases;if(F==null)continue;for(var G=0;G<F.length;G++)M[F[G]]=R}for(G=0;G<T.length;G++){var _=T[G],U=A(_.attributes["class"],_.className,_.attributes["language"],_.language),Q="";if(U==null)continue;U=U.split(":");Q=U[0].toLowerCase();if(M[Q]==null)continue;P=new dp.sh.Brushes[M[Q]]();_.style.display="none";P.noGutter=(B==null)?J("nogutter",U):!B;P.addControls=(K==null)?!J("nocontrols",U):K;P.collapse=(I==null)?J("collapse",U):I;P.showColumns=(E==null)?J("showcolumns",U):E;var D=document.getElementsByTagName("head")[0];if(P.Style&&D){var S=document.createElement("style");S.setAttribute("type","text/css");if(S.styleSheet)S.styleSheet.cssText=P.Style;else{var H=document.createTextNode(P.Style);S.appendChild(H)}D.appendChild(S)}P.firstLine=(O==null)?parseInt(L("firstline",U,1)):O;P.Highlight(_[$]);P.source=_;_.parentNode.insertBefore(P.div,_)}};version.extensions.SyntaxHighLighterPlugin={major:1,minor:1,revision:3,date:new Date(2008,10,24)};dp.sh.ClipboardSwf="clipboard.swf";dp.sh.Highlight=function(_,Q,B,J,H,M,D){function A(){var $=arguments;for(var _=0;_<$.length;_++){if($[_]==null)continue;if(typeof($[_])=="string"&&$[_]!="")return $[_]+"";if(typeof($[_])=="object"&&$[_].value!="")return $[_].value+""}return null}function I($,_){for(var A=0;A<_.length;A++)if(_[A]==$)return true;return false}function K(A,B,C){var _=new RegExp("^"+A+"\\[(\\w+)\\]$","gi"),$=null;for(var D=0;D<B.length;D++)if(($=_.exec(B[D]))!=null)return $[1];return C}var N=null,$="innerHTML";if(this.registered==undefined){var L={};for(var O in dp.sh.Brushes){var E=dp.sh.Brushes[O].Aliases;if(E==null)continue;for(var F=0;F<E.length;F++)L[E[F]]=O}this.registered=L}Q=Q.split(":");language=Q[0].toLowerCase();if(this.registered[language]==null)return;N=new dp.sh.Brushes[this.registered[language]]();_.style.display="none";N.noGutter=(B==null)?I("nogutter",Q):!B;N.addControls=(J==null)?!I("nocontrols",Q):J;N.collapse=(H==null)?I("collapse",Q):H;N.showColumns=(D==null)?I("showcolumns",Q):D;var C=document.getElementsByTagName("head")[0],P=document.getElementById(N.CssClass);if(N.Style&&C&&!P){P=document.createElement("style");P.setAttribute("id",N.CssClass);P.setAttribute("type","text/css");if(P.styleSheet)P.styleSheet.cssText=N.Style;else{var G=document.createTextNode(N.Style);P.appendChild(G)}C.appendChild(P)}N.firstLine=(M==null)?parseInt(K("firstline",Q,1)):M;N.Highlight(_[$]);N.source=_;_.parentNode.insertBefore(N.div,_)};config.formatters.push({name:"SyntaxHighlighter",match:"^<code[\\s]+[^>]+>\\n",element:"pre",handler:function(_){this.lookaheadRegExp=/<code[\s]+([^>]+)>\n((?:^[^\n]*\n)+?)(^<\/code>$\n?)/mg;this.lookaheadRegExp.lastIndex=_.matchStart;var $=this.lookaheadRegExp.exec(_.source);if($&&$.index==_.matchStart){var C=$[1],B=$[2];if(config.browser.isIE)B=B.replace(/\n/g,"\r");var A=createTiddlyElement(_.output,this.element,null,null,B);dp.sh.Highlight(A,C);_.nextMatch=$.index+$[0].length}}});config.formatterHelpers.enclosedTextHelper=function(_){this.lookaheadRegExp.lastIndex=_.matchStart;var $=this.lookaheadRegExp.exec(_.source);if($&&$.index==_.matchStart){var B=$[1];if(config.browser.isIE)B=B.replace(/\n/g,"\r");var A=createTiddlyElement(_.output,this.element,null,null,B);switch(_.matchText){case"/*{{{*/\n":dp.sh.Highlight(A,"css");break;case"//{{{\n":dp.sh.Highlight(A,"js");break;case"<!--{{{-->\n":dp.sh.Highlight(A,"xml");break}_.nextMatch=$.index+$[0].length}};dp.sh.Brushes.AS3=function(){var _="class interface package",$="Array Boolean Date decodeURI decodeURIComponent encodeURI encodeURIComponent escape "+"int isFinite isNaN isXMLName Number Object parseFloat parseInt "+"String trace uint unescape XML XMLList "+"Infinity -Infinity NaN undefined "+"as delete instanceof is new typeof "+"break case catch continue default do each else finally for if in "+"label return super switch throw try while with "+"dynamic final internal native override private protected public static "+"...rest const extends function get implements namespace set "+"import include use "+"AS3 flash_proxy object_proxy "+"false null this true "+"void Null";this.regexList=[{regex:dp.sh.RegexLib.SingleLineCComments,css:"comment"},{regex:dp.sh.RegexLib.MultiLineCComments,css:"blockcomment"},{regex:dp.sh.RegexLib.DoubleQuotedString,css:"string"},{regex:dp.sh.RegexLib.SingleQuotedString,css:"string"},{regex:new RegExp("^\\s*#.*","gm"),css:"preprocessor"},{regex:new RegExp(this.GetKeywords(_),"gm"),css:"definition"},{regex:new RegExp(this.GetKeywords($),"gm"),css:"keyword"},{regex:new RegExp("var","gm"),css:"variable"}];this.CssClass="dp-as";this.Style=".dp-as .comment { color: #009900; font-style: italic; }"+".dp-as .blockcomment { color: #3f5fbf; }"+".dp-as .string { color: #990000; }"+".dp-as .preprocessor { color: #0033ff; }"+".dp-as .definition { color: #9900cc; font-weight: bold; }"+".dp-as .keyword { color: #0033ff; }"+".dp-as .variable { color: #6699cc; font-weight: bold; }"};dp.sh.Brushes.AS3.prototype=new dp.sh.Highlighter();dp.sh.Brushes.AS3.Aliases=["as","actionscript","ActionScript","as3","AS3"];dp.sh.Brushes.Bash=function(){var _="alias bg bind break builtin cd command compgen complete continue "+"declare dirs disown echo enable eval exec exit export fc fg "+"getopts hash help history jobs kill let local logout popd printf "+"pushd pwd read readonly return set shift shopt source "+"suspend test times trap type typeset ulimit umask unalias unset wait",$="case do done elif else esac fi for function if in select then "+"time until while";this.regexList=[{regex:dp.sh.RegexLib.SingleLinePerlComments,css:"comment"},{regex:dp.sh.RegexLib.DoubleQuotedString,css:"string"},{regex:dp.sh.RegexLib.SingleQuotedString,css:"string"},{regex:new RegExp("[()[\\]{}]","g"),css:"delim"},{regex:new RegExp("\\$\\w+","g"),css:"vars"},{regex:new RegExp("\\w+=","g"),css:"vars"},{regex:new RegExp("\\s-\\w+","g"),css:"flag"},{regex:new RegExp(this.GetKeywords(_),"gm"),css:"builtin"},{regex:new RegExp(this.GetKeywords($),"gm"),css:"keyword"}];this.CssClass="dp-bash";this.Style=".dp-bash .builtin {color: maroon; font-weight: bold;}"+".dp-bash .comment {color: gray;}"+".dp-bash .delim {font-weight: bold;}"+".dp-bash .flag {color: green;}"+".dp-bash .string {color: red;}"+".dp-bash .vars {color: blue;}"};dp.sh.Brushes.Bash.prototype=new dp.sh.Highlighter();dp.sh.Brushes.Bash.Aliases=["bash","sh"];dp.sh.Brushes.Batch=function(){var _="APPEND ATTRIB CD CHDIR CHKDSK CHOICE CLS COPY DEL ERASE DELTREE "+"DIR EXIT FC COMP FDISK FIND FORMAT FSUTIL HELP JOIN "+"LABEL LOADFIX MK MKDIR MEM MEMMAKER MORE MOVE MSD PCPARK "+"PRINT RD RMDIR REN SCANDISK SHARE SORT SUBST SYS "+"TIME DATE TREE TRUENAME TYPE UNDELETE VER XCOPY",$="DO ELSE FOR IN CALL CHOICE GOTO SHIFT PAUSE ERRORLEVEL "+"IF NOT EXIST LFNFOR START SETLOCAL ENDLOCAL ECHO SET";this.regexList=[{regex:new RegExp("REM.*$","gm"),css:"comment"},{regex:new RegExp("::.*$","gm"),css:"comment"},{regex:dp.sh.RegexLib.DoubleQuotedString,css:"string"},{regex:dp.sh.RegexLib.SingleQuotedString,css:"string"},{regex:new RegExp("[()[\\]{}]","g"),css:"delim"},{regex:new RegExp("%\\w+%","g"),css:"vars"},{regex:new RegExp("%%\\w+","g"),css:"vars"},{regex:new RegExp("\\w+=","g"),css:"vars"},{regex:new RegExp("@\\w+","g"),css:"keyword"},{regex:new RegExp(":\\w+","g"),css:"keyword"},{regex:new RegExp("\\s/\\w+","g"),css:"flag"},{regex:new RegExp(this.GetKeywords(_),"gm"),css:"builtin"},{regex:new RegExp(this.GetKeywords($),"gm"),css:"keyword"}];this.CssClass="dp-batch";this.Style=".dp-batch .builtin {color: maroon; font-weight: bold;}"+".dp-batch .comment {color: gray;}"+".dp-batch .delim {font-weight: bold;}"+".dp-batch .flag {color: green;}"+".dp-batch .string {color: red;}"+".dp-batch .vars {color: blue;font-weight: bold;}"};dp.sh.Brushes.Batch.prototype=new dp.sh.Highlighter();dp.sh.Brushes.Batch.Aliases=["batch","dos"];dp.sh.Brushes.ColdFusion=function(){this.CssClass="dp-coldfusion";this.Style=".dp-coldfusion { font: 13px \"Courier New\", Courier, monospace; }"+".dp-coldfusion .tag, .dp-coldfusion .tag-name { color: #990033; }"+".dp-coldfusion .attribute { color: #990033; }"+".dp-coldfusion .attribute-value { color: #0000FF; }"+".dp-coldfusion .cfcomments { background-color: #FFFF99; color: #000000; }"+".dp-coldfusion .cfscriptcomments { color: #999999; }"+".dp-coldfusion .keywords { color: #0000FF; }"+".dp-coldfusion .mgkeywords { color: #CC9900; }"+".dp-coldfusion .numbers { color: #ff0000; }"+".dp-coldfusion .strings { color: green; }";this.mgKeywords="setvalue getvalue addresult viewcollection viewstate";this.keywords="var eq neq gt gte lt lte not and or true false "+"abs acos addsoaprequestheader addsoapresponseheader "+"arrayappend arrayavg arrayclear arraydeleteat arrayinsertat "+"arrayisempty arraylen arraymax arraymin arraynew "+"arrayprepend arrayresize arrayset arraysort arraysum "+"arrayswap arraytolist asc asin atn binarydecode binaryencode "+"bitand bitmaskclear bitmaskread bitmaskset bitnot bitor bitshln "+"bitshrn bitxor ceiling charsetdecode charsetencode chr cjustify "+"compare comparenocase cos createdate createdatetime createobject "+"createobject createobject createobject createobject createodbcdate "+"createodbcdatetime createodbctime createtime createtimespan "+"createuuid dateadd datecompare dateconvert datediff dateformat "+"datepart day dayofweek dayofweekasstring dayofyear daysinmonth "+"daysinyear de decimalformat decrementvalue decrypt decryptbinary "+"deleteclientvariable directoryexists dollarformat duplicate encrypt "+"encryptbinary evaluate exp expandpath fileexists find findnocase "+"findoneof firstdayofmonth fix formatbasen generatesecretkey "+"getauthuser getbasetagdata getbasetaglist getbasetemplatepath "+"getclientvariableslist getcontextroot getcurrenttemplatepath "+"getdirectoryfrompath getencoding getexception getfilefrompath "+"getfunctionlist getgatewayhelper gethttprequestdata gethttptimestring "+"getk2serverdoccount getk2serverdoccountlimit getlocale "+"getlocaledisplayname getlocalhostip getmetadata getmetricdata "+"getpagecontext getprofilesections getprofilestring getsoaprequest "+"getsoaprequestheader getsoapresponse getsoapresponseheader "+"gettempdirectory gettempfile gettemplatepath gettickcount "+"gettimezoneinfo gettoken hash hour htmlcodeformat htmleditformat "+"iif incrementvalue inputbasen insert int isarray isbinary isboolean "+"iscustomfunction isdate isdebugmode isdefined isk2serverabroker "+"isk2serverdoccountexceeded isk2serveronline isleapyear islocalhost "+"isnumeric isnumericdate isobject isquery issimplevalue issoaprequest "+"isstruct isuserinrole isvalid isvalid isvalid iswddx isxml "+"isxmlattribute isxmldoc isxmlelem isxmlnode isxmlroot javacast "+"jsstringformat lcase left len listappend listchangedelims listcontains "+"listcontainsnocase listdeleteat listfind listfindnocase listfirst "+"listgetat listinsertat listlast listlen listprepend listqualify "+"listrest listsetat listsort listtoarray listvaluecount "+"listvaluecountnocase ljustify log log10 lscurrencyformat lsdateformat "+"lseurocurrencyformat lsiscurrency lsisdate lsisnumeric lsnumberformat "+"lsparsecurrency lsparsedatetime lsparseeurocurrency lsparsenumber "+"lstimeformat ltrim max mid min minute month monthasstring now "+"numberformat paragraphformat parameterexists parsedatetime pi "+"preservesinglequotes quarter queryaddcolumn queryaddrow querynew "+"querysetcell quotedvaluelist rand randomize randrange refind "+"refindnocase releasecomobject removechars repeatstring replace "+"replacelist replacenocase rereplace rereplacenocase reverse right "+"rjustify round rtrim second sendgatewaymessage setencoding "+"setlocale setprofilestring setvariable sgn sin spanexcluding "+"spanincluding sqr stripcr structappend structclear structcopy "+"structcount structdelete structfind structfindkey structfindvalue "+"structget structinsert structisempty structkeyarray structkeyexists "+"structkeylist structnew structsort structupdate tan timeformat "+"tobase64 tobinary toscript tostring trim ucase urldecode urlencodedformat "+"urlsessionformat val valuelist week wrap writeoutput xmlchildpos "+"xmlelemnew xmlformat xmlgetnodetype xmlnew xmlparse xmlsearch xmltransform "+"xmlvalidate year yesnoformat";this.stringMatches=new Array();this.attributeMatches=new Array()};dp.sh.Brushes.ColdFusion.prototype=new dp.sh.Highlighter();dp.sh.Brushes.ColdFusion.Aliases=["coldfusion","cf"];dp.sh.Brushes.ColdFusion.prototype.ProcessRegexList=function(){function B(_,$){_[_.length]=$}function A(A,$){for(var _=0;_<A.length;_++)if(A[_]==$)return _;return-1}var _=null,$=null;this.GetMatches(new RegExp("\\b(\\d+)","gm"),"numbers");this.GetMatches(new RegExp(this.GetKeywords(this.mgKeywords),"igm"),"mgkeywords");this.GetMatches(dp.sh.RegexLib.SingleLineCComments,"cfscriptcomments");this.GetMatches(dp.sh.RegexLib.MultiLineCComments,"cfscriptcomments");this.GetMatches(new RegExp("(<|<)!---[\\s\\S]*?---(>|>)","gm"),"cfcomments");$=new RegExp("(cfset\\s*)?([:\\w-.]+)\\s*=\\s*(\".*?\"|'.*?')*","gm");while((_=$.exec(this.code))!=null){if(_[1]!=undefined&&_[1]!="")continue;if(_[3]!=undefined&&_[3]!=""&&_[3]!="\"\""&&_[3]!="''"){B(this.matches,new dp.sh.Match(_[2],_.index,"attribute"));B(this.matches,new dp.sh.Match(_[3],_.index+_[0].indexOf(_[3]),"attribute-value"));B(this.stringMatches,_[3]);B(this.attributeMatches,_[2])}}this.GetMatches(new RegExp("(<|<)/*\\?*(?!\\!)|/*\\?*(>|>)","gm"),"tag");$=new RegExp("(?:<|<)/*\\?*\\s*([:\\w-.]+)","gm");while((_=$.exec(this.code))!=null)B(this.matches,new dp.sh.Match(_[1],_.index+_[0].indexOf(_[1]),"tag-name"));$=new RegExp(this.GetKeywords(this.keywords),"igm");while((_=$.exec(this.code))!=null)if(A(this.attributeMatches,_[0])==-1)B(this.matches,new dp.sh.Match(_[0],_.index,"keywords"));$=new RegExp("cfset\\s*.*(\".*?\"|'.*?')","gm");while((_=$.exec(this.code))!=null)if(_[1]!=undefined&&_[1]!=""){B(this.matches,new dp.sh.Match(_[1],_.index+_[0].indexOf(_[1]),"strings"));B(this.stringMatches,_[1])}while((_=dp.sh.RegexLib.DoubleQuotedString.exec(this.code))!=null)if(A(this.stringMatches,_[0])==-1)B(this.matches,new dp.sh.Match(_[0],_.index,"strings"));while((_=dp.sh.RegexLib.SingleQuotedString.exec(this.code))!=null)if(A(this.stringMatches,_[0])==-1)B(this.matches,new dp.sh.Match(_[0],_.index,"strings"))};dp.sh.Brushes.Cpp=function(){var _="ATOM BOOL BOOLEAN BYTE CHAR COLORREF DWORD DWORDLONG DWORD_PTR "+"DWORD32 DWORD64 FLOAT HACCEL HALF_PTR HANDLE HBITMAP HBRUSH "+"HCOLORSPACE HCONV HCONVLIST HCURSOR HDC HDDEDATA HDESK HDROP HDWP "+"HENHMETAFILE HFILE HFONT HGDIOBJ HGLOBAL HHOOK HICON HINSTANCE HKEY "+"HKL HLOCAL HMENU HMETAFILE HMODULE HMONITOR HPALETTE HPEN HRESULT "+"HRGN HRSRC HSZ HWINSTA HWND INT INT_PTR INT32 INT64 LANGID LCID LCTYPE "+"LGRPID LONG LONGLONG LONG_PTR LONG32 LONG64 LPARAM LPBOOL LPBYTE LPCOLORREF "+"LPCSTR LPCTSTR LPCVOID LPCWSTR LPDWORD LPHANDLE LPINT LPLONG LPSTR LPTSTR "+"LPVOID LPWORD LPWSTR LRESULT PBOOL PBOOLEAN PBYTE PCHAR PCSTR PCTSTR PCWSTR "+"PDWORDLONG PDWORD_PTR PDWORD32 PDWORD64 PFLOAT PHALF_PTR PHANDLE PHKEY PINT "+"PINT_PTR PINT32 PINT64 PLCID PLONG PLONGLONG PLONG_PTR PLONG32 PLONG64 POINTER_32 "+"POINTER_64 PSHORT PSIZE_T PSSIZE_T PSTR PTBYTE PTCHAR PTSTR PUCHAR PUHALF_PTR "+"PUINT PUINT_PTR PUINT32 PUINT64 PULONG PULONGLONG PULONG_PTR PULONG32 PULONG64 "+"PUSHORT PVOID PWCHAR PWORD PWSTR SC_HANDLE SC_LOCK SERVICE_STATUS_HANDLE SHORT "+"SIZE_T SSIZE_T TBYTE TCHAR UCHAR UHALF_PTR UINT UINT_PTR UINT32 UINT64 ULONG "+"ULONGLONG ULONG_PTR ULONG32 ULONG64 USHORT USN VOID WCHAR WORD WPARAM WPARAM WPARAM "+"char bool short int __int32 __int64 __int8 __int16 long float double __wchar_t "+"clock_t _complex _dev_t _diskfree_t div_t ldiv_t _exception _EXCEPTION_POINTERS "+"FILE _finddata_t _finddatai64_t _wfinddata_t _wfinddatai64_t __finddata64_t "+"__wfinddata64_t _FPIEEE_RECORD fpos_t _HEAPINFO _HFILE lconv intptr_t "+"jmp_buf mbstate_t _off_t _onexit_t _PNH ptrdiff_t _purecall_handler "+"sig_atomic_t size_t _stat __stat64 _stati64 terminate_function "+"time_t __time64_t _timeb __timeb64 tm uintptr_t _utimbuf "+"va_list wchar_t wctrans_t wctype_t wint_t signed",$="break case catch class const __finally __exception __try "+"const_cast continue private public protected __declspec "+"default delete deprecated dllexport dllimport do dynamic_cast "+"else enum explicit extern if for friend goto inline "+"mutable naked namespace new noinline noreturn nothrow "+"register reinterpret_cast return selectany "+"sizeof static static_cast struct switch template this "+"thread throw true false try typedef typeid typename union "+"using uuid virtual void volatile whcar_t while";this.regexList=[{regex:dp.sh.RegexLib.SingleLineCComments,css:"comment"},{regex:dp.sh.RegexLib.MultiLineCComments,css:"comment"},{regex:dp.sh.RegexLib.DoubleQuotedString,css:"string"},{regex:dp.sh.RegexLib.SingleQuotedString,css:"string"},{regex:new RegExp("^ *#.*","gm"),css:"preprocessor"},{regex:new RegExp(this.GetKeywords(_),"gm"),css:"datatypes"},{regex:new RegExp(this.GetKeywords($),"gm"),css:"keyword"}];this.CssClass="dp-cpp";this.Style=".dp-cpp .datatypes { color: #2E8B57; font-weight: bold; }"};dp.sh.Brushes.Cpp.prototype=new dp.sh.Highlighter();dp.sh.Brushes.Cpp.Aliases=["cpp","c","c++"];dp.sh.Brushes.CSharp=function(){var $="abstract as base bool break byte case catch char checked class const "+"continue decimal default delegate do double else enum event explicit "+"extern false finally fixed float for foreach get goto if implicit in int "+"interface internal is lock long namespace new null object operator out "+"override params private protected public readonly ref return sbyte sealed set "+"short sizeof stackalloc static string struct switch this throw true try "+"typeof uint ulong unchecked unsafe ushort using virtual void while";this.regexList=[{regex:dp.sh.RegexLib.SingleLineCComments,css:"comment"},{regex:dp.sh.RegexLib.MultiLineCComments,css:"comment"},{regex:dp.sh.RegexLib.DoubleQuotedString,css:"string"},{regex:dp.sh.RegexLib.SingleQuotedString,css:"string"},{regex:new RegExp("^\\s*#.*","gm"),css:"preprocessor"},{regex:new RegExp(this.GetKeywords($),"gm"),css:"keyword"}];this.CssClass="dp-c";this.Style=".dp-c .vars { color: #d00; }"};dp.sh.Brushes.CSharp.prototype=new dp.sh.Highlighter();dp.sh.Brushes.CSharp.Aliases=["c#","c-sharp","csharp"];dp.sh.Brushes.CSS=function(){var _="ascent azimuth background-attachment background-color background-image background-position "+"background-repeat background baseline bbox border-collapse border-color border-spacing border-style border-top "+"border-right border-bottom border-left border-top-color border-right-color border-bottom-color border-left-color "+"border-top-style border-right-style border-bottom-style border-left-style border-top-width border-right-width "+"border-bottom-width border-left-width border-width border cap-height caption-side centerline clear clip color "+"content counter-increment counter-reset cue-after cue-before cue cursor definition-src descent direction display "+"elevation empty-cells float font-size-adjust font-family font-size font-stretch font-style font-variant font-weight font "+"height letter-spacing line-height list-style-image list-style-position list-style-type list-style margin-top "+"margin-right margin-bottom margin-left margin marker-offset marks mathline max-height max-width min-height min-width orphans "+"outline-color outline-style outline-width outline overflow padding-top padding-right padding-bottom padding-left padding page "+"page-break-after page-break-before page-break-inside pause pause-after pause-before pitch pitch-range play-during position "+"quotes richness size slope src speak-header speak-numeral speak-punctuation speak speech-rate stemh stemv stress "+"table-layout text-align text-decoration text-indent text-shadow text-transform unicode-bidi unicode-range units-per-em "+"vertical-align visibility voice-family volume white-space widows width widths word-spacing x-height z-index",$="above absolute all always aqua armenian attr aural auto avoid baseline behind below bidi-override black blink block blue bold bolder "+"both bottom braille capitalize caption center center-left center-right circle close-quote code collapse compact condensed "+"continuous counter counters crop cross crosshair cursive dashed decimal decimal-leading-zero default digits disc dotted double "+"embed embossed e-resize expanded extra-condensed extra-expanded fantasy far-left far-right fast faster fixed format fuchsia "+"gray green groove handheld hebrew help hidden hide high higher icon inline-table inline inset inside invert italic "+"justify landscape large larger left-side left leftwards level lighter lime line-through list-item local loud lower-alpha "+"lowercase lower-greek lower-latin lower-roman lower low ltr marker maroon medium message-box middle mix move narrower "+"navy ne-resize no-close-quote none no-open-quote no-repeat normal nowrap n-resize nw-resize oblique olive once open-quote outset "+"outside overline pointer portrait pre print projection purple red relative repeat repeat-x repeat-y rgb ridge right right-side "+"rightwards rtl run-in screen scroll semi-condensed semi-expanded separate se-resize show silent silver slower slow "+"small small-caps small-caption smaller soft solid speech spell-out square s-resize static status-bar sub super sw-resize "+"table-caption table-cell table-column table-column-group table-footer-group table-header-group table-row table-row-group teal "+"text-bottom text-top thick thin top transparent tty tv ultra-condensed ultra-expanded underline upper-alpha uppercase upper-latin "+"upper-roman url visible wait white wider w-resize x-fast x-high x-large x-loud x-low x-slow x-small x-soft xx-large xx-small yellow",A="[mM]onospace [tT]ahoma [vV]erdana [aA]rial [hH]elvetica [sS]ans-serif [sS]erif";this.regexList=[{regex:dp.sh.RegexLib.MultiLineCComments,css:"comment"},{regex:dp.sh.RegexLib.DoubleQuotedString,css:"string"},{regex:dp.sh.RegexLib.SingleQuotedString,css:"string"},{regex:new RegExp("\\#[a-zA-Z0-9]{3,6}","g"),css:"value"},{regex:new RegExp("(-?\\d+)(.\\d+)?(px|em|pt|:|%|)","g"),css:"value"},{regex:new RegExp("!important","g"),css:"important"},{regex:new RegExp(this.GetKeywordsCSS(_),"gm"),css:"keyword"},{regex:new RegExp(this.GetValuesCSS($),"g"),css:"value"},{regex:new RegExp(this.GetValuesCSS(A),"g"),css:"value"}];this.CssClass="dp-css";this.Style=".dp-css .value { color: black; }"+".dp-css .important { color: red; }"};dp.sh.Highlighter.prototype.GetKeywordsCSS=function($){return"\\b([a-z_]|)"+$.replace(/ /g,"(?=:)\\b|\\b([a-z_\\*]|\\*|)")+"(?=:)\\b"};dp.sh.Highlighter.prototype.GetValuesCSS=function($){return"\\b"+$.replace(/ /g,"(?!-)(?!:)\\b|\\b()")+":\\b"};dp.sh.Brushes.CSS.prototype=new dp.sh.Highlighter();dp.sh.Brushes.CSS.Aliases=["css"];dp.sh.Brushes.Delphi=function(){var $="abs addr and ansichar ansistring array as asm begin boolean byte cardinal "+"case char class comp const constructor currency destructor div do double "+"downto else end except exports extended false file finalization finally "+"for function goto if implementation in inherited int64 initialization "+"integer interface is label library longint longword mod nil not object "+"of on or packed pansichar pansistring pchar pcurrency pdatetime pextended "+"pint64 pointer private procedure program property pshortstring pstring "+"pvariant pwidechar pwidestring protected public published raise real real48 "+"record repeat set shl shortint shortstring shr single smallint string then "+"threadvar to true try type unit until uses val var varirnt while widechar "+"widestring with word write writeln xor";this.regexList=[{regex:new RegExp("\\(\\*[\\s\\S]*?\\*\\)","gm"),css:"comment"},{regex:new RegExp("{(?!\\$)[\\s\\S]*?}","gm"),css:"comment"},{regex:dp.sh.RegexLib.SingleLineCComments,css:"comment"},{regex:dp.sh.RegexLib.SingleQuotedString,css:"string"},{regex:new RegExp("\\{\\$[a-zA-Z]+ .+\\}","g"),css:"directive"},{regex:new RegExp("\\b[\\d\\.]+\\b","g"),css:"number"},{regex:new RegExp("\\$[a-zA-Z0-9]+\\b","g"),css:"number"},{regex:new RegExp(this.GetKeywords($),"gm"),css:"keyword"}];this.CssClass="dp-delphi";this.Style=".dp-delphi .number { color: blue; }"+".dp-delphi .directive { color: #008284; }"+".dp-delphi .vars { color: #000; }"};dp.sh.Brushes.Delphi.prototype=new dp.sh.Highlighter();dp.sh.Brushes.Delphi.Aliases=["delphi","pascal"];dp.sh.Brushes.Java=function(){var $="abstract assert boolean break byte case catch char class const "+"continue default do double else enum extends "+"false final finally float for goto if implements import "+"instanceof int interface long native new null "+"package private protected public return "+"short static strictfp super switch synchronized this throw throws true "+"transient try void volatile while";this.regexList=[{regex:dp.sh.RegexLib.SingleLineCComments,css:"comment"},{regex:dp.sh.RegexLib.MultiLineCComments,css:"comment"},{regex:dp.sh.RegexLib.DoubleQuotedString,css:"string"},{regex:dp.sh.RegexLib.SingleQuotedString,css:"string"},{regex:new RegExp("\\b([\\d]+(\\.[\\d]+)?|0x[a-f0-9]+)\\b","gi"),css:"number"},{regex:new RegExp("(?!\\@interface\\b)\\@[\\$\\w]+\\b","g"),css:"annotation"},{regex:new RegExp("\\@interface\\b","g"),css:"keyword"},{regex:new RegExp(this.GetKeywords($),"gm"),css:"keyword"}];this.CssClass="dp-j";this.Style=".dp-j .annotation { color: #646464; }"+".dp-j .number { color: #C00000; }"};dp.sh.Brushes.Java.prototype=new dp.sh.Highlighter();dp.sh.Brushes.Java.Aliases=["java"];dp.sh.Brushes.JScript=function(){var $="abstract boolean break byte case catch char class const continue debugger "+"default delete do double else enum export extends false final finally float "+"for function goto if implements import in instanceof int interface long native "+"new null package private protected public return short static super switch "+"synchronized this throw throws transient true try typeof var void volatile while with";this.regexList=[{regex:dp.sh.RegexLib.SingleLineCComments,css:"comment"},{regex:dp.sh.RegexLib.MultiLineCComments,css:"comment"},{regex:dp.sh.RegexLib.DoubleQuotedString,css:"string"},{regex:dp.sh.RegexLib.SingleQuotedString,css:"string"},{regex:new RegExp("^\\s*#.*","gm"),css:"preprocessor"},{regex:new RegExp(this.GetKeywords($),"gm"),css:"keyword"}];this.CssClass="dp-c"};dp.sh.Brushes.JScript.prototype=new dp.sh.Highlighter();dp.sh.Brushes.JScript.Aliases=["js","jscript","javascript"];dp.sh.Brushes.Lua=function(){var $="break do end else elseif function if local nil not or repeat return and then until while this",_="math\\.\\w+ string\\.\\w+ os\\.\\w+ debug\\.\\w+ io\\.\\w+ error fopen dofile coroutine\\.\\w+ arg getmetatable ipairs loadfile loadlib loadstring longjmp print rawget rawset seek setmetatable assert tonumber tostring";this.regexList=[{regex:new RegExp("--\\[\\[[\\s\\S]*\\]\\]--","gm"),css:"comment"},{regex:new RegExp("--[^\\[]{2}.*$","gm"),css:"comment"},{regex:dp.sh.RegexLib.DoubleQuotedString,css:"string"},{regex:dp.sh.RegexLib.SingleQuotedString,css:"string"},{regex:new RegExp(this.GetKeywords($),"gm"),css:"keyword"},{regex:new RegExp(this.GetKeywords(_),"gm"),css:"func"},];this.CssClass="dp-lua"};dp.sh.Brushes.Lua.prototype=new dp.sh.Highlighter();dp.sh.Brushes.Lua.Aliases=["lua"];dp.sh.Brushes.Mxml=function(){this.CssClass="dp-mxml";this.Style=".dp-mxml .cdata { color: #000000; }"+".dp-mxml .tag { color : #0000ff; }"+".dp-mxml .tag-name { color: #0000ff; }"+".dp-mxml .script { color: green; }"+".dp-mxml .metadata { color: green; }"+".dp-mxml .attribute { color: #000000; }"+".dp-mxml .attribute-value { color: #990000; }"+".dp-mxml .trace { color: #cc6666; }"+".dp-mxml .var { color: #6699cc; }"+".dp-mxml .comment { color: #009900; }"+".dp-mxml .string { color: #990000; }"+".dp-mxml .keyword { color: blue; }"};dp.sh.Brushes.Mxml.prototype=new dp.sh.Highlighter();dp.sh.Brushes.Mxml.Aliases=["mxml"];dp.sh.Brushes.Mxml.prototype.ProcessRegexList=function(){function H(_,$){_[_.length]=$}function B(B,_){var A=0,$=false;for(A=0;A<B.length;A++)if(_.index>B[A].firstIndex&&_.index<B[A].lastIndex)$=true;return $}var $=0,F=null,D=null,A=null,C="",E=new Array(),_="abstract boolean break byte case catch char class const continue debugger "+"default delete do double else enum export extends false final finally float "+"for function goto if implements import in instanceof int interface long native "+"new null package private protected public return short static super switch "+"synchronized this throw throws transient true try typeof var void volatile while with",G=[{regex:dp.sh.RegexLib.SingleLineCComments,css:"comment"},{regex:dp.sh.RegexLib.MultiLineCComments,css:"comment"},{regex:dp.sh.RegexLib.DoubleQuotedString,css:"string"},{regex:dp.sh.RegexLib.SingleQuotedString,css:"string"},{regex:new RegExp("^\\s*#.*","gm"),css:"preprocessor"},{regex:new RegExp(this.GetKeywords("trace"),"gm"),css:"trace"},{regex:new RegExp(this.GetKeywords(_),"gm"),css:"keyword"}];A=new RegExp("<\\!\\[CDATA\\[(.|\\s)*?\\]\\]>","gm");while((F=A.exec(this.code))!=null){C=F[0].substr(0,12);H(this.matches,new dp.sh.Match(C,F.index,"cdata"));C=F[0].substr(12,F[0].length-12-6);for(var I=0;I<G.length;I++)while((D=G[I].regex.exec(C))!=null)H(this.matches,new dp.sh.Match(D[0],F.index+12+D.index,G[I].css));C=F[0].substr(F[0].length-6,6);H(this.matches,new dp.sh.Match(C,F.index+F[0].length-6,"cdata"));E.push({firstIndex:F.index,lastIndex:F.index+F[0].length-1})}this.GetMatches(new RegExp("(<|<)!--\\s*.*?\\s*--(>|>)","gm"),"comments");A=new RegExp("([:\\w-.]+)\\s*=\\s*(\".*?\"|'.*?'|\\w+)*|(\\w+)","gm");while((F=A.exec(this.code))!=null){if(F[1]==null)continue;if(B(E,F))continue;H(this.matches,new dp.sh.Match(F[1],F.index,"attribute"));if(F[2]!=undefined)H(this.matches,new dp.sh.Match(F[2],F.index+F[0].indexOf(F[2]),"attribute-value"))}A=new RegExp("(?:<|<)/*\\?*\\s*([:\\w-.]+)","gm");while((F=A.exec(this.code))!=null){if(B(E,F))continue;C=F[0].substr(4,F[0].length-4);switch(C){case"mx:Script":case"/mx:Script":H(this.matches,new dp.sh.Match(F[0]+">",F.index,"script"));break;case"mx:Metadata":case"/mx:Metadata":H(this.matches,new dp.sh.Match(F[0]+">",F.index,"metadata"));break;default:H(this.matches,new dp.sh.Match(F[0],F.index,"tag-name"));break}}A=new RegExp("\\?>|>|/>","gm");while((F=A.exec(this.code))!=null){if(B(E,F))continue;H(this.matches,new dp.sh.Match(F[0],F.index,"tag"))}};dp.sh.Brushes.Perl=function(){var _="abs accept alarm atan2 bind binmode bless caller chdir chmod chomp chop chown chr chroot close closedir connect cos crypt dbmclose dbmopen defined delete dump each endgrent endhostent endnetent endprotoent endpwent endservent eof exec exists exp fcntl fileno flock fork format formline getc getgrent getgrgid getgrnam gethostbyaddr gethostbyname gethostent getlogin getnetbyaddr getnetbyname getnetent getpeername getpgrp getppid getpriority getprotobyname getprotobynumber getprotoent getpwent getpwnam getpwuid getservbyname getservbyport getservent getsockname getsockopt glob gmtime grep hex import index int ioctl join keys kill lc lcfirst length link listen localtime lock log lstat m map mkdir msgctl msgget msgrcv msgsnd no oct open opendir ord pack pipe pop pos print printf prototype push q qq quotemeta qw qx rand read readdir readline readlink readpipe recv ref rename reset reverse rewinddir rindex rmdir scalar seek seekdir semctl semget semop send setgrent sethostent setnetent setpgrp setpriority setprotoent setpwent setservent setsockopt shift shmctl shmget shmread shmwrite shutdown sin sleep socket socketpair sort splice split sprintf sqrt srand stat study sub substr symlink syscall sysopen sysread sysseek system syswrite tell telldir tie tied time times tr truncate uc ucfirst umask undef unlink unpack unshift untie utime values vec waitpid wantarray warn write qr",$="s select goto die do package redo require return continue for foreach last next wait while use if else elsif eval exit unless switch case",A="my our local";this.regexList=[{regex:dp.sh.RegexLib.SingleLinePerlComments,css:"comment"},{regex:dp.sh.RegexLib.DoubleQuotedString,css:"string"},{regex:dp.sh.RegexLib.SingleQuotedString,css:"string"},{regex:new RegExp("(\\$|@|%)\\w+","g"),css:"vars"},{regex:new RegExp(this.GetKeywords(_),"gmi"),css:"func"},{regex:new RegExp(this.GetKeywords($),"gm"),css:"keyword"},{regex:new RegExp(this.GetKeywords(A),"gm"),css:"declarations"}];this.CssClass="dp-perl"};dp.sh.Brushes.Perl.prototype=new dp.sh.Highlighter();dp.sh.Brushes.Perl.Aliases=["perl"];dp.sh.Brushes.Php=function(){var _="abs acos acosh addcslashes addslashes "+"array_change_key_case array_chunk array_combine array_count_values array_diff "+"array_diff_assoc array_diff_key array_diff_uassoc array_diff_ukey array_fill "+"array_filter array_flip array_intersect array_intersect_assoc array_intersect_key "+"array_intersect_uassoc array_intersect_ukey array_key_exists array_keys array_map "+"array_merge array_merge_recursive array_multisort array_pad array_pop array_product "+"array_push array_rand array_reduce array_reverse array_search array_shift "+"array_slice array_splice array_sum array_udiff array_udiff_assoc "+"array_udiff_uassoc array_uintersect array_uintersect_assoc "+"array_uintersect_uassoc array_unique array_unshift array_values array_walk "+"array_walk_recursive atan atan2 atanh base64_decode base64_encode base_convert "+"basename bcadd bccomp bcdiv bcmod bcmul bindec bindtextdomain bzclose bzcompress "+"bzdecompress bzerrno bzerror bzerrstr bzflush bzopen bzread bzwrite ceil chdir "+"checkdate checkdnsrr chgrp chmod chop chown chr chroot chunk_split class_exists "+"closedir closelog copy cos cosh count count_chars date decbin dechex decoct "+"deg2rad delete ebcdic2ascii echo empty end ereg ereg_replace eregi eregi_replace error_log "+"error_reporting escapeshellarg escapeshellcmd eval exec exit exp explode extension_loaded "+"feof fflush fgetc fgetcsv fgets fgetss file_exists file_get_contents file_put_contents "+"fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype "+"floatval flock floor flush fmod fnmatch fopen fpassthru fprintf fputcsv fputs fread fscanf "+"fseek fsockopen fstat ftell ftok getallheaders getcwd getdate getenv gethostbyaddr gethostbyname "+"gethostbynamel getimagesize getlastmod getmxrr getmygid getmyinode getmypid getmyuid getopt "+"getprotobyname getprotobynumber getrandmax getrusage getservbyname getservbyport gettext "+"gettimeofday gettype glob gmdate gmmktime ini_alter ini_get ini_get_all ini_restore ini_set "+"interface_exists intval ip2long is_a is_array is_bool is_callable is_dir is_double "+"is_executable is_file is_finite is_float is_infinite is_int is_integer is_link is_long "+"is_nan is_null is_numeric is_object is_readable is_real is_resource is_scalar is_soap_fault "+"is_string is_subclass_of is_uploaded_file is_writable is_writeable mkdir mktime nl2br "+"parse_ini_file parse_str parse_url passthru pathinfo readlink realpath rewind rewinddir rmdir "+"round str_ireplace str_pad str_repeat str_replace str_rot13 str_shuffle str_split "+"str_word_count strcasecmp strchr strcmp strcoll strcspn strftime strip_tags stripcslashes "+"stripos stripslashes stristr strlen strnatcasecmp strnatcmp strncasecmp strncmp strpbrk "+"strpos strptime strrchr strrev strripos strrpos strspn strstr strtok strtolower strtotime "+"strtoupper strtr strval substr substr_compare",$="and or xor __FILE__ __LINE__ array as break case "+"cfunction class const continue declare default die do else "+"elseif empty enddeclare endfor endforeach endif endswitch endwhile "+"extends for foreach function include include_once global if "+"new old_function return static switch use require require_once "+"var while __FUNCTION__ __CLASS__ "+"__METHOD__ abstract interface public implements extends private protected throw";this.regexList=[{regex:dp.sh.RegexLib.SingleLineCComments,css:"comment"},{regex:dp.sh.RegexLib.MultiLineCComments,css:"comment"},{regex:dp.sh.RegexLib.DoubleQuotedString,css:"string"},{regex:dp.sh.RegexLib.SingleQuotedString,css:"string"},{regex:new RegExp("\\$\\w+","g"),css:"vars"},{regex:new RegExp(this.GetKeywords(_),"gmi"),css:"func"},{regex:new RegExp(this.GetKeywords($),"gm"),css:"keyword"}];this.CssClass="dp-c"};dp.sh.Brushes.Php.prototype=new dp.sh.Highlighter();dp.sh.Brushes.Php.Aliases=["php"];dp.sh.Brushes.Python=function(){var $="and assert break class continue def del elif else "+"except exec finally for from global if import in is "+"lambda not or pass print raise return try yield while",_="None True False self cls class_";this.regexList=[{regex:dp.sh.RegexLib.SingleLinePerlComments,css:"comment"},{regex:new RegExp("^\\s*@\\w+","gm"),css:"decorator"},{regex:new RegExp("(['\"]{3})([^\\1])*?\\1","gm"),css:"comment"},{regex:new RegExp("\"(?!\")(?:\\.|\\\\\\\"|[^\\\"\"\\n\\r])*\"","gm"),css:"string"},{regex:new RegExp("'(?!')*(?:\\.|(\\\\\\')|[^\\''\\n\\r])*'","gm"),css:"string"},{regex:new RegExp("\\b\\d+\\.?\\w*","g"),css:"number"},{regex:new RegExp(this.GetKeywords($),"gm"),css:"keyword"},{regex:new RegExp(this.GetKeywords(_),"gm"),css:"special"}];this.CssClass="dp-py";this.Style=".dp-py .builtins { color: #ff1493; }"+".dp-py .magicmethods { color: #808080; }"+".dp-py .exceptions { color: brown; }"+".dp-py .types { color: brown; font-style: italic; }"+".dp-py .commonlibs { color: #8A2BE2; font-style: italic; }"};dp.sh.Brushes.Python.prototype=new dp.sh.Highlighter();dp.sh.Brushes.Python.Aliases=["py","python"];dp.sh.Brushes.Ruby=function(){var $="alias and BEGIN begin break case class def define_method defined do each else elsif "+"END end ensure false for if in module new next nil not or raise redo rescue retry return "+"self super then throw true undef unless until when while yield",_="Array Bignum Binding Class Continuation Dir Exception FalseClass File::Stat File Fixnum Fload "+"Hash Integer IO MatchData Method Module NilClass Numeric Object Proc Range Regexp String Struct::TMS Symbol "+"ThreadGroup Thread Time TrueClass";this.regexList=[{regex:dp.sh.RegexLib.SingleLinePerlComments,css:"comment"},{regex:dp.sh.RegexLib.DoubleQuotedString,css:"string"},{regex:dp.sh.RegexLib.SingleQuotedString,css:"string"},{regex:new RegExp(":[a-z][A-Za-z0-9_]*","g"),css:"symbol"},{regex:new RegExp("(\\$|@@|@)\\w+","g"),css:"variable"},{regex:new RegExp(this.GetKeywords($),"gm"),css:"keyword"},{regex:new RegExp(this.GetKeywords(_),"gm"),css:"builtin"}];this.CssClass="dp-rb";this.Style=".dp-rb .symbol { color: #a70; }"+".dp-rb .variable { color: #a70; font-weight: bold; }"};dp.sh.Brushes.Ruby.prototype=new dp.sh.Highlighter();dp.sh.Brushes.Ruby.Aliases=["ruby","rails","ror"];dp.sh.Brushes.Sql=function(){var _="abs avg case cast coalesce convert count current_timestamp "+"current_user day isnull left lower month nullif replace right "+"session_user space substring sum system_user upper user year",$="absolute action add after alter as asc at authorization begin bigint "+"binary bit by cascade char character check checkpoint close collate "+"column commit committed connect connection constraint contains continue "+"create cube current current_date current_time cursor database date "+"deallocate dec decimal declare default delete desc distinct double drop "+"dynamic else end end-exec escape except exec execute false fetch first "+"float for force foreign forward free from full function global goto grant "+"group grouping having hour ignore index inner insensitive insert instead "+"int integer intersect into is isolation key last level load local max min "+"minute modify move name national nchar next no numeric of off on only "+"open option order out output partial password precision prepare primary "+"prior privileges procedure public read real references relative repeatable "+"restrict return returns revoke rollback rollup rows rule schema scroll "+"second section select sequence serializable set size smallint static "+"statistics table temp temporary then time timestamp to top transaction "+"translation trigger true truncate uncommitted union unique update values "+"varchar varying view when where with work",A="all and any between cross in join like not null or outer some";this.regexList=[{regex:new RegExp("--(.*)$","gm"),css:"comment"},{regex:dp.sh.RegexLib.DoubleQuotedString,css:"string"},{regex:dp.sh.RegexLib.SingleQuotedString,css:"string"},{regex:new RegExp(this.GetKeywords(_),"gmi"),css:"func"},{regex:new RegExp(this.GetKeywords(A),"gmi"),css:"op"},{regex:new RegExp(this.GetKeywords($),"gmi"),css:"keyword"}];this.CssClass="dp-sql";this.Style=".dp-sql .func { color: #ff1493; }"+".dp-sql .op { color: #808080; }"};dp.sh.Brushes.Sql.prototype=new dp.sh.Highlighter();dp.sh.Brushes.Sql.Aliases=["sql"];dp.sh.Brushes.Vb=function(){var $="AddHandler AddressOf AndAlso Alias And Ansi As Assembly Auto "+"Boolean ByRef Byte ByVal Call Case Catch CBool CByte CChar CDate "+"CDec CDbl Char CInt Class CLng CObj Const CShort CSng CStr CType "+"Date Decimal Declare Default Delegate Dim DirectCast Do Double Each "+"Else ElseIf End Enum Erase Error Event Exit False Finally For Friend "+"Function Get GetType GoSub GoTo Handles If Implements Imports In "+"Inherits Integer Interface Is Let Lib Like Long Loop Me Mod Module "+"MustInherit MustOverride MyBase MyClass Namespace New Next Not Nothing "+"NotInheritable NotOverridable Object On Option Optional Or OrElse "+"Overloads Overridable Overrides ParamArray Preserve Private Property "+"Protected Public RaiseEvent ReadOnly ReDim REM RemoveHandler Resume "+"Return Select Set Shadows Shared Short Single Static Step Stop String "+"Structure Sub SyncLock Then Throw To True Try TypeOf Unicode Until "+"Variant When While With WithEvents WriteOnly Xor";this.regexList=[{regex:new RegExp("'.*$","gm"),css:"comment"},{regex:dp.sh.RegexLib.DoubleQuotedString,css:"string"},{regex:new RegExp("^\\s*#.*","gm"),css:"preprocessor"},{regex:new RegExp(this.GetKeywords($),"gm"),css:"keyword"}];this.CssClass="dp-vb"};dp.sh.Brushes.Vb.prototype=new dp.sh.Highlighter();dp.sh.Brushes.Vb.Aliases=["vb","vb.net"];dp.sh.Brushes.Xml=function(){this.CssClass="dp-xml";this.Style=".dp-xml .cdata { color: #ff1493; }"+".dp-xml .tag, .dp-xml .tag-name { color: #069; font-weight: bold; }"+".dp-xml .attribute { color: red; }"+".dp-xml .attribute-value { color: blue; }"};dp.sh.Brushes.Xml.prototype=new dp.sh.Highlighter();dp.sh.Brushes.Xml.Aliases=["xml","xhtml","xslt","html","xhtml"];dp.sh.Brushes.Xml.prototype.ProcessRegexList=function(){function B(_,$){_[_.length]=$}var $=0,A=null,_=null;this.GetMatches(new RegExp("(<|<)\\!\\[[\\w\\s]*?\\[(.|\\s)*?\\]\\](>|>)","gm"),"cdata");this.GetMatches(new RegExp("(<|<)!--\\s*.*?\\s*--(>|>)","gm"),"comments");_=new RegExp("([:\\w-.]+)\\s*=\\s*(\".*?\"|'.*?'|\\w+)*|(\\w+)","gm");while((A=_.exec(this.code))!=null){if(A[1]==null)continue;B(this.matches,new dp.sh.Match(A[1],A.index,"attribute"));if(A[2]!=undefined)B(this.matches,new dp.sh.Match(A[2],A.index+A[0].indexOf(A[2]),"attribute-value"))}this.GetMatches(new RegExp("(<|<)/*\\?*(?!\\!)|/*\\?*(>|>)","gm"),"tag");_=new RegExp("(?:<|<)/*\\?*\\s*([:\\w-.]+)","gm");while((A=_.exec(this.code))!=null)B(this.matches,new dp.sh.Match(A[1],A.index+A[0].indexOf(A[1]),"tag-name"))}
//}}}
!Workflow of ~HaikuVM
!!step one (java to class)
Translate your JAVA program with [[haikuc]] into a class-file (bytecode). This will translate the JAVA class given by you. From this seed it recursively determines which classes and class members are used. All other classes and class members are discarded. For this job [[haikuc]] uses javac. But it will not compile against rt.jar (the standard JAVA runtime). Instead it will use the leJOS runtime which is given in classes.jar. Superseded by haikuvm.jar, to pick and overwrite a specific small set of this leJOS runtime classes to adapt to ~HaikuVM and micros.
!!step two (class to C)
Basicaly [[haikulink]] will read the bytecode (using the BECL library) and translate it into C data structures. In contrast, other systems e.g. GCJ will translate direct into C program code. With Haiku the only C code is the C code of the Haiku virtual machine (~HaikuVM) itself augmented with C data structures. Together this is linked into the binary by [[haikulink]]. During runtime (e.g. in an Atmega8) the ~HaikuVM interpretes the data in the (above mentioned) C data structures. ([[More ...|Compact HaikuVM Code]])
!!step three (C to binary)
Because [[haikulink]] translated into C code we now need to cross-compile it for the target machine. This is in contrast to leJOS (and nanoVM) where no cross-compiling step is needed. On the other hand cross-compiling allows a tight coupling of the above C data structures and the ~HaikuVM. In addidion the linker step will eliminate all unneeded code and data. This is the main reason for having suprisingly short binaries representing your JAVA program.
!!step four (upload and run)
[[haikuupload]] uploads the binary builded in step three, to the microprocessor.
!Philosopie of ~HaikuVM
~HaikuVM tries to use as less as possible native methods. (Native methods are methods which have to be written in C.) The idea is to reduce (not restrict) the native methods to the following small set:
A) reading from and writting to RAM memory like this:
*public static native int getMemory8(int adr);
*public static native void setMemory8(int adr, int value);
*... about 10 more memory setter and getter methods
B) A method for getting the time in milliseconds:
*public static native long currentTimeMillis();
C) A method for copying arrays:
*public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
D) And methods for Thread schedule:
*private native int fork();
*private native int setStateAndSwitch(int state);
An example for reading analog data from an Atmega8:
<code java>
...
public static final long F_CPU = 8000000L;
public static final int REFS0 = 6;
public static final int ADSC = 6;
public static final int ADIF = 4;
public static final int ADC = (((0x04) + 0x20)); //16Bit
public static final int ADCSRA = (((0x06) + 0x20));
public static final int ADMUX = (((0x07) + 0x20));
...
public static int ReadADC(int mux) {
setMemory8(ADMUX, (1 << REFS0) | mux); // voltage reference with external capacity
setMem(ADCSRA, (1 << ADSC)); // start the AD conversion
while ((getMemory8(ADCSRA) & (1 << ADIF)) == 0) // wait for the end of the AD conversion
;
return getMemory16(ADC); // read 16Bit result
}
</code>
To handle native methods like found in the given leJOS classes.jar you have two choices:
#Write your own native C code for a native JAVA function. ([[More ...|native JAVA methods]])
#Redirect a native method back to a plain JAVA method (and use memory setter and getter methods). ([[More ...|redirect JAVA methods]])
Before a simple ~HalloWorld Java program like this:
<code java>
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
</code>
will run on a micro you have to initialize several things. This boilerplate code for basic initialization have to be written for each Java program you write. Typically you have to write code for:
* initialize serial output (baud rate etc.).
* code a basic write(aByte) and readByte() method.
* initialize a time base.
* write an exception handler.
You find two different approaches for this:
* Write code for initialization in your Java program<br>This is flexible when adapting to different ~AVRs but pollutes your Jave code.
* Write code for initialization in C, here in Haiku VM's C code<br>This has to be specific for an AVR model and could be done for every AVR with a big #if. But then it's easy to forget a specific AVR or initialisation aspect. In this concern it's an inflexible approach but, at the end, does not pollute your Java code.
Here I give you an example for the first approach: initialization in your Java program:
<code java>
package arduino.tutorial;
import static haiku.avr.AVRConstants.*;
public class HelloWorldWithoutHaikuKernel {
private static final int BAUD_RATE = 57600;
private static final long F_CPU = 16000000;
private static void init() {
// set baud rate
final short t = (short) (((F_CPU >> 4) + (BAUD_RATE >>> 1)) / BAUD_RATE - 1);
UBRR0H = (t >>> 8);
UBRR0L = t;
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
}
private static void write(int b) {
while ((UCSR0A & (1 << UDRE0)) == 0)
;
UDR0 = b;
}
public static void println(String line) {
for (int i = 0; i < line.length(); i++) {
write(line.charAt(i));
}
write('\r');
write('\n');
}
public static void main(String[] args) {
init();
println("Hello World");
while(true) ;
}
}
</code>
Because no timer methods are needed and no exceptions are thrown the code for initializing this is neglegted.
~HaikuVM follows an innovative third approach by introducing a ''~MicroKernel''. The idea is that the ~MicroKernel, written in Java, should cover all the model specific initialisation. So the C part of ~HaikuVM can kept more generic and free from model specific C code. While your main Java program can be expressed without being polluted by boilerplate code for specific AVR initialization.
Factoring out initialisation code from ~HelloWorldWithoutHaikuKernel into a ~HaikuKernel looks like this:
<code java>
package arduino.tutorial;
import static haiku.avr.AVRConstants.*;
import java.io.*;
public class HaikuKernel {
private static final int BAUD_RATE = 57600;
private static final long F_CPU = 16000000;
private static void init() {
// set baud rate
final short t = (short) (((F_CPU >> 4) + (BAUD_RATE >>> 1)) / BAUD_RATE - 1);
UBRR0H = (t >>> 8);
UBRR0L = t;
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
// set timer 0 prescale factor to 64
TCCR0B = (1<<CS01) | (1<<CS00);
// enable timer 0 overflow interrupt
TIMSK0 = (1<<TOIE0);
System.out = new PrintStream(new OutputStream() {
public void write(int b) throws IOException {
while ((UCSR0A & (1 << UDRE0)) == 0)
;
UDR0 = b;
}
});
}
public static void main(String[] args) {
init();
haiku.vm.HaikuMagic.main(args);
Thread.currentThread().stop();
}
}
</code>
In conjunction with this ~HaikuKernel you are ready to use the Java program from the very begin of this tutorial. For this you have to configure it in '~HaikuVM.properties' to be used with your configuration.
I'm sure you noticed the hint in line 35, leading us to some Haiku magic. The magic here is that [[haikulink]] will substitute the call of ''haiku.vm.~HaikuMagic.main(args)'' by the call of your Java main method. Effectively resulting in a call of ''~HelloWorld.main(args)'' during runtime, in this tutorial.
The download of ~HaikuVM includes predefined HaikuKernels for several AVR models and plattforms. If yours is missing and you designed a HaikuKernel for it, please send it to me. I will include it in future versions of ~HaikuVM.
Advantages of using a ~MicroKernel:
* no need for JNI code to initialize your AVR.
* full flexibility in Java having no need to switch to C.
* initialization code written in Java ~MicroKernels tends to be 4 times shorter than equivalent C code (see [[Compact]]).
* exception handler is seamingly integrated in the general exception handling of Java.
To be continued ...
There might be situations where interaction with an C interrupt routine is wanted. ~HaikuVM, as a JAVA VM, does not support interrupts. Instead, interrupt routines have to be written in C. This can be done for every interrupt, except for the timer 0 overflow interrupt which is reserved for ~HaikuVM's timing.
It's not the goal of this tutorial to explain interrupts. Here are great tutorials on AVR interrupts:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=55347
In this tutorial I want to show how to interact with a '~TIMER2_OVF_vect' interrupt routine. The timer 2 overflow interrupt is handled in function '~TIMER2_OVF_vect' mean and lean by just incrementing a variable of type jlong. This is how the C code looks like to accomplish this:
<code cpp>
#include ???
#include <avr/interrupt.h>
volatile static jlong timer2_interrupts = 0;
ISR(TIMER2_OVF_vect) {
timer2_interrupts ++;
}
</code>
On the other end there is a Java program which wants to read out the value of timer2_interrupts and prints the first 10 values. This is how the Java program looks like (until now):
<code java>
package arduino.tutorial;
import static haiku.avr.AVRConstants.*;
public class InterruptTimer2 {
private static native long getTimer2();
public static void main(String[] args) {
// TODO: set up timer2
for (int i = 0; i < 10; i++) {
System.out.println("Value of timer2_interrupts is: " + getTimer2());
}
}
}
</code>
As you may have expected, we use a ''native'' Java method to read out the value of timer2_interrupts (see line 05). From the [[Tutorial JNI]] we have learned that ''all'' JNI C function wrappers are generated during the [[haikulink]] phase and placed in file './myCProject/haikuC/haikuJNI.c' for cut&past usage. So we pick our getTimer2(..) function wrapper and getTime2(..) JNI template from there and cut&past it into our C file which now becomes:
<code cpp>
#include <jni.h>
#include <avr/interrupt.h>
volatile static jlong timer2_interrupts = 0;
ISR(TIMER2_OVF_vect) {
timer2_interrupts ++;
}
/**
* Automatic generated JNI template
* getTimer2()J
*/
jlong Java_avr_tutorial_Interrupt1_getTimer2( JNIEnv *env, jobject obj) {
// TODO: insert your code here
return 0;
}
/**
* Automatic generated JNI wrapper
* getTimer2()J
*/
void native_arduino_tutorial_InterruptTimer2_getTimer2_J(void) {
pushTop(); // Save variable top onto stack.
{
jobject obj = NULL;
JNIEnv *env = NULL;
top.j = Java_arduino_tutorial_InterruptTimer2_getTimer2(env, obj);
}
// Variable top holds the return value. But we have to push the lower half.
pushTop0();
}
</code>
(Don't forget to insert line 01 to include the basic JNI type declarations etc. .)
If you inspect the JNI function '~Java_avr_tutorial_Interrupt1_getTimer2(env, obj)' you will see a TODO which has to be filled. In our case we want to access and return the value of timer2_interrupts:
<code cpp>
#include <jni.h>
#include <avr/interrupt.h>
volatile static jlong timer2_interrupts = 0;
ISR(TIMER2_OVF_vect) {
timer2_interrupts ++;
}
/**
* Automatic generated JNI template
* getTimer2()J
*/
jlong Java_arduino_tutorial_InterruptTimer2_getTimer2(JNIEnv *env, jobject obj) {
jlong value;
uint8_t oldSREG = SREG;
cli(); // we don't want to be desturbed by an interrupt
value = timer2_interrupts;
SREG = oldSREG; // restore interruptable state again.
return value;
}
/**
* Automatic generated JNI wrapper
* getTimer2()J
*/
void native_arduino_tutorial_InterruptTimer2_getTimer2_J(void) {
pushTop(); // Save variable top onto stack.
{
jobject obj = NULL;
JNIEnv *env = NULL;
top.j = Java_arduino_tutorial_InterruptTimer2_getTimer2(env, obj);
}
// Variable top holds the return value. But we have to push the lower half.
pushTop0();
}
</code>
(See also './haikuVM/myCProject/tutorials/interruptTimer2.c').
There is only a final step missing. We have to initialize timer 2 and its overflow interrupt (here for ~ATmega328p) . In this example its done in the Java main(..) method of our example (see also 'arduino.tutorial/~InterruptTimer2.java'):
<code java>
package arduino.tutorial;
import static haiku.avr.AVRConstants.*;
public class InterruptTimer2 {
private static native long getTimer2();
public static void main(String[] args) {
// prescaler 1024
TCCR2B = (1<<CS22) | (1<<CS21) | (1<<CS20);
// enable timer interrupt overflow
TIMSK2 = (1<<TOIE2);
for (int i = 0; i < 10; i++) {
System.out.println("Value of timer2_interrupts is: " + getTimer2());
}
}
}
</code>
Have fun when playing with different prescale values!
In case you write some Java code which declares a ''native method'' like here:
<code java>
package arduino.tutorial;
public class JNItest1 {
private static native int add(int a, int b);
public static void main(String[] args) {
int a=3;
int b=4;
System.out.println(a+" + "+b+" = "+add(a,b));
}
}
</code>
~HaikuVM will detect this situation during the run of [[haikulink]] and writes JNI code templates and some wrapper code which is special for ~HaikuVM in your project directory file './myCProject/haikuC/haikuJNI.c'. In our case you will find something like this:
<code cpp>
...
/**
* Automatic generated JNI template
* add(II)I
*/
jint Java_arduino_tutorial_JNItest1_add(JNIEnv *env, jobject obj, jint arg1, jint arg2) {
// TODO: insert your code here
return 0;
}
/**
* Automatic generated JNI wrapper
* add(II)I
*/
void native_arduino_tutorial_JNItest1_add_III(void) {
pushTop(); // Save variable top onto stack.
{
jint arg2 = pop()->i;
jint arg1 = pop()->i;
jobject obj = NULL;
JNIEnv *env = NULL; // not used in HaikuVM
top.s1.i = Java_arduino_tutorial_JNItest1_add(env, obj, arg1, arg2);
}
// Variable top holds the return value.
}
...
</code>
You have to copy this into some C file of your project directory. In case of this tutorial do this in file './myCProject/tutorial/~JNItest.c'. And give life to the JNI function by inserting your code near the line marked with TODO. In our case add arg1 and arg2.
<code cpp>
#include <jni.h>
/**
* Automatic generated JNI template
* add(II)I
*/
jint Java_arduino_tutorial_JNItest1_add(JNIEnv *env, jobject obj, jint arg1, jint arg2) {
return arg1 + arg2;
}
/**
* Automatic generated JNI wrapper
* add(II)I
*/
void native_arduino_tutorial_JNItest1_add_III(void) {
pushTop(); // Save variable top onto stack.
{
jint arg2 = pop()->i;
jint arg1 = pop()->i;
jobject obj = NULL;
JNIEnv *env = NULL; // not used in HaikuVM
top.s1.i = Java_arduino_tutorial_JNItest1_add(env, obj, arg1, arg2);
}
// Variable top holds the return value.
}
</code>
That's it! Now compile (by using haikulink) again and your native function will be used. Easy isn't it? (Don't forget to include 'jni.h', as can be seen in line 01.)
''Note''
~HaikuVM is a simple VM. When calling one of your JNI C functions the complete Haiku VM (that is every thread) is suspended. So keep in mind, that your JNI C functions have to be cooperative and lean.
----
Let's proceed with an example using other Java types. Here the first native function should add an int, float and double. A second native function should deliver the result.
<code java>
package arduino.tutorial;
public class JNItest2 {
private static native void add(int a, float b, double c);
private static native double result();
public static void main(String[] args) {
int a=3;
float b=4;
double c=5;
add(a, b, c);
System.out.println(a+" + "+b+" + "+c+" = "+result());
}
}
</code>
Again copy the needed functions from 'haikuJNI.h' into file './myCProject/tutorial/~JNItest.c'. And insert the intended code. You should come out with something similar like this:
<code cpp>
#include <jni.h>
static double result;
/**
* Automatic generated JNI template
* add(IFD)V
*/
void Java_arduino_tutorial_JNItest2_add(JNIEnv *env, jobject obj, jint arg1, jfloat arg2, jdouble arg3) {
result = arg1 + arg2 + arg3;
}
/**
* Automatic generated JNI wrapper
* add(IFD)V
*/
void native_arduino_tutorial_JNItest2_add_IFDV(void) {
pushTop(); // Save variable top onto stack.
{
jdouble arg3 = popp2()->d;
jfloat arg2 = pop()->f;
jint arg1 = pop()->i;
jobject obj = NULL;
JNIEnv *env = NULL; // not used in HaikuVM
Java_arduino_tutorial_JNItest2_add(env, obj, arg1, arg2, arg3);
}
popTop();
}
/////////////////////////////////////////////////
/**
* Automatic generated JNI template
* result()D
*/
jdouble Java_arduino_tutorial_JNItest2_result(JNIEnv *env, jobject obj) {
return result;
}
/**
* Automatic generated JNI wrapper
* result()D
*/
void native_arduino_tutorial_JNItest2_result_D(void) {
pushTop(); // Save variable top onto stack.
{
jobject obj = NULL;
JNIEnv *env = NULL; // not used in HaikuVM
top.d = Java_arduino_tutorial_JNItest2_result(env, obj);
}
// Variable top holds the return value. But we have to push the lower half.
pushTop0();
}
</code>
Come on, be brave and give it a try. The output is unexpected:
{{{
3 + 4.0 + 5.0 = 17416.0
}}}
What's wrong here? Remember that in 16/32 mode (see [[Configurable 64, 32 or 16 bit data types]] and in [[half precision float]]) a Java float is a 16Bit data type and therefore is just a storage type. The AVR compiler does not support 16Bit floats. You have to use the right ~HaikuVM macros to unpack/pack float16 to something meaningful for AVR, as so:
<code cpp>
#include <jni.h>
static double result;
/**
* Automatic generated JNI template
* add(IFD)V
*/
void Java_arduino_tutorial_JNItest2_add(JNIEnv *env, jobject obj, jint arg1, jfloat arg2, jdouble arg3) {
result = arg1 + TF2FLOAT(arg2) + TD2DOUBLE(arg3);
}
/**
* Automatic generated JNI wrapper
* add(IFD)V
*/
void native_arduino_tutorial_JNItest2_add_IFDV(void) {
pushTop(); // Save variable top onto stack.
{
jdouble arg3 = popp2()->d;
jfloat arg2 = pop()->f;
jint arg1 = pop()->i;
jobject obj = NULL;
JNIEnv *env = NULL; // not used in HaikuVM
Java_arduino_tutorial_JNItest2_add(env, obj, arg1, arg2, arg3);
}
popTop();
}
/////////////////////////////////////////////////
/**
* Automatic generated JNI template
* result()D
*/
jdouble Java_arduino_tutorial_JNItest2_result(JNIEnv *env, jobject obj) {
return DOUBLE2TD(result);
}
/**
* Automatic generated JNI wrapper
* result()D
*/
void native_arduino_tutorial_JNItest2_result_D(void) {
pushTop(); // Save variable top onto stack.
{
jobject obj = NULL;
JNIEnv *env = NULL; // not used in HaikuVM
top.d = Java_arduino_tutorial_JNItest2_result(env, obj);
}
// Variable top holds the return value. But we have to push the lower half.
pushTop0();
}
</code>
Now we get the expected result:
{{{
3 + 4.0 + 5.0 = 12.0
}}}
As you can see in line 09 and 37, I was extra careful and used the unpack/pack macros for doubles, as well. Just to make this code more portable in case you want to give it a try in 16/16 memory mode.
To be continued ...
Here are great tutorials on AVR timers:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=50106
This tutorial on timing in ~HaikuVM compliments those. Those tutorials are aimed at the C language, here I'll give some insight on how ~HaikuVM uses the AVR's timers.
First of all, the VM of Haiku (written in C) does not set or configure any timer, it's up to your Java program to do that. Many simple C and therefore Java programs do work without the use of timers.
On the other hand, when you start to use some of Java's time methods like
*Thread.sleep(..),
*Thread.wait(..),
*System.currentTimeMillis() or
*you want to use multiple Threads
then ''a proper setup of timer 0 is important''. The VM of Haiku is designed in a way that proper timing relies on timer 0 overflow interrupt. The timer 0 overflow interrupt is handled in an already predefined interrupt routine '~TIMER0_OVF_vect' (located in file './haikuVM/simpleOS.c') and just increments variable 'timer0_interrupts'. From this variable the function millis() derives the milliseconds for Thread.sleep(..), Thread.wait(..), etc. and for Thread scheduling. Here is some code, to give you a clue:
<code cpp>
volatile jmillis timer0_interrupts = 0;
...
SIGNAL(TIMER0_OVF_vect)
{
timer0_interrupts++;
}
...
julong millis()
{
jmillis m;
uint8_t oldSREG = SREG;
cli();
m = timer0_interrupts;
SREG = oldSREG;
return m * HAIKU_MillisDividend / HAIKU_MillisDivisor;
}
</code>
Where ''~HAIKU_MillisDividend'' and ''~HAIKU_MillisDivisor'' are #defines (see file 'haikuDefs.h') and those values will be pre-calculated automatically during the [[haikulink]] phase (derived from HaikuVM property Clock (see [[HaikuVM.properties]] assuming a prescaler of 64 for timer 0). If, for some reasons, you don't want to live with the predefined values or program a different prescal you have to define your values manually in file '~HaikuVM.properties' like this:
<code bash>
myconfig.MillisDividend = 128
myconfig.MillisDivisor = 125
</code>
Where "myconfig" is the Config-parameter you choose in the commandline of [[haikulink]] or [[haiku]].
This is a snipped showing how you setup the timer 0 with a prescale of 64 and enable timer 0 overflow interrupt for an Atmega8, Atmega16, etc.:
<code java>
import static haiku.avr.AVRConstants.*;
...
// In main():
// Timer-Configuration: Prescaler to 1/64
TCCR0 |= (1 << CS01);
TCCR0 |= (1 << CS00);
// Timer-Overflow-Interrupt-Enable Timer0
TIMSK |= (1 << TOIE0);
...
</code>
This is a snipped showing how you setup the timer 0 with a prescale of 64 and enable timer 0 overflow interrupt for an Atmega328p, etc.:
<code java>
import static haiku.avr.AVRConstants.*;
...
// In main():
TCCR0B |= _BV(CS01) | _BV(CS00); // set prescaler to 1/64
TIMSK0 |= _BV(TOIE0); // Timer0-Overflow-Interrupt-Enable
...
</code>
For a complete, running Java example which sets up timer 0 for ~ATmega328p take a look at 'C:\haikuVM\examples\src\main\java\avr\tutorial\Blink.java'.
Here is a table, presenting what ''~MillisDividend'' and ''~MillisDivisor'' ~HaikuVM will calculate and assign automatically (in blue) for some commonly used Clock values [Hz], if not defined manually.
| Clock [Hz] | Prescale | ~MillisDividend | ~MillisDivisor | Error in [ms/s] | Overflow32 [min] | Resolution [ms] |
| 8000000 | 1| 4 | 125 |0.00000 | 572.662 | 0.0320000 |
|~| 8| 32 | 125 |0.00000 | 572.662 | 0.256000 |
|~| 64|bgcolor(#66f): 256 |bgcolor(#66f): 125 |0.00000 | 572.662 | 2.04800 |
|~| 256| 1024 | 125 |0.00000 | 572.662 | 8.19200 |
|~| 1024| 2261 | 69 |0.00353827 | 1037.43 | 32.7681 |
||||||||
| 12000000 | 1| 8 | 375 |0.00000 | 190.887 | 0.0213333 |
|~| 8| 64 | 375 |0.00000 | 190.887 | 0.170667 |
|~| 64|bgcolor(#66f): 512 |bgcolor(#66f): 375 |0.00000 | 190.887 | 1.36533 |
|~| 256| 2048 | 375 |0.00000 | 190.887 | 5.46133 |
|~| 1024| 2119 | 97 |0.00125846 | 737.967 | 21.8454 |
||||||||
| 15000000 | 1| 32 | 1875 |0.00000 | 38.1775 | 0.0170667 |
|~| 8| 256 | 1875 |0.00000 | 38.1775 | 0.136533 |
|~| 64|bgcolor(#66f): 2048 |bgcolor(#66f): 1875 |0.00000 | 38.1775 | 1.09227 |
|~| 256| 2853 | 653 |-0.000186938 | 109.621 | 4.36907 |
|~| 1024| 367 | 21 |-0.00435965 | 3408.70 | 17.4762 |
||||||||
| 16000000 | 1| 2 | 125 |0.00000 | 572.662 | 0.0160000 |
|~| 8| 16 | 125 |0.00000 | 572.662 | 0.128000 |
|~| 64|bgcolor(#66f): 128 |bgcolor(#66f): 125 |0.00000 | 572.662 | 1.02400 |
|~| 256| 512 | 125 |0.00000 | 572.662 | 4.09600 |
|~| 1024| 2048 | 125 |0.00000 | 572.662 | 16.3840 |
||||||||
| 20000000 | 1| 8 | 625 |0.00000 | 114.532 | 0.0128000 |
|~| 8| 64 | 625 |0.00000 | 114.532 | 0.102400 |
|~| 64|bgcolor(#66f): 512 |bgcolor(#66f): 625 |0.00000 | 114.532 | 0.819200 |
|~| 256| 2048 | 625 |0.00000 | 114.532 | 3.27680 |
|~| 1024| 367 | 28 |-0.00435965 | 2556.53 | 13.1071 |
*Overview
**[[Tool Chain]]
**[[Architecture]]
**[[Your Project on Disk and at Runtime]]
*Tutorials
**[[Tutorial Blinky]]
**[[Tutorial Timing]]
**[[Tutorial Basic Serial IO]]
**[[Tutorial Use Your Own C main Function]]
**[[Tutorial JNI]]
**[[Tutorial Access to C Libraries]]
**[[Tutorial Interrupts]]
**[[Tutorial All About MicroKernels]]
**[[Arduino]]
**[[Wiring]]
**[[Asuro]]
*~IDEs
**[[Eclipse]]
~HaikuVM is a JAVA VM for microcontrollers. It implements all JAVA bytecodes.
~HaikuVM has been started for hobbyists who develop applications for ~AVRs (e.g. ARDUINO) to open the world of JAVA.
''Yes, with ~HaikuVM you can program an ARDUINO with JAVA!'' ([[More ...|Arduino]])
~HaikuVM is so small that it even runs on an atmega8 (and the ASURO robot).
''And yes, you can program an ASURO robot with JAVA!'' ([[More ...|Asuro]])
But for the beginner I suggest to start with a simple and basic AVR example. ([[More ...|BlinkSimple]])
~HaikuVM works by compiling JAVA bytecode to C data structures to be compiled by a C cross compiler for your target platform. So, the resulting code is small and fast. ([[More ...|Architecture]])
This is how to program an Arduino in JAVA using the wiring habit (not using main() but setup() and loop()) and library to let the LED blink.
<code java>
package wiring.tutorial;
import static haiku.avr.lib.arduino.WProgram.*;
public class Blink {
static byte ledPin = 13; // LED connected to digital pin 13
public static void loop() // run over and over again
{
digitalWrite(ledPin, HIGH); // sets the LED on
delay(1000); // waits for a second
digitalWrite(ledPin, LOW); // sets the LED off
delay(1000); // waits for a second
}
public static void setup() {
pinMode(ledPin, OUTPUT); // sets the digital pin as output
}
}
</code>
A part of the ''wiring core library 022'' is ported to JAVA. For the rest help is wanted.
Currently supported functions:
<code c>
map()
random()
randomSeed()
millis()
delay()
delayMicroseconds()
analogRead()
analogWrite()
pinMode()
digitalRead()
digitalWrite()
</code>
!On the Disk
You have to move (cd) into an empty directory which will be used for your project. Any empty directory will do. In addition, ~HaikuVM comes with a template directory called 'myCProject' for your project (and tutorials). At the beginning, and to follow the examples and tutorials more literally, I suggest to pick this one.
*''myCProject'' (Any other name and empty directory, elsewhere on your disk, will do as well.)<br>During a run of haikulink directories will be created here. (Some only once.)
**''haikuC''<br>Mainly constants and static variables including method- and exception-tables as derived from your Java program. Other stuff like JNI function templates and debug information.
**''haikuJava''<br>Bytecode as prepared and linked for the ~Haiku-VM. "Bytecode" here has to be translated to "C structs". There is a *.c and *.h file for each Java class. Filled with two kinds of C structs ([[More...|Compact HaikuVM Code]]):
***C structs containing the Java class methods bytecode.
***C structs describing the memory layout of the class and instance.
**''haikuVM'' (Only once. Has to be deleted to be created again.)<br>The Java VM. A clone from haikuVM (see [[Architecture]]).
**''target/cross''<br>Contains all stuff needed for 'make' to cross compile your project.
!On the Microcontroller
Here is a diagram to give you an impression about how flash memory is used from ~HaikuVM. This is only a rough estimate about the relation of the sections mentioned below. The concret layout (and order) is not important for ~HaikuVM and is up to the AVR linker.
|e| possible unused |
|e|~|
|e|~|
|e|~|
|e|~|
|d|bgcolor(#6f6): Your Java Program |
|d|~|
|d|~|
|d|~|
|c|bgcolor(#6d6): Your ~MicroKernel (possible empty) |
|b|bgcolor(#6b6): Constants and exception tables |
|a|bgcolor(#66b): The haikuVM |
|a|~|
| flash usage |c
*''Section [a] The haikuVM''<br>This section corresponds to the project directory haikuVM. It contains the C program which in fact is the ~Haiku-VM (the equivalent to the Java VM). Although the sourcecode of ~HaikuVM has constant size, the resulting flash memory consumption of section [a-b] depends of your Java program. This is because ~HaikuVM is designed in a way that the AVR linker is able to pick only the source code needed. For example if you don't use double devision the bytecode DDIV (which divides two doubles) is not linked into the flash image. (And therefore saves space.)
*''Section [b] Constants and exception tables''<br>This section corresponds to the project directory haikuC.
*''Section [c] Your ~MicroKernel (possible empty)''<br>This section corresponds to the project directory haikuJava. This is only a logical section. Physically it's completely merged with section [d].
*''Section [d] Your Java Program''<br>This section corresponds to the project directory haikuJava and contains the bytecode (as refined by haikulink) of your Java Program.
|C|bgcolor(#6f6): Java stack and object heap |
|C|~|
|C|~|
|C|~|
|C|~|
|B|bgcolor(#6d6): Java static variables |
|A|bgcolor(#66b): C stack (ABI) and variables for ~Haiku-VM |
| RAM usage |c
*''Section [A] C stack (ABI) and variables for ~Haiku-VM''<br>This section defines the space which is needed for the plain ~Haiku-VM to do its job.
*''Section [B] Java static variables''<br>This section defines the space for the Java static variables your Java program (section [c] + [d]) is using.
*''Section [C] Java stack and object heap''
''Note''
The size of section [B] + [C] is defined by your ~HaikuVM property ''Memory'' as declared in [[HaikuVM.properties]] of your configuration. The rest of the RAM is used by section [A]. Please select ~HaikuVM property ''Memory'' in a way that section [A] has room to live. In my experience 300 byte is enough.
For being portable, I decided to code the VM in pure C (no assembler and no C++).
For garbage collection
{{{--Config:GC HAIKU_NoGC}}}
{{{--Config:GC HAIKU_StopTheWorldGC}}} (default)
{{{--Config:GC HAIKU_IncrementalGC}}}
For configurable 64, 32 or 16 bit data types
{{{--Config:Mode HAIKU_32_64}}} or equivalent {{{--Config:Mode 32/64}}} (for JAVA compliants)
{{{--Config:Mode HAIKU_32_32}}} or equivalent {{{--Config:Mode 32/32}}}
{{{--Config:Mode HAIKU_16_32}}} or equivalent {{{--Config:Mode 16/32}}} (default and most convenient for micros)
{{{--Config:Mode HAIKU_16_16}}} or equivalent {{{--Config:Mode 16/16}}}
For configurable 16 or 8 bit char type
{{{--Config:Char HAIKU_CHAR_16}}} or equivalent {{{--Config:Char HAIKU_CHAR_2}}}
or equivalent {{{--Config:Char 16}}} or equivalent {{{--Config:Char 2}}} (for JAVA compliants)
{{{--Config:Char HAIKU_CHAR_8}}} or equivalent {{{--Config:Char HAIKU_CHAR_1}}}
or equivalent {{{--Config:Char 8}}} or equivalent {{{--Config:Char 1}}} (default and most convenient for micros)
The JAVA type ''double'' is mapped to C type ''float''.
~HaikuVM supports double and float types. But details depend on the underlying hardware and C compiler infrastructure. Because ~HaikuVM works by translating JAVA bytecode to C code. So, for instance, the WINAVR C Compiler supports double and float types but the double type has only 32 Bits and is, behind the scenes, effectively a C float type.
!link, upload and run a program
Usage:
haiku [options] main-class
Example:
{{{
haiku -v HelloWorld
}}}
The haiku command links and uploads a JAVA program. It is the equivalent of haikulink followed by haikuupload.
Any of the options for haikulink and haikuupload can be specified.
The default binary name is <main-class>.hex, e.g. Tune.hex.
!compile a JAVA program
Compiles one or more java files.
Usage: haikuc <java-files>
Example:
{{{
haikuc HelloWorld.java
}}}
Internally haikuc calls javac with parameters:
-bootclasspath <path to haiku.jar and classes.jar> <java-files>
-bootclasspath is set because ~HaikuVM does not use the standard java.lang classes but has its own versions in haiku.jar and classes.jar.
See also [[Commands]].
!haikufy the program and cross-compile the resulting C Program
Calls the ~HaikuVM linker.
Usage:
haikulink [-v|"""--"""verbose] [-g|"""--"""debug] [-gr|"""--"""remotedebug] [-a|"""--"""all]
[-dm|"""--"""disablememcompaction] [-ea|"""--"""enableassertions] [-ec|"""--"""enablechecks]
["""--"""Config <config>] ["""--"""Config:<propertyname> <value>]* [-od|"""--"""outputdebug <debug-file> ]
-o <binary> main-class
Example:
{{{
haikulink -v -o HelloWorld.hex HelloWorld
}}}
Links the specified main class with any classes that it refers in the current directory and with the standard ~HaikuVM classes from haiku.jar and classes.jar (from leJOS) to produce a C program. Next this C program will be cross-compiled into the binary HEX program that can be uploaded and run.
The -v or """--"""verbose flag causes a list of class names and method signatures included in the binary to be sent to the standard output. This output is extremely useful for debugging.
The -g or """--"""debug flag is not yet supported by ~HaikuVM.
The -gr or """--"""remotedebug flag is not yet supported by ~HaikuVM.
The -od or """--"""outputdebug flag is not yet supported by ~HaikuVM.
The -ec or """--"""enablechecks flag is used to enable additional run time checks. These checks are relatively expensive (and rarely generate errors) and so are off by default. The checks that this setting enables is defined in [[HaikuVM.properties]] by the property ~InternalExceptionEnable and are usually:
*~NullPointerException
*~NoSuchMethodError
*~OutOfMemoryError
*~ClassCastException
*~VirtualMachineError
*~ArrayIndexOutOfBoundsException
*~StackOverflowError
The -ea or """--"""enableassertions flag is used to enable the checking of assert statements with the program.
The -dm or """--"""disablememcompactions flag is always set for ~HaikuVM. So memory compaction is always disabled and can not be enabled for ~HaikuVM. Normally a marture garbage collector will attempt to move large objects in memory to maximize the amount of contiguous free space, this is not implemented in the simple garbage collector of ~HaikuVM.
The linker removes methods that are not used. Specify -a or """--"""all to include all methods whether they are used or not. This should never be necessary.
The -o <binary> option is used to define the name of the output file.
The """--"""Config <config> option is an addition of ~HaikuVM to specify (overwrite) the default configuration of the [[HaikuVM.properties]].
The """--"""Config:<propertyname> <value> option is an addition of ~HaikuVM to set (overwrite) any value of the [[HaikuVM.properties]].
Use the -h or """--"""help flag to print out the options.
!upload a program
Usage:
haikuupload ["""--"""Config:<propertyname> <value>]* <binary>
Example:
{{{
haikuupload HelloWorld.hex
}}}
Uploads the binary (.hex) file.
None of the (leJOS) options are supported yet (but may be in future). Instead the upload is configurated in [[HaikuVM.properties]] and may be changed in the command line by overwriting property values with the option """--"""Config:<propertyname> <value>.
The JAVA type ''double'' type is a half precision float.
*The minimum strictly positive (subnormal) value is 2^-24 ~ 5.96 * 10^-8.
*The minimum positive normal value is 2^-14 ~ 6.10 * 10^-5.
*The maximum representable value is (2-2^-10) * 2^15 = 65504.
The JAVA ''double'' is only a storage type. The ~HaikuVM unpacks it into a C float for calculations.
~HaikuVM supports half precision float (see [[wikipedia|http://en.wikipedia.org/wiki/Half-precision_floating-point_format]]) in case you select a 16Bit data type for JAVA type ''float''. This is only a storage type. The ~HaikuVM unpacks it into a C float for calculations.
*The minimum strictly positive (subnormal) value is 2^-24 ~ 5.96 * 10^-8.
*The minimum positive normal value is 2^-14 ~ 6.10 * 10^-5.
*The maximum representable value is (2-2^-10) * 2^15 = 65504.
~HaikuVM, at its core, is just another JAVA VM for micros. I decided to go without building an own JAVA runtime. Instead ~HaikuVM is tailor made to use the JAVA runtime coming with [[leJOS|http://en.wikipedia.org/wiki/LeJOS]].
''NOT IMPLEMENTED'' But this is the idea:
Besides //bootclasspath// and //classpath//, well known from javac, [[haikulink]] supports a third form called //redirectmethodpath//.
For example currentTimeMillis() is defined as ''native'' in java.lang.System:
<code java>
package java.lang;
...
public class System {
...
/**
* Returns the current time in milliseconds.
* This is the number of milliseconds since the AVR has been on.
*/
public static native long currentTimeMillis();
...
}
</code>
If you don't want to implement it in plain C and you know the memory address where the millis are stored, lets say for example the address is 123, you might write a second class System including a implementation of currentTimeMillis() like this:
<code java>
package java.lang;
public class System {
public static long currentTimeMillis() {
return haiku.vm.MemoryAccess.getMemoryLong(123);
}
}
</code>
Lets say the class file is 'C:\haikuVM\myCProject\redirects\java\lang\System.class' then, to use it, you have to call [[haikulink]] like this:
{{{
C:\haikuVM\bin\haikulink -v -redirectmethodpath C:\haikuVM\myCProject\redirects --Config arduino -o Blink.hex C:\haikuVM\examples\src\main\java\arduino\tutorial\Blink
}}}
This will ''not overwrite'' the definition of ''class'' System given in classes.jar from leJOS, but will ''overwrite only'' the implementation of the ''method'' currentTimeMillis() given in classes.jar, hence the name of the option //redirect''method''path//.
This technique of overwriting method implementations is ''not restricted to native methods'' but will work for regular methods as well.