Uitleg code versie 1

Initialisatie

In dit stuk code worden de in- en uitgangen geconfigureerd, de bibliotheken geïnitialiseerd en een welkomstbericht  afgespeeld door de DFPlayer-mini module.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
    ANSEL = 0x00;           //no analog function
    ANSELH = 0x00;          //no analog function
    TRISA = 0x00;           //PORTA als input
    TRISB |= 0b00001110;    //RB1, RB2, RB3 input
    TRISB &=~0b00100000;    //RB5 output
    TRISD = 0x10;       //PORTD output (RD4 input)
    PORTD = 0x00;       //PORTD laag
    LCD_Start();        //start LCD
    LCD_Clear();        //clear LCD
    IR_INIT();          //initialise IR receive and send
    initLED();          //initialise smartled
    configUART(1);      //configure UART @ 9600bps
    __delay_ms(2000);
    setVOL(20);         //set volume to 20
    playNUM(1);         //welkom message
    waitForStop();      //wait for playing to stop

Setup

Het systeem kan op 2 manieren geconfigureerd worden: manueel en automatisch. Als automatisch wordt gekozen, zullen de instellingen gedownload worden van de webserver. Bij manueel moet de gebruiker deze zelf instellen. Na het instellen van het spel moet de 'fire-mode' worden ingesteld. Hierna volgt een countdown van 10 seconden.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
    setVOL(20);         //set volume to 20
    playNUM(2);         //play setup select
    waitForStop();      //wait for playing to stop
    setupSelect();      //select setup mode
    if(!setup){         //manueel
        selectTeam();   //set team in output IR data
        selectPlayer(); //set player in output IR data
    }
    else{               //automatisch
        startup();      //startup message and connect to wifi
    }
    setFireMode();      //set fire mode for rifle
    countDown();        //10s countdown
    unsigned char inTeam = 0;   //inkomend teamnummer
    unsigned char inPlayer = 0; //id van inkomende speler
    unsigned char inWeapon = 0; //damage van inkomende speler
    unsigned char ammo = myAmmo;//momentele ammo is mijn maximale ammo
    unsigned char life = myLife;//momentele levens is mijn maximale levens

    updateLED(ammo,life);   //zet ammo en life op leds

Main loop

