PadController/input.h
2022-08-21 14:00:32 +02:00

712 lines
21 KiB
C

void loadProgram(String program);
#include "nrf.h"
#include "ble.h"
#include <btnMatrix.h>
#define aBtnBorder 22936
#define aBtnIncBorder 500
btnMatrix btns(25,26,27,14 ,34,35,32,33);
//animation Store
struct animation{
unsigned int totaltime;
String data;
};
animation A_store[NUM_BTNS * 4];
struct buttonlink{
byte clock; //0 system, 1 own, 2 own + reset
unsigned int offset;
byte id;
};
buttonlink B_store [NUM_BTNS][4]; //notused,released,pressed,changing
//running
byte A_programId[NUM_BTNS];
byte A_state[NUM_BTNS]; //0-3 2-Dim in B_store
//round
String A_program[NUM_BTNS];
unsigned long A_clock[NUM_BTNS]; //begin of the time
byte A_clocktype[NUM_BTNS]; //wich time should be used
unsigned int A_offset[NUM_BTNS]; //time offset
unsigned int A_totalroundtime[NUM_BTNS]; //total time
unsigned int A_roundtime[NUM_BTNS]; //time passed
//step
boolean A_slow[NUM_BTNS];
unsigned int A_steptime[NUM_BTNS];
CRGB A_color[NUM_BTNS];
boolean A_next_slow[NUM_BTNS];
unsigned int A_next_steptime[NUM_BTNS];
CRGB A_next_color[NUM_BTNS];
//read in
bool state[64];
int values[64];
//btns
bool lastState[NUM_BTNS]; //first interpreter
bool switchState[NUM_BTNS];
byte buttonaction[NUM_BTNS][7];
//analog
int16_t lastValue[NUM_ANALOG];
double analogCalibrate[NUM_ANALOG][3];
byte analogaction[NUM_ANALOG][5];
/*analog -> btns
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0: lx rx lt rt sy 1 5 9
16: ly ry lr rr sy 2 6 10
32: lt rt ll rl tl 3 7
48: lr rr lb rb tr 4 8
0-1 analog
2-3 HAT
4 2xsys 2xtrigger
5-7 10x btn
buttons: hat left -> hat right -> (l->r) trigger -> left to right bottom btn
*/
boolean readBTN(byte i){
//const byte pos[] = {2,18,34,50, 3,19,35,51, 36,52, 5,21,37,53,6,22,38,54,7,23};
const byte pos[] = {36, 2,18,34,50, 5,21,37,53,6,22,38,54,7,23, 51,19,35,3,/*3,19,35,51,*/ 52};
return state[pos[i]];
}
double readAnalog(byte i, bool raw = false){
const byte pos[] = {0,16,32,48, 1,17,33,49};
byte j = pos[i];
double value = values[j];
return raw?value:(value*value*analogCalibrate[i][0]+value*analogCalibrate[i][1]+analogCalibrate[i][2]);
}
void pressBTN(byte amode, byte value){
if(amode==0)return;
if(mode==mode_radio&&value<32){
NRFpress(value);
}
if(mode==mode_bluetooth){
BLEpress(amode,value);
}
}
void releaseBTN(byte amode, byte value){
if(amode==0)return;
if(mode==mode_radio&&value<32){
NRFrelese(value);
}
if(mode==mode_bluetooth){
BLErelese(amode,value);
}
}
void increseAxis(byte analog_num, int16_t value){
if(mode==mode_radio){
NRFincreseAxis(analog_num,value/**currentTime/1000*/);
}
if(mode==mode_bluetooth){
BLEincreseAxis(analog_num,value/**currentTime/1000*/);
}
}
void setAxis(byte analog_num, int16_t value){
if(mode==mode_radio){
NRFsetAxis(analog_num,value);
}
if(mode==mode_bluetooth){
BLEsetAxis(analog_num,value);
}
}
void datasend(){
if(mode==mode_radio){
NRFsend();
//BLEnotsend();
}
if(mode==mode_bluetooth){
BLEsend();
NRFnotsend();
}
}
void innerModeClick(){
if(mode==mode_radio){
NRFclick();
}
if(mode==mode_bluetooth){
BLEclick();
}
}
void load_next_step(byte i){
unsigned int cutpos = 0;
cutpos = cutcheck(A_program[i].indexOf(","),A_program[i].length());
String now = A_program[i].substring(0,cutpos);
A_program[i] = A_program[i].substring(cutpos+1);
//add roundtime
A_roundtime[i] += A_steptime[i];
//move old
A_slow[i] = A_next_slow[i];
A_steptime[i] = A_next_steptime[i];
A_color[i] = A_next_color[i];
//load new
//slow?
cutpos = cutcheck(now.indexOf(" "),now.length());
String nowin = now.substring(0,cutpos);
now = now.substring(cutpos+1);
A_next_slow[i]=false;
if(nowin.startsWith("1")){
A_next_slow[i]=true;
}
//time
cutpos = cutcheck(now.indexOf(" "),now.length());
nowin = now.substring(0,cutpos);
now = now.substring(cutpos+1);
A_next_steptime[i] = nowin.toInt();
//color
cutpos = cutcheck(now.indexOf(" "),now.length());
nowin = now.substring(0,cutpos);
now = now.substring(cutpos+1);
A_next_color[i] = hextocolor(nowin);
if(A_program[i].length()<2){
A_program[i] = A_store[A_programId[i]].data;
}
}
void loadC(byte state,byte i){
A_state[i] = state;
buttonlink B_now = B_store[i][state];
A_programId[i] = B_now.id > 255?0:B_now.id;
animation A_now = A_store[A_programId[i]];
A_totalroundtime[i] = A_now.totaltime;
A_offset[i] = B_now.offset;
A_clocktype[i] = B_now.clock;
if(B_now.clock>0){
A_clock[i] = millis();
}
A_program[i] = A_now.data;
load_next_step(i);
load_next_step(i);
leds[i] = A_color[i];
A_roundtime[i] = 0;
}
float lastBright = getBrightness();
void animateBTNs(){
for (int i = 0; i < NUM_BTNS; i++) {
unsigned long time = millis()-(A_clocktype[i]==0?0:A_clock[i])+A_offset[i];
unsigned int roundtime = time%A_totalroundtime[i];
if(roundtime<A_roundtime[i]){//overrun
load_next_step(i);
leds[i] = A_color[i];
A_roundtime[i]=0;
}
if(roundtime>=A_roundtime[i]+A_steptime[i]){
load_next_step(i);
leds[i] = A_color[i];
}
if(A_roundtime[i]>=A_totalroundtime[i])A_roundtime[i]=0;
if(A_slow[i]){
float per = 100.0*(roundtime-A_roundtime[i])/((float) A_steptime[i]);
leds[i] = CRGB(
round((float)(A_color[i][0] * (100.0-per)/100.0) + (A_next_color[i][0] * per/100.0)),
round((float)(A_color[i][1] * (100.0-per)/100.0) + (A_next_color[i][1] * per/100.0)),
round((float)(A_color[i][2] * (100.0-per)/100.0) + (A_next_color[i][2] * per/100.0))
);
}
}
lastBright = lastBright * 0.999 + getBrightness() * 0.001;
FastLED.setBrightness(lastBright);
FastLED.show();
}
void handelInput(){
unsigned long nowTime = millis();
currentTime = nowTime-lastTime;
lastTime = nowTime;
btns.readAll(state,values,8);
btns.analogGlide(values,0,0.3);
btns.analogGlide(values,1,0.3);
btns.analogGlide(values,0,0.1);
btns.analogGlide(values,1,0.1);
for(int i = 0; i < NUM_ANALOG; i++){
if(analogaction[i][0]>0){
double analoginR = readAnalog(i);
int16_t analogin;
if(analoginR>32767){
analogin = 32767;
}else if(analoginR<-32767){
analogin = -32767;
}else{
analogin = (int16_t)analoginR;
}
if(analogaction[i][0]==1){
//press up
if(analogin>=aBtnBorder&&lastValue[i]<aBtnBorder)pressBTN(analogaction[i][1],analogaction[i][2]);
//press down
if(analogin<=-aBtnBorder&&lastValue[i]>-aBtnBorder)pressBTN(analogaction[i][3],analogaction[i][4]);
//release up
if(analogin<aBtnBorder&&lastValue[i]>=aBtnBorder)releaseBTN(analogaction[i][1],analogaction[i][2]);
//release down
if(analogin>-aBtnBorder&&lastValue[i]<=-aBtnBorder)releaseBTN(analogaction[i][3],analogaction[i][4]);
}
if(analogaction[i][0]==2){
setAxis(analogaction[i][1],analogin);
}
if(analogaction[i][0]==3){
if(abs(analogin)>aBtnIncBorder)
increseAxis(analogaction[i][1],round((double)analogin * ((double) ((int16_t)((analogaction[i][2]<<8)+analogaction[i][3])) )/32767.0) );
}
lastValue[i] = analogin;
}
}
for (int i = 0; i < NUM_BTNS; i++) {
boolean btnstate = readBTN(i);
if(buttonaction[i][0]==1){
if(btnstate&&!lastState[i]){
loadC(2,i);
pressBTN(buttonaction[i][1],buttonaction[i][2]);
pressBTN(buttonaction[i][3],buttonaction[i][4]);
pressBTN(buttonaction[i][5],buttonaction[i][6]);
}
if(!btnstate&&lastState[i]){
loadC(1,i);
releaseBTN(buttonaction[i][1],buttonaction[i][2]);
releaseBTN(buttonaction[i][3],buttonaction[i][4]);
releaseBTN(buttonaction[i][5],buttonaction[i][6]);
}
}
if(buttonaction[i][0]==2){
if(btnstate&&!lastState[i]){
loadC(3,i);
pressBTN(buttonaction[i][1],buttonaction[i][2]);
pressBTN(buttonaction[i][3],buttonaction[i][4]);
pressBTN(buttonaction[i][5],buttonaction[i][6]);
}
if(!btnstate&&lastState[i]){
switchState[i]=!switchState[i];
if(switchState[i]){
loadC(2,i);
}else{
loadC(1,i);
}
releaseBTN(buttonaction[i][1],buttonaction[i][2]);
releaseBTN(buttonaction[i][3],buttonaction[i][4]);
releaseBTN(buttonaction[i][5],buttonaction[i][6]);
}
}
if(buttonaction[i][0]==3){
if(btnstate&&!lastState[i]){
loadC(3,i);
}
if(!btnstate&&lastState[i]){
switchState[i]=!switchState[i];
if(switchState[i]){
loadC(2,i);
pressBTN(buttonaction[i][1],buttonaction[i][2]);
pressBTN(buttonaction[i][3],buttonaction[i][4]);
pressBTN(buttonaction[i][5],buttonaction[i][6]);
}else{
loadC(1,i);
releaseBTN(buttonaction[i][1],buttonaction[i][2]);
releaseBTN(buttonaction[i][3],buttonaction[i][4]);
releaseBTN(buttonaction[i][5],buttonaction[i][6]);
}
}
}
if(buttonaction[i][0]==4){
if(btnstate&&!lastState[i]){
loadC(2,i);
}
if(!btnstate&&lastState[i]){
loadC(1,i);
}
if(btnstate){
setAxis(buttonaction[i][1],(buttonaction[i][2]<<8)+buttonaction[i][3]);
}
}
if(buttonaction[i][0]==5){
if(btnstate&&!lastState[i]){
loadC(2,i);
}
if(!btnstate&&lastState[i]){
loadC(1,i);
}
if(btnstate){
increseAxis(buttonaction[i][1],(buttonaction[i][2]<<8)+buttonaction[i][3]);
}
}
lastState[i] = btnstate;
}
animateBTNs();
datasend();
}
void LEDsetShutdown(){
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB(100,0,0);
}
FastLED.show();
}
void loadProgram(String program){
unsigned int cutpos = 0;
cutpos = cutcheck(program.indexOf(";"),program.length());
String btns = program.substring(0,cutpos);
String analog = program.substring(cutpos+1);
int i = 0;
for(i = 0; i < NUM_BTNS; i++){
lastState[i] = false;
switchState[i] = false;
buttonaction[i][0] = 0;
buttonaction[i][1] = 0;
buttonaction[i][2] = 0;
buttonaction[i][3] = 0;
buttonaction[i][4] = 0;
buttonaction[i][5] = 0;
buttonaction[i][6] = 0;
}
i=0;
while(btns.length()>1){
if(i>=NUM_BTNS)break;
cutpos = cutcheck(btns.indexOf(","),btns.length());
String now = btns.substring(0,cutpos);
btns = btns.substring(cutpos+1);
/*Serial.print("signle btn: ");
Serial.println(now);*/
int j = 0;
if(now.startsWith("00")){
loadC(0,i);
}else{
loadC(1,i);
}
while(now.length()>j*2+1&&j<7){
String now2 = now.substring(j*2,j*2+2);
/*Serial.print("read [");
Serial.print(i);
Serial.print("] [");
Serial.print(j);
Serial.print("] : ");*/
buttonaction[i][j] = hextonum(now2);
/*Serial.print(buttonaction[i][j]);
Serial.print(" (");
Serial.print(now2);
Serial.println(")");*/
j++;
}
i++;
}
//analog
for(i = 0; i < NUM_ANALOG; i++){
lastValue[i] = 0;
analogaction[i][0] = 0;
analogaction[i][1] = 0;
analogaction[i][2] = 0;
analogaction[i][3] = 0;
analogaction[i][4] = 0;
}
i = 0;
while(analog.length()>1){
if(i>=NUM_ANALOG)break;
cutpos = cutcheck(analog.indexOf(","),analog.length());
String now = analog.substring(0,cutpos);
analog = analog.substring(cutpos+1);
int j = 0;
while(now.length()>j*2+1&&j<5){
String now2 = now.substring(j*2,j*2+2);
analogaction[i][j] = hextonum(now2);
j++;
}
i++;
}
}
void loadLEDProgram(String program){
preferences.putString("LEDProgram",program);
unsigned int cutpos = 0;
cutpos = cutcheck(program.indexOf("|"),program.length());
String prog = program.substring(0,cutpos);
String links = program.substring(cutpos+1);
byte i = 0;
while(prog.length()>2&&i<NUM_BTNS*4){
cutpos = cutcheck(prog.indexOf(";"),prog.length());
String now = prog.substring(0,cutpos);
prog = prog.substring(cutpos+1);
cutpos = cutcheck(now.indexOf(":"),now.length());
A_store[i].totaltime = max((long int)1, ((String) now.substring(0,cutpos)).toInt());
A_store[i].data = now.substring(cutpos+1);
i++;
}
i=0;
while(links.length()>2&&i<NUM_BTNS){
cutpos = cutcheck(links.indexOf(";"),links.length());
String btn = links.substring(0,cutpos);
links = links.substring(cutpos+1);
byte j = 0;
while(btn.length()>2&&j<4){
cutpos = cutcheck(btn.indexOf(","),btn.length());
String now = btn.substring(0,cutpos);
btn = btn.substring(cutpos+1);
cutpos = cutcheck(now.indexOf(" "),now.length());
String nowin = now.substring(0,cutpos);
now = now.substring(cutpos+1);
B_store[i][j].clock = nowin=="0"?(0):(nowin=="2"?(2):(1));
cutpos = cutcheck(now.indexOf(" "),now.length());
nowin = now.substring(0,cutpos);
now = now.substring(cutpos+1);
B_store[i][j].offset = nowin.toInt();
cutpos = cutcheck(now.indexOf(" "),now.length());
nowin = now.substring(0,cutpos);
now = now.substring(cutpos+1);
B_store[i][j].id = (byte) nowin.toInt();
j++;
}
i++;
}
}
void loadCalibrationData(String data){
unsigned int cutpos = 0;
int i = 0;
while(data.length()>1){
if(i>=NUM_ANALOG)break;
cutpos = cutcheck(data.indexOf(";"),data.length());
String now = data.substring(0,cutpos);
data = data.substring(cutpos+1);
for (int j = 0; j < 3; j++) {
if(now.length()>0){
cutpos = cutcheck(now.indexOf(","),now.length());
String now2 = now.substring(0,cutpos);
now = now.substring(cutpos+1);
analogCalibrate[i][j] = now2.toFloat();
}
}
i++;
}
preferences.putBytes("analogCalib",analogCalibrate, sizeof(analogCalibrate));
}
void iniInput(){
if(firstLaunch){
//loadProgram("010500,02020b,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00;00,00,00,00,00,00,00,00");
//loadProgram("010304,010400,010401,010403,010402,01040a,010408,01020e,01020d,02020b,02020a,010209,010208,010409,01040b,0103000,010301,010302,010303,010305;0208,0209,00,00,020b,020a,00,00");
loadCalibrationData(
(String)"0.00016901909683607273,23.823860249481648,-41965.23905167896;"+
"0.0032568361858686832,14.552576203914427,-35492.98520912674;"+
"-0.0000019086881625810545,16.011234881444572,-32767;"+
"-0.0000019086881625810545,16.011234881444572,-32767;"+
"-0.00019162251342654416,20.605461485605023,-35751.76305206794;"+
"-0.0008308262876500306,22.692086412128443,-35479.08647091325;"+
"-0.0000019086881625810545,16.011234881444572,-32767;"+
"-0.0000019086881625810545,16.011234881444572,-32767;"
);
}else{
preferences.getBytes("analogCalib",analogCalibrate, sizeof(analogCalibrate));
}
loadLEDProgram(preferences.getString("LEDProgram","10000:1 5000 880000,1 5000 004444;2000:1 1000 ff0000,1 1000 dd1111;2000:1 1000 00ff00,1 1000 11dd11;2000:1 1000 eeee00,1 1000 bb2222;|0 0 0,0 0 1,0 0 2,0 0 3;0 500 0,0 0 1,0 0 2,0 0 3;0 1000 0,0 0 1,0 0 2,0 0 3;0 1500 0,0 0 1,0 0 2,0 0 3;0 2000 0,0 0 1,0 0 2,0 0 3;0 2500 0,0 0 1,0 0 2,0 0 3;0 3000 0,0 0 1,0 0 2,0 0 3;0 3500 0,0 0 1,0 0 2,0 0 3;0 4000 0,0 0 1,0 0 2,0 0 3;0 4500 0,0 0 1,0 0 2,0 0 3;0 5000 0,0 0 1,0 0 2,0 0 3;0 5500 0,0 0 1,0 0 2,0 0 3;0 6000 0,0 0 1,0 0 2,0 0 3;0 6500 0,0 0 1,0 0 2,0 0 3;0 7000 0,0 0 1,0 0 2,0 0 3;0 7500 0,0 0 1,0 0 2,0 0 3;0 8000 0,0 0 1,0 0 2,0 0 3;0 8500 0,0 0 1,0 0 2,0 0 3;0 9000 0,0 0 1,0 0 2,0 0 3;0 9500 0,0 0 1,0 0 2,0 0 3;"));
BLEProgramCache[0] = preferences.getString("BLEPchache_0","010304,010400,010401,010403,010402,01040a,010408,01020e,01020d,02020b,02020a,010209,010208,010409,01040b,0103000,010301,010302,010303,010305;0208,0209,00,00,020b,020a,00,00");
BLEProgramCache[1] = preferences.getString("BLEPchache_1","");
BLEProgramCache[2] = preferences.getString("BLEPchache_2","");
BLEProgramCache[3] = preferences.getString("BLEPchache_3","");
BLEProgramCache[4] = preferences.getString("BLEPchache_4","");
FastLED.addLeds<WS2812B, LED_DATA_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(100);
}
/*
analogCalibrate Date:
wert_0_0,wert_0_1,wert_0_2;
*/
/*
empty Program
010500,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00;00,00,00,00,00,00,00,00
*/
/*
//all numbers are in hexadecimal
mode submode value
//for btns
[0] //not unsed
[1] //normal btns
--> see btns
--> see btns
--> see btns
[2] //seemingly switch
--> see btns
--> see btns
--> see btns
[3] //switch
--> see btns
--> see btns
--> see btns
[4] //setAnaloge
[0-11] //analoge Values
[-32767 - 32767]
[5] //incrementalchange
[0-11] //analoge Values
[-32767 - 32767]
//for analog
[0] //not unsed
[1] //normal btns //min 70%
--> see btns (up)
--> see btns (down)
[2] //setAnaloge
[0-11] //analoge Values
[3] //incrementalchange
[0-11] //analoge Values
[-32767 - 32767] //multiplayer of in (-1 to 1)
--> btns
[0] empty
//ble
[1] //scancode
[0-255]
[2] //MediaKey
[0-15]
[3] //Gamepadbtns
[0-13]
[4] //HAT
[0-3]
[5] //Mouse
[0-4]
//nrf
[ff] //bool chanels
[0-31]
--> analoge
//ble -> lx, ly, rx, ry, lt, rt, lr, rr, mx, my, sm, sh
//nrf -> 0-11 raw send
//saved as float rounded for send to int16_t
*/
/*
nrfpackage
[4] reserved
[4] 32x btns
[24] 12x 2byte analoge outputs
== 32
*/
/*
new animation idea
from
0x00: 1000:1 500 880000,1 500 004444; //totaltime:slow steptime color, slow steptime color, ...;
0x01: 1000:1 500 880000,1 500 004444;
....
0x50: 1000:1 500 880000,1 500 004444;
to max 0x50 (80) |
0x00 0 0 0,1 0 1,0 0 2,0 0 3; //clock offset id,clock offset id,clock offset id,clock offset id;
0x01 0 0 0,1 0 1,0 0 2,0 0 3;
0x14 0 0 0,1 0 1,0 0 2,0 0 3;
detail specs, look old structur v
*/
/*
animation: {
totaltime, [in ms]
clock, [0: systemclock, 1 (and else): Button clock, 2 Button clock with reset]
offset: posnumber,
data:[
slow, [1: slow, 0: hard]
time,
color
]
}
*/
/*
"10000:1 5000 880000,1 5000 004444;"+
"2000:1 1000 ff0000,1 1000 dd1111;"+
"2000:1 1000 00ff00,1 1000 11dd11;"+
"2000:1 1000 eeee00,1 1000 bb2222;"+
"|"+
"0 0 0,0 0 1,0 0 2,0 0 3;"+
"0 500 0,0 0 1,0 0 2,0 0 3;"+
"0 1000 0,0 0 1,0 0 2,0 0 3;"+
"0 1500 0,0 0 1,0 0 2,0 0 3;"+
"0 2000 0,0 0 1,0 0 2,0 0 3;"+
"0 2500 0,0 0 1,0 0 2,0 0 3;"+
"0 3000 0,0 0 1,0 0 2,0 0 3;"+
"0 3500 0,0 0 1,0 0 2,0 0 3;"+
"0 4000 0,0 0 1,0 0 2,0 0 3;"+
"0 4500 0,0 0 1,0 0 2,0 0 3;"+
"0 5000 0,0 0 1,0 0 2,0 0 3;"+
"0 5500 0,0 0 1,0 0 2,0 0 3;"+
"0 6000 0,0 0 1,0 0 2,0 0 3;"+
"0 6500 0,0 0 1,0 0 2,0 0 3;"+
"0 7000 0,0 0 1,0 0 2,0 0 3;"+
"0 7500 0,0 0 1,0 0 2,0 0 3;"+
"0 8000 0,0 0 1,0 0 2,0 0 3;"+
"0 8500 0,0 0 1,0 0 2,0 0 3;"+
"0 9000 0,0 0 1,0 0 2,0 0 3;"+
"0 9500 0,0 0 1,0 0 2,0 0 3;"
*/
/*
example:
1000:0:0:1 500 880000,1 500 004444;
10000:0:0:0 10000 ff0000;
10000:0:0:0 10000 00ff00;
10000:0:0:0 10000 eeee00|
"10000:0:0:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"+
"10000:0:500:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"+
"10000:0:1000:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"+
"10000:0:1500:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"+
"10000:0:2000:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"+
"10000:0:2500:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"+
"10000:0:3000:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"+
"10000:0:3500:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"+
"10000:0:4000:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"+
"10000:0:4500:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"+
"10000:0:5000:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"+
"10000:0:5500:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"+
"10000:0:6000:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"+
"10000:0:6500:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"+
"10000:0:7000:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"+
"10000:0:7500:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"+
"10000:0:8000:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"+
"10000:0:8500:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"+
"10000:0:9000:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"+
"10000:0:9500:1 5000 880000,1 5000 004444;10000:0:0:0 10000 ff0000;10000:0:0:0 10000 00ff00;10000:0:0:0 10000 eeee00|"
*/