In de main-loop wordt het indrukken van drukknoppen en binnengekomen data geïnterpreteerd. Het ontvangen van IR-data gebeurt interrupt based. Als een volledige 16bits code werd ontvangen zal IRIF hoog worden. Zo weet de main loop dat er data behandeld moet worden.
Wanneer de speler schiet of wanneer deze geraakt wordt, zullen de smartLED's aangepast worden.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
    while(1){               //eeuwige loop
        if(RB1 && life){    //schieten kan als je niet dood bent
            if(!semi && ammo){  //single shot
                IR_Send();      //ir schot
                beep();         //beep sound
                ammo--;         //decrement ammo
            }
            else if(ammo >= 3 && semi){ //als ammo groter is dan 3 en semi is geselecteerd
                for(char c=0; c<3;c++){ //semi shot
                    IR_Send();          //ir schot
                    beep();             //beep sound
                    ammo--;             //decrement ammo
                    __delay_ms(2);      //short delay 
                }
            }
            else if (ammo < 3 && semi){ //als ammo lager is dan 3 en simi is geselecteerd
               for(char c=0; c<ammo;c++){ //semi shot
                    IR_Send();          //ir schot
                    __delay_ms(2);      //short delay
                    beep();             //beep sound
                    ammo--;             //decrement ammo
                }
            }
            __delay_ms(50);             //wachttijd tussen shots
            updateLED(ammo,life);       //update ammo en life
        }
        if(trigger && !ammo){   //proberen schieten zonder kogels
            configUART(1);      //9600bps
            setVOL(20);         //set volume to 20
            playNUM(15);        //play no ammo error
            waitForStop();      //wait for play to stop
            configUART(0);      //115200bps
        }
        if(reload){    //herladen
            ammo = myAmmo;  //momentele ammo is max ammo
            beeps();        //beep soung 1s
            updateLED(ammo,life);   //update ammo en life
            configUART(1);  //9600bps
            setVOL(20);     //set volume to 20
            playNUM(14);    //play reloading
            waitForStop();  //wait for play to stop
            configUART(0);  //115200bps
            if(!life){      //for testing fase
                life = myLife;  //momentele levens is max levens
            }
        }
        else if(mode){      //als mode
            log(myId,myTeam,'K',2); //test log een kill door speler 2
            __delay_ms(50);         //wacht 50ms
        }
        if(IRIF){       //nieuwe ontvangen data
            /*
             * indata 16bits
             * XPPPPTTT DDDDDDDD
             */
           inPlayer = (inData>>11)&0x0F;    //krijg id van inkomende speler
           inTeam = (inData>>8)&0x07;       //krijg team van inkomende speler
           inWeapon = inData&0xFF;          //krijg damage van inkomende speler
           /*
            * met gamemode wordt momenteel geen rekening meer gehouden
            * damage wordt geregistreerd waneer inkomend signaal niet van zelfde team komt
            */
           if(inTeam != myTeam){     //als teams niet hetzelfde zijn
               if(inWeapon >= life){ //als er meer damage is dan levenspunten -> dood
                   life = 0;          //je bent dood
                   if(setup){         //als auto setup was geselecteerd
                    configUART(0);    //baud 115200bps for esp01
                    log(myId,myTeam,'K',inPlayer);  //log kill
                    __delay_ms(50);
                    configUART(1);          //baud 9600bps for dfplayer
                   }
                   configUART(1);   //baud 9600bps for dfplayer
                   beep();          //beep sound
                   setVOL(20);      //set volume to 20
                   playNUM(13);     //play dead
                   waitForStop();   //wait for play to stop
               }
               else{                //damage is kleiner dan levens
                    life -= inWeapon;  //trek damage af van levens
                    beep();         //beep sound
                    setVOL(20);     //set volume to 20
                    playNUM(12);    //play hit
                    waitForStop();  //wait for play to stop  
               }
               updateLED(ammo,life);//update ammo en life
           }
           /* flash HIT LED*/
           hit = 1;
           __delay_ms(50);
           hit = 0;
           __delay_ms(50);

           IRIF = 0;                //clear 'interrupt' flag
        }
    }

Speler wordt geraakt

Volgende code wordt uitgevoerd wanneer een speler geraakt wordt. Eerst kijkt het het programma of de binnengekomen data niet van een ander teamlid komt (gamemode's zijn nog niet geïmplementeerd). Daarna worden de levens van de speler verminderd en indien nodig wordt er een 'kill' gelogd.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
        if(inTeam != myTeam){     //als teams niet hetzelfde zijn
               if(inWeapon >= life){ //als er meer damage is dan levenspunten -> dood
                   life = 0;          //je bent dood
                   if(setup){         //als auto setup was geselecteerd
                    configUART(0);    //baud 115200bps for esp01
                    log(myId,myTeam,'K',inPlayer);  //log kill
                    __delay_ms(50);
                    configUART(1);          //baud 9600bps for dfplayer
                   }
                   configUART(1);   //baud 9600bps for dfplayer
                   beep();          //beep sound
                   setVOL(20);      //set volume to 20
                   playNUM(13);     //play dead
                   waitForStop();   //wait for play to stop
               }
               else{                //damage is kleiner dan levens
                    life -= inWeapon;  //trek damage af van levens
                    beep();         //beep sound
                    setVOL(20);     //set volume to 20
                    playNUM(12);    //play hit
                    waitForStop();  //wait for play to stop  
               }
               updateLED(ammo,life);//update ammo en life
           }
           /* flash HIT LED*/
           hit = 1;
           __delay_ms(50);
           hit = 0;
           __delay_ms(50);

           IRIF = 0;                //clear 'interrupt' flag
        }

Interrupt routine

In de interrupt routine wordt de IR_Handler en de millis timer geplaatst. De IR_Handler zorgt voor het ontvangen van de IR-data. De millis timer wordt momenteel allen gebruikt in de timeOut van de waitFor functie van de ESP8266 bibliotheek.

1
2
3
4
void interrupt isr(void){           //interrupt routine
    IR_Handler();                   //interpreteren van IR pulsen
    millisTimer();                  //incrementen van miller counter
}

UART config

Omdat er twee modules gebruik maken van het RS232 protocol (TTL) en dus de UART van de µC moet er gewisseld kunnen worden tussen de modules. De ESP-module werkt met een baud rate van 115200bps en de audio-module met een baud rate van 9600bps. De Tx lijn wordt gewisseld met een multiplexer. De select lijn is verbonden met RD2. 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void configUART(char speed){
    if(speed == 0){
    /*  UART configs  */
    // Baud rate 38400 w/ xtal 19660800: ((19660800/115200)/4)-1 = 42
    SPBRGH = 42 >> 8;   // Baudrate high register -> 8 MSB of SPBRG 
    SPBRG = 42 & 0xFF;  // Baudrate low register  -> 8 LSB of SPBRG 
    TRISC6 = 0;         // RC6 is TX -> output
    TRISC7 = 1;         // RC7 is RX -> input
    BAUDCTL = 0x08;     // Non inverted TX data, 16bit baud gen
    RCSTA = 0x90;       // Enable serial, enable receiver
    TXSTA = 0x24;       // Send 8bits, enable transmitter, high speed, asynchronous mode
    RD2 = 0;            // Select MUX to 0
    __delay_ms(2);
    }
    else{
    /*  UART configs  */
    // Baud rate 9600 w/ xtal 19660800: ((19660800/9600)/4)-1 = 511
    SPBRGH = 511 >> 8;  // Baudrate high register -> 8 MSB of SPBRG 
    SPBRG = 511 & 0xFF; // Baudrate low register  -> 8 LSB of SPBRG 
    TRISC6 = 0;         // RC6 is TX -> output
    TRISC7 = 1;         // RC7 is RX -> input
    BAUDCTL = 0x08;     // Non inverted TX data, 16bit baud gen
    RCSTA = 0x90;       // Enable serial, enable receiver
    TXSTA = 0x24;       // Send 8bits, enable transmitter, high speed, asynchronous mode
    RD2 = 1;            // Select MUX to 1
    __delay_ms(2);
    }
}

Buzzer

Om met de buzzer geluid te maken zijn er twee functies. De beeps functie genereert een 1000Hz blokgolf voor 0.5 seconden. De beep functie genereert een 714Hz blokgolf voor 70ms.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
void beep(void){        //short beep
    for(char i=0; i<50; i++){   //loop 50 times
        /* square wave of 714Hz*/
        RB5 = 1;
        __delay_us(700);
        RB5 = 0;
        __delay_us(700);
    }
}

void beeps(void){       //beep for 0.5s
    for(char i=0; i<250; i++){  //loop 250 times
        /* square wave of 1000 Hz*/
        RB5 = 1;
        __delay_ms(1);
        RB5 = 0;
        __delay_ms(1);
    }
}

Setup selecteren

Om te kiezen tussen automatische configuratie en manuele configuratie wordt de functie setupSelect gebruikt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
void setupSelect(void){
    while(!reload && !mode);    //wait for button to be pressed
    if(mode){       //pressed on mode
        setup = 0;  //manual mode
        setVOL(20); //set volume to 20
        playNUM(3); //play manual selected
    }
    else{
        setup = 1;  //auto mode
        setVOL(20); //set volume to 20
        playNUM(4); //play auto selected
    }
    beep();         //beep sound
    waitForStop();  //wait for play to stop
    __delay_ms(250);//no doubble press
}

Automatische configuratie

Wanneer er gekozen wordt voor de auto setup modus wordt deze functie aangeroepen. Eerst wordt de ESP-module ingesteld als station, daarna wordt er verbinding gemaakt met het netwerk en wordt er een GET request gestuurd naar een lokale server op 192.168.0.117/esp/getData.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void startup(void){ //auto startup (get data from server)
    beep();         //start with beep
    /*
     * WDT werkt op 31kHz interne klok
     * Met prescaler op 65536 -> 2.11s timeout
     * Als die tijd bereikt wordt, reset deze de microcontroler
     */
    /* WDT telt van 0 tot 65535 */
    WDTPS3 = 1;
    WDTPS2 = 0;
    WDTPS1 = 1;
    WDTPS0 = 1;

    configUART(0);      //UART @ 115200bps
    SWDTEN = 1;         //start WDT
    __delay_ms(1500);   //wait 1.5s, ESP8266-01 startup
    writeString("AT+CWMODE=1\r\n"); //Station mode
    waitFor("OK\r\n",2000);         //wait for OK
    asm("clrwdt");      //clear wdt
    //writeString("AT+CWJAP_CUR=\"telenet-99FEDF4\",\"yM8ak4khxywZ\"\r\n");//connect to AP
    writeString("AT+CWJAP_CUR=\"LaboEA-ICT\",\"SJS2900Schoten153\"\r\n");//connect to AP
    waitFor("OK\r\n",10000);        //wait for response OK
    asm("clrwdt");      //clear wdt
    writeString("AT+CIPSTART=\"TCP\",\"192.168.0.117\",80\r\n");//connect to server
    waitFor("OK\r\n",2000);         //wait for response OK
    asm("clrwdt");      //clear wdt
    writeString("AT+CIPSEND=54\r\n");//setup send to server
    waitFor("> ",2000);              //wait for response
    asm("clrwdt");      //clear wdt
    writeString(request);           //send request
    writeString("\r\n");            //einde van request
    waitFor("+IPD",2000);           //wait for +IPD
    waitFor("\r\n\r\n",2000);       //wait for response
    asm("clrwdt");      //clear wdt
    getSettings();      //receive gamedata function
    SWDTEN = 0;         //disable wdt
    configUART(1);      //baud 9600bps for dfplayer
    setVOL(20);         //set volume to 20
    playNUM(5);         //play settings received
    waitForStop();      //wait for audio to end
    configUART(0);      //baud 115200bps for ESP01
}

Ontvangen van instellingen

In deze functie worden de instellingen in string formaat omgezet naar decimale waardes en opgeslagen in de juiste variabelen. Op de smartLED's wordt de spelerID (ook te vinden in game viewer) weergegeven in de teamkleur.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
void getSettings(void){
    /* data from server format: ID,TEAM,AMMO,HEALTH,GAMEMODE */
    char temp = '\0';   //temp char is null
    temp = getByte();   //get byte(char) | cijfer 1
    myId = temp-'0';    //ascii naar decimaal
    temp = getByte();   //get byte(char) | comma
    temp = getByte();   //get byte(char) | cijfer 1
    myTeam = temp-'0';  //ascii naar decimaal
    temp = getByte();   //get byte(char) | comma
    temp = getByte();   //get byte(char) | cijfer 1
    myAmmo = temp-'0';  //ascii naar decimaal
    temp = getByte();   //get byte(char) | cijfer 2/comma
    if(temp != ','){    //als karakter geen comma is -> nog een digit
        myAmmo = (10*myAmmo)+(temp-'0'); //ascii naar decimaal
        temp = getByte();   //get byte(char) | cijfer 3/comma
        if(temp != ','){    //als karakter geen comma is -> nog een digit
            myAmmo = (10*myAmmo)+(temp-'0'); //ascii naar decimaal
        }
    }
    temp = getByte();   //get byte(char) | cijfer 1
    myLife = temp - '0';//ascii naar decimaal
    temp = getByte();   //get byte(char) | cijfer 2/comma
    if(temp != ','){    //als karakter geen comma is -> nog een digit
        myLife = (10*myLife)+(temp-'0'); //ascii naar decimaal
        temp = getByte();   //get byte(char) | cijfer 3/comma
        if(temp != ','){    //als karakter geen comma is -> nog een digit
            myLife = (10*myLife)+(temp-'0'); //ascii naar decimaal
        }
    }
    temp = getByte();       //get byte(char) | cijfer 1
    gameMode = temp-'0';    //ascii naar decimaal
    outData |= (myId << 11);//zet id in ir code
    outData |= (myTeam << 8);   //zet team in ir code
    outData |= 0x000F;      //15 damage
    /* give leds team color
     * num leds = player
     */
    switch(myTeam){     //check team
        case 1:         //rood
            for(unsigned char i = 0; i<myId; i++){
                setLED(i,20,0,0);  //red
            }
            break;
        case 2:         //blauw
            for(unsigned char i = 0; i<myId; i++){
                setLED(0,0,0,20);  //blue
            }
            break;
        default:        //fout
            setLED(0,20,20,20); //licht wit
            break;
    }
    writeLED();         //stuur data naar leds
}

Manuele configuratie

Wanneer er gekozen werd voor de manuele modus worden onderstaande functies achter elkaar uitgevoerd. Eerst worden de instructies afgespeeld door de audio module. Daarna kan de gebruiker kiezen welke instelling hij neemt. Na het selecteren zal een korte "beep" te horen zijn.

Team selecteren

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void selectTeam(void){
    configUART(1);      //baud 9600bps for dfplayer
    setVOL(20);         //set volume to 20
    playNUM(6);         //play team select
    waitForStop();      //wait for play to stop
    while(!reload && !mode);    //wait for button to be pressed
    if(reload){         //pressed on reload
        myTeam = 1;     //set local team
        outData |= 0b0000000100000000; //set team in ir data
        setVOL(20);     //set volume to 20
        playNUM(8);     //play red selected
        setLED(0,20,0,0);       //first led red
    }
    else{               //pressed on mode
        myTeam = 2;     //set local team
        outData |= 0b0000001000000000; //set team in ir data
        setVOL(20);     //set volume to 20
        playNUM(7);     //play blue selected
        setLED(0,0,0,20);       //first led blue
    }
    beep();             //beep sound
    writeLED();         //give color to leds
    waitForStop();      //wait for audio to stop playing
    __delay_ms(250);    //no doubble press
}

Speler selecteren

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
void selectPlayer(void){
    setVOL(20);     //set volume to 20
    playNUM(9);     //play select player
    waitForStop();  //wait for audio to stop
    while(!reload && !mode);    //wait for button to be pressed
    if(reload){     //pressed on reload
        myId = 1;   //set local id
        outData |= 0b0000100000000000; //set player in ir data
    }
    else{           //pressed on mode
        myId = 2;   //set local id
        outData |= 0b0001000000000000; //set player in ir data
    }
    beep();         //beep sound
    __delay_ms(250);//no doubble press
}

'Fire-mode' en countdown

Na de automatische- of manuele instellingen moet er altijd een fire mode gekozen worden. Bij 'single' wordt er telkens 1 'kogel' afgevuurd, bij 'semi-auto' zijn dat er 3 per keer. Als de 'fire-mode' ingesteld is, wordt er -na het indrukken van de trigger- afgeteld van 10 seconden afgeteld.

fire-mode

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
void setFireMode(void){
    configUART(1);  //baud9600bps for dfplayer
    setVOL(20);     //set volume to 20
    playNUM(16);    //play fire mode select
    waitForStop();  //wait for playing to stop
    while(!reload && !mode);    //wait for button to be pressed
    if(reload){     //pressed on reload
        semi = 0;   //single fire mode
        setVOL(20); //set volume to 20
        playNUM(18);//play selected single
    }
    else{           //pressed on mode
        semi = 1;   //semi fire mode
        setVOL(20); //set volume to 20
        playNUM(17);//play selected semi-auto
    }
    beep();         //beep sound
    waitForStop();  //wait for audio to stop
    __delay_ms(250);//no doubble press
}

countdown

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
void countDown(void){
    setVOL(20);     //set volume to 20
    playNUM(11);    //play trigger to start
    waitForStop();  //wait for audio to stop
    configUART(0);  //baud 115200bps for ESP01
    while(!trigger);//wait for trigger press
    /* wait 10s with beeps */
    for(char i=0; i<10; i++){
        beeps();    //beep 0.5s
        __delay_ms(500);
    }
}

Logging

Om een scoresysteem te kunnen maken wordt er data naar de server gestuurd. Deze verwerkt de ontvangen data en zet deze om naar tabellen en grafieken. Om data te versturen met de ESP-module wordt de functie log gebruikt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
void log(unsigned char id,unsigned char team,char type,unsigned char kby){
    configUART(0);      //baud 115200bps for ESP01
    char buf[85];       //request buffer
    char bufb[4];       //request length buffer
    sprintf(buf,"GET /esp/regDead.php?N=%d&T=%d&Y=%c&K=%d HTTP/1.0\r\nHost: 192.168.0.117\r\n\r\n",id,team,type,kby);
    sprintf(bufb,"%d",strlen(buf));//create string
    writeString("AT+CIPSTART=\"TCP\",\"192.168.0.117\",80\r\n");//connect to server
    //waitFor("OK\r\n",2000);              //wait for response OK
    __delay_ms(20);
    writeString("AT+CIPSEND=");//setup send to server
    writeString(bufb);  //send request string length
    writeString("\r\n");//end command
    //waitFor("> ",2000);              //wait for response
    __delay_ms(20);
    writeString(buf);   //send request string
    writeString("\r\n");//end request string
}

smartLED's

Het aantal resterende kogels en levens wordt weergegeven op de smartLED's. Om de data op de LED's aan te passen wordt de functie updateLED gebruikt. Hier worden de variabelen ammo en life geschaald naar 20 LED's.

updateLED

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
void updateLED(unsigned char am,unsigned char li){
    if(am == 0){    //if no ammo
        /* 10 first LEDs purple */
        for(unsigned char i = 0; i<9; i++){
            setLED(i,10,0,10);
        }
    }
    else{           //ammo available
        /* scale ammo to 10 leds*/
        unsigned char x = map(am,1,myAmmo,0,NUMLEDS/2);
        /* if led is in range -> red */
        for(unsigned char i = 0; i<x; i++){
                setLED(i,20,0,0);
        }
        /* if led is not in range -> off*/
        for(unsigned char i = 9; i>x; i--){
            setLED(i,0,0,0);
        }
    }
    if(li == 0){    //if no lives
        /* 10 last LEDs purple */
        for(unsigned char i = 10; i<NUMLEDS; i++){
            setLED(i,20,0,20);
        }
    }
    else{           //ammo available
        /* scale life to 10 leds */
        unsigned char y = map(li,1,myLife,10,NUMLEDS);
        /* if led is in range -> green */
        for(unsigned char i = 10; i<y; i++){
            setLED(i,0,20,0);
        }
        /* if led is not in range -> off*/
        for(unsigned char i = 19; i>y; i--){
            setLED(i,0,0,0);
        }   
    }
    writeLED();     //write data to LEDs
}

map functie

Het schalen van variabelen gebeurt met de map functie.  Bij het aanroepen van de functie kan een integer geschaald worden tussen een minimale en maximale waarde.

1
2
3
4
5
/* scaling function like arduino*/
unsigned int map(unsigned int in, unsigned int inm, unsigned int inM, unsigned int outm, unsigned int outM)
{
    return (in - inm) * (outM - outm) / (inM - inm) + outm;
}