chore: crlf --> lf
This commit is contained in:
parent
20a6b6cb0b
commit
1a1193a10d
960
main.cpp
960
main.cpp
@ -1,480 +1,480 @@
|
||||
// Ukazka odezvy programu
|
||||
//
|
||||
// Ocekavane chovani:
|
||||
// Pri stisku tlacitka se spusti efekt, kdy blikaji postupne LED,
|
||||
// Po uvolneni tlacitka LED zhasnou. Tedy blikani trva po dobu stisku tlacitka.
|
||||
//
|
||||
// Ukazano je postupne vylepsovani odezvy programu - aby program rychleji reagoval na
|
||||
// uvolneni tlacitka. Verzi programu zvolte nize v #define VERSION
|
||||
//
|
||||
// Posledni zmena: 30.10.2020
|
||||
///////////////////////////////////////////////
|
||||
#include <iostream>
|
||||
#include "simul_kl25z.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
//#include "MKL25Z4.h"
|
||||
//#include "drv_gpio.h"
|
||||
//#include "drv_systick.h"
|
||||
#include <stdbool.h> // kvuli typu bool
|
||||
|
||||
// Vyber verze kodu.
|
||||
// 1. stav blikani a nesviti; kontrola tlacitka vzdy az po bliknuti vsech LED.
|
||||
// 2. kontrola tlacitka po bliknuti kazde LED.
|
||||
// 3. nepouziva se delay - polling casu.
|
||||
// 4. rozdeleni kodu na ulohy - tasky.
|
||||
#define VERSION 1
|
||||
|
||||
// Spolecne definice
|
||||
#define SWITCH_PRESSED (1)
|
||||
#define SWITCH_NOT_PRESSED (0)
|
||||
|
||||
#define KEY SW1
|
||||
#define LED1 LD1
|
||||
#define LED2 LD2
|
||||
#define LED3 LD3
|
||||
#define BLINK_DELAY 1000
|
||||
|
||||
// Prototypy funkci
|
||||
void init(void);
|
||||
int switch1_read(void);
|
||||
void delay_debounce(void);
|
||||
void LED_control(bool d1, bool d2, bool d3);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// Kod programu v nekolika verzich.
|
||||
// Aktivni verze se vybere pomoci #define VERSION nahore.
|
||||
#if VERSION == 1
|
||||
// Verze 1
|
||||
// Odezva je spatna, protoze stav tlacitka se testuje az po bliknuti vsech LED.
|
||||
// Pri uvolneni tlacitka program zareaguje az na konci celeho efektu, kdyz zhasne
|
||||
// treti LED a prvni uz se nerozsviti.
|
||||
|
||||
// Stavy programu
|
||||
#define ST_EFFECT 1
|
||||
#define ST_OFF 2
|
||||
|
||||
int state = ST_OFF;
|
||||
|
||||
|
||||
int main(void) {
|
||||
// inicializace ovladace pinu a delay
|
||||
init();
|
||||
|
||||
while (1) {
|
||||
if (switch1_read() == SWITCH_PRESSED)
|
||||
state = ST_EFFECT;
|
||||
else
|
||||
state = ST_OFF;
|
||||
|
||||
switch (state) {
|
||||
case ST_OFF:
|
||||
LED_control(false, false, false);
|
||||
break;
|
||||
|
||||
case ST_EFFECT:
|
||||
LED_control(true, false, false);
|
||||
SYSTICK_delay_ms(BLINK_DELAY);
|
||||
LED_control(false, true, false);
|
||||
SYSTICK_delay_ms(BLINK_DELAY);
|
||||
LED_control(false, false, true);
|
||||
SYSTICK_delay_ms(BLINK_DELAY);
|
||||
break;
|
||||
} // switch
|
||||
|
||||
} // while
|
||||
|
||||
/* Never leave main */
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#elif VERSION == 2
|
||||
// Verze 2
|
||||
// Odezva je vylepsena tim, ze kontrola tlacitka probiha po bliknuti kazde LED.
|
||||
// Po uvolneni tlacitka pak LED sice "dosviti" svou dobu svitu,
|
||||
// ale dalsi LED uz se nerozsviti.
|
||||
|
||||
// Stavy programu
|
||||
#define ST_LED1_ON 1
|
||||
#define ST_LED2_ON 2
|
||||
#define ST_LED3_ON 3
|
||||
#define ST_OFF 4
|
||||
|
||||
int state = ST_OFF;
|
||||
|
||||
int main(void) {
|
||||
// inicializace ovladace pinu a delay
|
||||
init();
|
||||
|
||||
while (1) {
|
||||
if (switch1_read() == SWITCH_PRESSED) {
|
||||
// Jen pokud je stisknuto tlacitko a soucasny stav je vypnuto,
|
||||
// prejdeme na stav rozsviceni prvni LED, jinak uz nektera LED
|
||||
// sviti a stavy se meni ve switch.
|
||||
if ( state == ST_OFF )
|
||||
state = ST_LED1_ON;
|
||||
}
|
||||
else
|
||||
state = ST_OFF;
|
||||
|
||||
switch (state) {
|
||||
|
||||
case ST_OFF:
|
||||
LED_control(false, false, false);
|
||||
break;
|
||||
|
||||
case ST_LED1_ON:
|
||||
// Bliknout LED1 a prejit na stav dalsi LED2
|
||||
LED_control(true, false, false);
|
||||
SYSTICK_delay_ms(BLINK_DELAY);
|
||||
state = ST_LED2_ON;
|
||||
break;
|
||||
|
||||
case ST_LED2_ON:
|
||||
LED_control(false, true, false);
|
||||
SYSTICK_delay_ms(BLINK_DELAY);
|
||||
state = ST_LED3_ON;
|
||||
break;
|
||||
|
||||
case ST_LED3_ON:
|
||||
LED_control(false, false, true);
|
||||
SYSTICK_delay_ms(BLINK_DELAY);
|
||||
state = ST_LED1_ON;
|
||||
break;
|
||||
} // switch
|
||||
|
||||
} // while
|
||||
|
||||
/* Never leave main */
|
||||
return 0;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#elif VERSION == 3
|
||||
// Verze 3
|
||||
// Odezva je vylepsena tim, ze se nepouziva cekani (busy waiting) ale zjistuje se
|
||||
// zda uz ubehl potrebny cas - jde o tzv. polling - dotazovani.
|
||||
// Diky tomu LED zhasne okamzite po uvolneni tlacitka.
|
||||
|
||||
// Stavy programu
|
||||
#define ST_LED1_ON 1
|
||||
#define ST_LED2_ON 2
|
||||
#define ST_LED3_ON 3
|
||||
#define ST_OFF 4
|
||||
#define ST_LED1_WAIT 5
|
||||
#define ST_LED2_WAIT 6
|
||||
#define ST_LED3_WAIT 7
|
||||
|
||||
int state = ST_OFF;
|
||||
|
||||
int main(void) {
|
||||
// inicializace ovladace pinu a delay
|
||||
init();
|
||||
|
||||
uint32_t waitStart; // cas, kdy se rozvitila LED
|
||||
uint32_t currentTime; // aktualni cas, pomocna promenna
|
||||
|
||||
while (1) {
|
||||
|
||||
if (switch1_read() == SWITCH_PRESSED) {
|
||||
// Jen pokud je stisknuto tlacitko a soucasny stav je vypnuto,
|
||||
// prejdeme na stav rozsviceni prvni LED, jinak uz nektera LED
|
||||
// sviti a stavy se meni ve switch.
|
||||
if ( state == ST_OFF )
|
||||
state = ST_LED1_ON;
|
||||
}
|
||||
else
|
||||
state = ST_OFF;
|
||||
|
||||
switch (state) {
|
||||
|
||||
case ST_OFF:
|
||||
LED_control(false, false, false);
|
||||
break;
|
||||
|
||||
case ST_LED1_ON:
|
||||
// Rozsvitit LED, ulozit aktualni cas a prejit do stavu cekani na
|
||||
// uplynuti casu svitu teto LED.
|
||||
LED_control(true, false, false);
|
||||
waitStart = SYSTICK_millis();
|
||||
state = ST_LED1_WAIT;
|
||||
break;
|
||||
|
||||
case ST_LED1_WAIT:
|
||||
// Kontrola jestli uz ubehlo dost casu abychom rozsvitili dalsi LED
|
||||
// a pokud ano, prechod na dalsi stav
|
||||
currentTime = SYSTICK_millis();
|
||||
if ( currentTime - waitStart >= BLINK_DELAY )
|
||||
state = ST_LED2_ON;
|
||||
break;
|
||||
|
||||
|
||||
case ST_LED2_ON:
|
||||
LED_control(false, true, false);
|
||||
waitStart = SYSTICK_millis();
|
||||
state = ST_LED2_WAIT;
|
||||
break;
|
||||
|
||||
case ST_LED2_WAIT:
|
||||
currentTime = SYSTICK_millis();
|
||||
if ( currentTime - waitStart >= BLINK_DELAY )
|
||||
state = ST_LED3_ON;
|
||||
break;
|
||||
|
||||
case ST_LED3_ON:
|
||||
LED_control(false, false, true);
|
||||
waitStart = SYSTICK_millis();
|
||||
state = ST_LED3_WAIT;
|
||||
break;
|
||||
|
||||
case ST_LED3_WAIT:
|
||||
currentTime = SYSTICK_millis();
|
||||
if ( currentTime - waitStart >= BLINK_DELAY )
|
||||
state = ST_LED1_ON;
|
||||
break;
|
||||
|
||||
} // switch
|
||||
|
||||
} // while
|
||||
|
||||
/* Never leave main */
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#elif VERSION == 4
|
||||
// Verze 4
|
||||
// Program je vylepsen rozdelenim na jednotlive ulohy - tasky.
|
||||
// Z pohledu odezvy je chovani stejne jako u verze 3, ale struktura programu je
|
||||
// prehlednejsi a snadneji by se rozsiroval o dalsi cinnosti.
|
||||
|
||||
// Stavy programu
|
||||
#define ST_LED1_ON 1
|
||||
#define ST_LED2_ON 2
|
||||
#define ST_LED3_ON 3
|
||||
#define ST_OFF 4
|
||||
#define ST_LED1_WAIT 5
|
||||
#define ST_LED2_WAIT 6
|
||||
#define ST_LED3_WAIT 7
|
||||
|
||||
// globalni promenna pro stav tlacitka SW1
|
||||
bool SW1_pressed;
|
||||
// Promenna state je nove lokalni uvnitr tasku (funkce) pro blikani
|
||||
|
||||
// Prototypy funkci
|
||||
void TaskSwitches(void);
|
||||
void TaskEffect(void);
|
||||
void TaskGreenLed(void);
|
||||
|
||||
int main(void) {
|
||||
// inicializace ovladace pinu a delay
|
||||
init();
|
||||
|
||||
while (1) {
|
||||
|
||||
TaskSwitches();
|
||||
TaskEffect();
|
||||
TaskGreenLed();
|
||||
|
||||
} // while
|
||||
|
||||
/* Never leave main */
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Uloha, ktera se stara o obsluhu tlacitek
|
||||
void TaskSwitches(void)
|
||||
{
|
||||
if (switch1_read() == SWITCH_PRESSED)
|
||||
SW1_pressed = true;
|
||||
else
|
||||
SW1_pressed = false;
|
||||
}
|
||||
|
||||
// Uloha, ktera se stara o blikani LED
|
||||
void TaskEffect(void) {
|
||||
// Stav totoho tasku.
|
||||
// Promenna je static, aby si uchovala hodnotu mezi volanimi teto funkce,
|
||||
// tj. aby nezanikla na konci funkce
|
||||
static int state = ST_LED1_ON;
|
||||
|
||||
static uint32_t waitStart; // cas, kdy se rozvitila LED, musi byt static!
|
||||
uint32_t currentTime; // aktualni cas, pomocna promenna
|
||||
|
||||
// Uloha efekt LED se provadi jen pri stisknutem tlacitku
|
||||
if (SW1_pressed) {
|
||||
switch (state) {
|
||||
|
||||
case ST_LED1_ON:
|
||||
// Rozsvitit LED, ulozit aktualni cas a prejit do stavu cekani na
|
||||
// uplynuti casu svitu teto LED.
|
||||
LED_control(true, false, false);
|
||||
waitStart = SYSTICK_millis();
|
||||
state = ST_LED1_WAIT;
|
||||
break;
|
||||
|
||||
case ST_LED1_WAIT:
|
||||
// Kontrola jestli uz ubehlo dost casu abychom rozsvitili dalsi LED
|
||||
// a pokud ano, prechod na dalsi stav
|
||||
currentTime = SYSTICK_millis();
|
||||
if (currentTime - waitStart >= BLINK_DELAY)
|
||||
state = ST_LED2_ON;
|
||||
break;
|
||||
|
||||
case ST_LED2_ON:
|
||||
LED_control(false, true, false);
|
||||
waitStart = SYSTICK_millis();
|
||||
state = ST_LED2_WAIT;
|
||||
break;
|
||||
|
||||
case ST_LED2_WAIT:
|
||||
currentTime = SYSTICK_millis();
|
||||
if (currentTime - waitStart >= BLINK_DELAY)
|
||||
state = ST_LED3_ON;
|
||||
break;
|
||||
|
||||
case ST_LED3_ON:
|
||||
LED_control(false, false, true);
|
||||
waitStart = SYSTICK_millis();
|
||||
state = ST_LED3_WAIT;
|
||||
break;
|
||||
|
||||
case ST_LED3_WAIT:
|
||||
currentTime = SYSTICK_millis();
|
||||
if (currentTime - waitStart >= BLINK_DELAY)
|
||||
state = ST_LED1_ON;
|
||||
break;
|
||||
|
||||
} // switch
|
||||
} else {
|
||||
// zhasnout LED pokud neni stisknuto tlacitko
|
||||
LED_control(false, false, false);
|
||||
state = ST_LED1_ON; // reset stavu tasku
|
||||
}
|
||||
|
||||
} // TaskEffect
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Doba svitu/zhasnuti zelene LED
|
||||
#define GREEN_ON_DELAY 200
|
||||
#define GREEN_OFF_DELAY 700
|
||||
|
||||
// Ukazka dalsiho tasku - blika pri stisknutem tlacitku RGB LED
|
||||
void TaskGreenLed() {
|
||||
static enum {
|
||||
ST_LED_ON,
|
||||
ST_ON_WAIT,
|
||||
ST_LED_OFF,
|
||||
ST_OFF_WAIT
|
||||
|
||||
} stav = ST_LED_ON;
|
||||
|
||||
static uint32_t startTime;
|
||||
|
||||
// uloha se provadi jen pri stisknutem tlacitku
|
||||
if (SW1_pressed) {
|
||||
|
||||
switch (stav) {
|
||||
|
||||
case ST_LED_ON:
|
||||
pinWrite(LED_GREEN, LOW);
|
||||
startTime = SYSTICK_millis();
|
||||
stav = ST_ON_WAIT;
|
||||
break;
|
||||
|
||||
case ST_ON_WAIT:
|
||||
if (SYSTICK_millis() - startTime >= GREEN_ON_DELAY)
|
||||
stav = ST_LED_OFF;
|
||||
break;
|
||||
|
||||
case ST_LED_OFF:
|
||||
pinWrite(LED_GREEN, HIGH);
|
||||
startTime = SYSTICK_millis();
|
||||
stav = ST_OFF_WAIT;
|
||||
break;
|
||||
|
||||
case ST_OFF_WAIT:
|
||||
if (SYSTICK_millis() - startTime >= GREEN_OFF_DELAY)
|
||||
stav = ST_LED_ON;
|
||||
break;
|
||||
} // switch
|
||||
} else {
|
||||
pinWrite(LED_GREEN, HIGH); // zhasni LED
|
||||
stav = ST_LED_ON; // resetuj stav LED
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#endif /* VERSION == 4*/
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Pomocne funkce spolecne pro vsechny verze
|
||||
|
||||
// inicializace
|
||||
void init()
|
||||
{
|
||||
SYSTICK_initialize();
|
||||
|
||||
GPIO_Initialize();
|
||||
|
||||
pinMode(SW1, INPUT_PULLUP);
|
||||
pinMode(LED1, OUTPUT);
|
||||
pinMode(LED2, OUTPUT);
|
||||
pinMode(LED3, OUTPUT);
|
||||
pinMode(LED_GREEN, OUTPUT);
|
||||
pinWrite(LED1, HIGH);
|
||||
pinWrite(LED2, HIGH);
|
||||
pinWrite(LED3, HIGH);
|
||||
pinWrite(LED_GREEN, HIGH);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Ovladani LED - parametr true znamena rozsvitit prislusnou LED, false zhasnout.
|
||||
void LED_control(bool d1, bool d2, bool d3)
|
||||
{
|
||||
pinWrite(LED1, !d1);
|
||||
pinWrite(LED2, !d2);
|
||||
pinWrite(LED3, !d3);
|
||||
}
|
||||
|
||||
/*
|
||||
switch1_read
|
||||
Cte stav tlacitka SW1 s osetrenim zakmitu.
|
||||
Vraci SWITCH_NOT_PRESSED pokud tlacitko neni stisknuto,
|
||||
SWITCH_PRESSED pokud je stisknuto.
|
||||
|
||||
Reads and debounces switch SW1 as follows:
|
||||
1. If switch is not pressed, return SWITCH_NOT_PRESSED.
|
||||
2. If switch is pressed, wait for about 20 ms (debounce),
|
||||
then:
|
||||
if switch is no longer pressed, return SWITCH_NOT_PRESSED.
|
||||
if switch is still pressed, return SWITCH_PRESSED.
|
||||
*/
|
||||
int switch1_read(void)
|
||||
{
|
||||
int switch_state = SWITCH_NOT_PRESSED;
|
||||
if ( pinRead(SW1) == LOW )
|
||||
{
|
||||
// tlacitko je stisknuto
|
||||
|
||||
// debounce = wait
|
||||
SYSTICK_delay_ms(50);
|
||||
|
||||
// znovu zkontrolovat stav tlacitka
|
||||
if ( pinRead(SW1) == LOW )
|
||||
{
|
||||
switch_state = SWITCH_PRESSED;
|
||||
}
|
||||
}
|
||||
// vratime stav tlacitka
|
||||
return switch_state;
|
||||
}
|
||||
|
||||
|
||||
// Ukazka odezvy programu
|
||||
//
|
||||
// Ocekavane chovani:
|
||||
// Pri stisku tlacitka se spusti efekt, kdy blikaji postupne LED,
|
||||
// Po uvolneni tlacitka LED zhasnou. Tedy blikani trva po dobu stisku tlacitka.
|
||||
//
|
||||
// Ukazano je postupne vylepsovani odezvy programu - aby program rychleji reagoval na
|
||||
// uvolneni tlacitka. Verzi programu zvolte nize v #define VERSION
|
||||
//
|
||||
// Posledni zmena: 30.10.2020
|
||||
///////////////////////////////////////////////
|
||||
#include <iostream>
|
||||
#include "simul_kl25z.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
//#include "MKL25Z4.h"
|
||||
//#include "drv_gpio.h"
|
||||
//#include "drv_systick.h"
|
||||
#include <stdbool.h> // kvuli typu bool
|
||||
|
||||
// Vyber verze kodu.
|
||||
// 1. stav blikani a nesviti; kontrola tlacitka vzdy az po bliknuti vsech LED.
|
||||
// 2. kontrola tlacitka po bliknuti kazde LED.
|
||||
// 3. nepouziva se delay - polling casu.
|
||||
// 4. rozdeleni kodu na ulohy - tasky.
|
||||
#define VERSION 1
|
||||
|
||||
// Spolecne definice
|
||||
#define SWITCH_PRESSED (1)
|
||||
#define SWITCH_NOT_PRESSED (0)
|
||||
|
||||
#define KEY SW1
|
||||
#define LED1 LD1
|
||||
#define LED2 LD2
|
||||
#define LED3 LD3
|
||||
#define BLINK_DELAY 1000
|
||||
|
||||
// Prototypy funkci
|
||||
void init(void);
|
||||
int switch1_read(void);
|
||||
void delay_debounce(void);
|
||||
void LED_control(bool d1, bool d2, bool d3);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// Kod programu v nekolika verzich.
|
||||
// Aktivni verze se vybere pomoci #define VERSION nahore.
|
||||
#if VERSION == 1
|
||||
// Verze 1
|
||||
// Odezva je spatna, protoze stav tlacitka se testuje az po bliknuti vsech LED.
|
||||
// Pri uvolneni tlacitka program zareaguje az na konci celeho efektu, kdyz zhasne
|
||||
// treti LED a prvni uz se nerozsviti.
|
||||
|
||||
// Stavy programu
|
||||
#define ST_EFFECT 1
|
||||
#define ST_OFF 2
|
||||
|
||||
int state = ST_OFF;
|
||||
|
||||
|
||||
int main(void) {
|
||||
// inicializace ovladace pinu a delay
|
||||
init();
|
||||
|
||||
while (1) {
|
||||
if (switch1_read() == SWITCH_PRESSED)
|
||||
state = ST_EFFECT;
|
||||
else
|
||||
state = ST_OFF;
|
||||
|
||||
switch (state) {
|
||||
case ST_OFF:
|
||||
LED_control(false, false, false);
|
||||
break;
|
||||
|
||||
case ST_EFFECT:
|
||||
LED_control(true, false, false);
|
||||
SYSTICK_delay_ms(BLINK_DELAY);
|
||||
LED_control(false, true, false);
|
||||
SYSTICK_delay_ms(BLINK_DELAY);
|
||||
LED_control(false, false, true);
|
||||
SYSTICK_delay_ms(BLINK_DELAY);
|
||||
break;
|
||||
} // switch
|
||||
|
||||
} // while
|
||||
|
||||
/* Never leave main */
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#elif VERSION == 2
|
||||
// Verze 2
|
||||
// Odezva je vylepsena tim, ze kontrola tlacitka probiha po bliknuti kazde LED.
|
||||
// Po uvolneni tlacitka pak LED sice "dosviti" svou dobu svitu,
|
||||
// ale dalsi LED uz se nerozsviti.
|
||||
|
||||
// Stavy programu
|
||||
#define ST_LED1_ON 1
|
||||
#define ST_LED2_ON 2
|
||||
#define ST_LED3_ON 3
|
||||
#define ST_OFF 4
|
||||
|
||||
int state = ST_OFF;
|
||||
|
||||
int main(void) {
|
||||
// inicializace ovladace pinu a delay
|
||||
init();
|
||||
|
||||
while (1) {
|
||||
if (switch1_read() == SWITCH_PRESSED) {
|
||||
// Jen pokud je stisknuto tlacitko a soucasny stav je vypnuto,
|
||||
// prejdeme na stav rozsviceni prvni LED, jinak uz nektera LED
|
||||
// sviti a stavy se meni ve switch.
|
||||
if ( state == ST_OFF )
|
||||
state = ST_LED1_ON;
|
||||
}
|
||||
else
|
||||
state = ST_OFF;
|
||||
|
||||
switch (state) {
|
||||
|
||||
case ST_OFF:
|
||||
LED_control(false, false, false);
|
||||
break;
|
||||
|
||||
case ST_LED1_ON:
|
||||
// Bliknout LED1 a prejit na stav dalsi LED2
|
||||
LED_control(true, false, false);
|
||||
SYSTICK_delay_ms(BLINK_DELAY);
|
||||
state = ST_LED2_ON;
|
||||
break;
|
||||
|
||||
case ST_LED2_ON:
|
||||
LED_control(false, true, false);
|
||||
SYSTICK_delay_ms(BLINK_DELAY);
|
||||
state = ST_LED3_ON;
|
||||
break;
|
||||
|
||||
case ST_LED3_ON:
|
||||
LED_control(false, false, true);
|
||||
SYSTICK_delay_ms(BLINK_DELAY);
|
||||
state = ST_LED1_ON;
|
||||
break;
|
||||
} // switch
|
||||
|
||||
} // while
|
||||
|
||||
/* Never leave main */
|
||||
return 0;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#elif VERSION == 3
|
||||
// Verze 3
|
||||
// Odezva je vylepsena tim, ze se nepouziva cekani (busy waiting) ale zjistuje se
|
||||
// zda uz ubehl potrebny cas - jde o tzv. polling - dotazovani.
|
||||
// Diky tomu LED zhasne okamzite po uvolneni tlacitka.
|
||||
|
||||
// Stavy programu
|
||||
#define ST_LED1_ON 1
|
||||
#define ST_LED2_ON 2
|
||||
#define ST_LED3_ON 3
|
||||
#define ST_OFF 4
|
||||
#define ST_LED1_WAIT 5
|
||||
#define ST_LED2_WAIT 6
|
||||
#define ST_LED3_WAIT 7
|
||||
|
||||
int state = ST_OFF;
|
||||
|
||||
int main(void) {
|
||||
// inicializace ovladace pinu a delay
|
||||
init();
|
||||
|
||||
uint32_t waitStart; // cas, kdy se rozvitila LED
|
||||
uint32_t currentTime; // aktualni cas, pomocna promenna
|
||||
|
||||
while (1) {
|
||||
|
||||
if (switch1_read() == SWITCH_PRESSED) {
|
||||
// Jen pokud je stisknuto tlacitko a soucasny stav je vypnuto,
|
||||
// prejdeme na stav rozsviceni prvni LED, jinak uz nektera LED
|
||||
// sviti a stavy se meni ve switch.
|
||||
if ( state == ST_OFF )
|
||||
state = ST_LED1_ON;
|
||||
}
|
||||
else
|
||||
state = ST_OFF;
|
||||
|
||||
switch (state) {
|
||||
|
||||
case ST_OFF:
|
||||
LED_control(false, false, false);
|
||||
break;
|
||||
|
||||
case ST_LED1_ON:
|
||||
// Rozsvitit LED, ulozit aktualni cas a prejit do stavu cekani na
|
||||
// uplynuti casu svitu teto LED.
|
||||
LED_control(true, false, false);
|
||||
waitStart = SYSTICK_millis();
|
||||
state = ST_LED1_WAIT;
|
||||
break;
|
||||
|
||||
case ST_LED1_WAIT:
|
||||
// Kontrola jestli uz ubehlo dost casu abychom rozsvitili dalsi LED
|
||||
// a pokud ano, prechod na dalsi stav
|
||||
currentTime = SYSTICK_millis();
|
||||
if ( currentTime - waitStart >= BLINK_DELAY )
|
||||
state = ST_LED2_ON;
|
||||
break;
|
||||
|
||||
|
||||
case ST_LED2_ON:
|
||||
LED_control(false, true, false);
|
||||
waitStart = SYSTICK_millis();
|
||||
state = ST_LED2_WAIT;
|
||||
break;
|
||||
|
||||
case ST_LED2_WAIT:
|
||||
currentTime = SYSTICK_millis();
|
||||
if ( currentTime - waitStart >= BLINK_DELAY )
|
||||
state = ST_LED3_ON;
|
||||
break;
|
||||
|
||||
case ST_LED3_ON:
|
||||
LED_control(false, false, true);
|
||||
waitStart = SYSTICK_millis();
|
||||
state = ST_LED3_WAIT;
|
||||
break;
|
||||
|
||||
case ST_LED3_WAIT:
|
||||
currentTime = SYSTICK_millis();
|
||||
if ( currentTime - waitStart >= BLINK_DELAY )
|
||||
state = ST_LED1_ON;
|
||||
break;
|
||||
|
||||
} // switch
|
||||
|
||||
} // while
|
||||
|
||||
/* Never leave main */
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#elif VERSION == 4
|
||||
// Verze 4
|
||||
// Program je vylepsen rozdelenim na jednotlive ulohy - tasky.
|
||||
// Z pohledu odezvy je chovani stejne jako u verze 3, ale struktura programu je
|
||||
// prehlednejsi a snadneji by se rozsiroval o dalsi cinnosti.
|
||||
|
||||
// Stavy programu
|
||||
#define ST_LED1_ON 1
|
||||
#define ST_LED2_ON 2
|
||||
#define ST_LED3_ON 3
|
||||
#define ST_OFF 4
|
||||
#define ST_LED1_WAIT 5
|
||||
#define ST_LED2_WAIT 6
|
||||
#define ST_LED3_WAIT 7
|
||||
|
||||
// globalni promenna pro stav tlacitka SW1
|
||||
bool SW1_pressed;
|
||||
// Promenna state je nove lokalni uvnitr tasku (funkce) pro blikani
|
||||
|
||||
// Prototypy funkci
|
||||
void TaskSwitches(void);
|
||||
void TaskEffect(void);
|
||||
void TaskGreenLed(void);
|
||||
|
||||
int main(void) {
|
||||
// inicializace ovladace pinu a delay
|
||||
init();
|
||||
|
||||
while (1) {
|
||||
|
||||
TaskSwitches();
|
||||
TaskEffect();
|
||||
TaskGreenLed();
|
||||
|
||||
} // while
|
||||
|
||||
/* Never leave main */
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Uloha, ktera se stara o obsluhu tlacitek
|
||||
void TaskSwitches(void)
|
||||
{
|
||||
if (switch1_read() == SWITCH_PRESSED)
|
||||
SW1_pressed = true;
|
||||
else
|
||||
SW1_pressed = false;
|
||||
}
|
||||
|
||||
// Uloha, ktera se stara o blikani LED
|
||||
void TaskEffect(void) {
|
||||
// Stav totoho tasku.
|
||||
// Promenna je static, aby si uchovala hodnotu mezi volanimi teto funkce,
|
||||
// tj. aby nezanikla na konci funkce
|
||||
static int state = ST_LED1_ON;
|
||||
|
||||
static uint32_t waitStart; // cas, kdy se rozvitila LED, musi byt static!
|
||||
uint32_t currentTime; // aktualni cas, pomocna promenna
|
||||
|
||||
// Uloha efekt LED se provadi jen pri stisknutem tlacitku
|
||||
if (SW1_pressed) {
|
||||
switch (state) {
|
||||
|
||||
case ST_LED1_ON:
|
||||
// Rozsvitit LED, ulozit aktualni cas a prejit do stavu cekani na
|
||||
// uplynuti casu svitu teto LED.
|
||||
LED_control(true, false, false);
|
||||
waitStart = SYSTICK_millis();
|
||||
state = ST_LED1_WAIT;
|
||||
break;
|
||||
|
||||
case ST_LED1_WAIT:
|
||||
// Kontrola jestli uz ubehlo dost casu abychom rozsvitili dalsi LED
|
||||
// a pokud ano, prechod na dalsi stav
|
||||
currentTime = SYSTICK_millis();
|
||||
if (currentTime - waitStart >= BLINK_DELAY)
|
||||
state = ST_LED2_ON;
|
||||
break;
|
||||
|
||||
case ST_LED2_ON:
|
||||
LED_control(false, true, false);
|
||||
waitStart = SYSTICK_millis();
|
||||
state = ST_LED2_WAIT;
|
||||
break;
|
||||
|
||||
case ST_LED2_WAIT:
|
||||
currentTime = SYSTICK_millis();
|
||||
if (currentTime - waitStart >= BLINK_DELAY)
|
||||
state = ST_LED3_ON;
|
||||
break;
|
||||
|
||||
case ST_LED3_ON:
|
||||
LED_control(false, false, true);
|
||||
waitStart = SYSTICK_millis();
|
||||
state = ST_LED3_WAIT;
|
||||
break;
|
||||
|
||||
case ST_LED3_WAIT:
|
||||
currentTime = SYSTICK_millis();
|
||||
if (currentTime - waitStart >= BLINK_DELAY)
|
||||
state = ST_LED1_ON;
|
||||
break;
|
||||
|
||||
} // switch
|
||||
} else {
|
||||
// zhasnout LED pokud neni stisknuto tlacitko
|
||||
LED_control(false, false, false);
|
||||
state = ST_LED1_ON; // reset stavu tasku
|
||||
}
|
||||
|
||||
} // TaskEffect
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Doba svitu/zhasnuti zelene LED
|
||||
#define GREEN_ON_DELAY 200
|
||||
#define GREEN_OFF_DELAY 700
|
||||
|
||||
// Ukazka dalsiho tasku - blika pri stisknutem tlacitku RGB LED
|
||||
void TaskGreenLed() {
|
||||
static enum {
|
||||
ST_LED_ON,
|
||||
ST_ON_WAIT,
|
||||
ST_LED_OFF,
|
||||
ST_OFF_WAIT
|
||||
|
||||
} stav = ST_LED_ON;
|
||||
|
||||
static uint32_t startTime;
|
||||
|
||||
// uloha se provadi jen pri stisknutem tlacitku
|
||||
if (SW1_pressed) {
|
||||
|
||||
switch (stav) {
|
||||
|
||||
case ST_LED_ON:
|
||||
pinWrite(LED_GREEN, LOW);
|
||||
startTime = SYSTICK_millis();
|
||||
stav = ST_ON_WAIT;
|
||||
break;
|
||||
|
||||
case ST_ON_WAIT:
|
||||
if (SYSTICK_millis() - startTime >= GREEN_ON_DELAY)
|
||||
stav = ST_LED_OFF;
|
||||
break;
|
||||
|
||||
case ST_LED_OFF:
|
||||
pinWrite(LED_GREEN, HIGH);
|
||||
startTime = SYSTICK_millis();
|
||||
stav = ST_OFF_WAIT;
|
||||
break;
|
||||
|
||||
case ST_OFF_WAIT:
|
||||
if (SYSTICK_millis() - startTime >= GREEN_OFF_DELAY)
|
||||
stav = ST_LED_ON;
|
||||
break;
|
||||
} // switch
|
||||
} else {
|
||||
pinWrite(LED_GREEN, HIGH); // zhasni LED
|
||||
stav = ST_LED_ON; // resetuj stav LED
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#endif /* VERSION == 4*/
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Pomocne funkce spolecne pro vsechny verze
|
||||
|
||||
// inicializace
|
||||
void init()
|
||||
{
|
||||
SYSTICK_initialize();
|
||||
|
||||
GPIO_Initialize();
|
||||
|
||||
pinMode(SW1, INPUT_PULLUP);
|
||||
pinMode(LED1, OUTPUT);
|
||||
pinMode(LED2, OUTPUT);
|
||||
pinMode(LED3, OUTPUT);
|
||||
pinMode(LED_GREEN, OUTPUT);
|
||||
pinWrite(LED1, HIGH);
|
||||
pinWrite(LED2, HIGH);
|
||||
pinWrite(LED3, HIGH);
|
||||
pinWrite(LED_GREEN, HIGH);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Ovladani LED - parametr true znamena rozsvitit prislusnou LED, false zhasnout.
|
||||
void LED_control(bool d1, bool d2, bool d3)
|
||||
{
|
||||
pinWrite(LED1, !d1);
|
||||
pinWrite(LED2, !d2);
|
||||
pinWrite(LED3, !d3);
|
||||
}
|
||||
|
||||
/*
|
||||
switch1_read
|
||||
Cte stav tlacitka SW1 s osetrenim zakmitu.
|
||||
Vraci SWITCH_NOT_PRESSED pokud tlacitko neni stisknuto,
|
||||
SWITCH_PRESSED pokud je stisknuto.
|
||||
|
||||
Reads and debounces switch SW1 as follows:
|
||||
1. If switch is not pressed, return SWITCH_NOT_PRESSED.
|
||||
2. If switch is pressed, wait for about 20 ms (debounce),
|
||||
then:
|
||||
if switch is no longer pressed, return SWITCH_NOT_PRESSED.
|
||||
if switch is still pressed, return SWITCH_PRESSED.
|
||||
*/
|
||||
int switch1_read(void)
|
||||
{
|
||||
int switch_state = SWITCH_NOT_PRESSED;
|
||||
if ( pinRead(SW1) == LOW )
|
||||
{
|
||||
// tlacitko je stisknuto
|
||||
|
||||
// debounce = wait
|
||||
SYSTICK_delay_ms(50);
|
||||
|
||||
// znovu zkontrolovat stav tlacitka
|
||||
if ( pinRead(SW1) == LOW )
|
||||
{
|
||||
switch_state = SWITCH_PRESSED;
|
||||
}
|
||||
}
|
||||
// vratime stav tlacitka
|
||||
return switch_state;
|
||||
}
|
||||
|
||||
|
||||
|
144
simul_adc.h
144
simul_adc.h
@ -1,72 +1,72 @@
|
||||
/* Simulacni kod pro simulaci AD prevodniku */
|
||||
|
||||
#ifndef SIMUL_ADC_H
|
||||
#define SIMUL_ADC_H
|
||||
|
||||
#include "simul_kl25z.h"
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
void AdcValueWrite(unsigned int data);
|
||||
void AdcStartConversion(unsigned int data);
|
||||
|
||||
class ADC_Peripheral {
|
||||
public:
|
||||
ADC_Peripheral() : CFG1(&AdcValueWrite), CFG2(&AdcValueWrite), CFG3(&AdcValueWrite),
|
||||
SC1{ Property<uint32_t>(&AdcStartConversion), Property<uint32_t>(&AdcValueWrite) },
|
||||
R{ Property<uint32_t>(&AdcValueWrite), Property<uint32_t>(&AdcValueWrite) }
|
||||
{
|
||||
mConversionStarted = false;
|
||||
mCurrentDataIndex = 0;
|
||||
}
|
||||
|
||||
// monitored values
|
||||
Property<uint32_t> CFG1, CFG2, CFG3;
|
||||
Property<uint32_t> SC1[2];
|
||||
Property<uint32_t> R[2];
|
||||
// not monitored values
|
||||
uint32_t SC2;
|
||||
uint32_t SC3;
|
||||
uint32_t CLP0;
|
||||
uint32_t CLP1;
|
||||
uint32_t CLP2;
|
||||
uint32_t CLP3;
|
||||
uint32_t CLP4;
|
||||
uint32_t CLPS;
|
||||
uint32_t CLM0;
|
||||
uint32_t CLM1;
|
||||
uint32_t CLM2;
|
||||
uint32_t CLM3;
|
||||
uint32_t CLM4;
|
||||
uint32_t CLMS;
|
||||
uint32_t PG;
|
||||
uint32_t MG;
|
||||
|
||||
// helpers
|
||||
bool mConversionStarted;
|
||||
int mCurrentDataIndex;
|
||||
|
||||
// called when user writes to a register, to update internal state
|
||||
void UpdateData();
|
||||
|
||||
// Test pin on port C is configured as input
|
||||
bool IsPinConfigValid() {
|
||||
// clock enabled for port C
|
||||
if ( (SIM->SCGC5 & SIM_SCGC5_PORTC_MASK) == 0 ) {
|
||||
printf("Error: Clock for the port of ADC input pin it not enabled.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// pin function set to ADC
|
||||
if ( (PORTC->PCR[2] & PORT_PCR_MUX_MASK) != 0 ) {
|
||||
printf("Error: ADC input pin function not configured for ADC");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // SIMUL_ADC_H
|
||||
/* Simulacni kod pro simulaci AD prevodniku */
|
||||
|
||||
#ifndef SIMUL_ADC_H
|
||||
#define SIMUL_ADC_H
|
||||
|
||||
#include "simul_kl25z.h"
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
void AdcValueWrite(unsigned int data);
|
||||
void AdcStartConversion(unsigned int data);
|
||||
|
||||
class ADC_Peripheral {
|
||||
public:
|
||||
ADC_Peripheral() : CFG1(&AdcValueWrite), CFG2(&AdcValueWrite), CFG3(&AdcValueWrite),
|
||||
SC1{ Property<uint32_t>(&AdcStartConversion), Property<uint32_t>(&AdcValueWrite) },
|
||||
R{ Property<uint32_t>(&AdcValueWrite), Property<uint32_t>(&AdcValueWrite) }
|
||||
{
|
||||
mConversionStarted = false;
|
||||
mCurrentDataIndex = 0;
|
||||
}
|
||||
|
||||
// monitored values
|
||||
Property<uint32_t> CFG1, CFG2, CFG3;
|
||||
Property<uint32_t> SC1[2];
|
||||
Property<uint32_t> R[2];
|
||||
// not monitored values
|
||||
uint32_t SC2;
|
||||
uint32_t SC3;
|
||||
uint32_t CLP0;
|
||||
uint32_t CLP1;
|
||||
uint32_t CLP2;
|
||||
uint32_t CLP3;
|
||||
uint32_t CLP4;
|
||||
uint32_t CLPS;
|
||||
uint32_t CLM0;
|
||||
uint32_t CLM1;
|
||||
uint32_t CLM2;
|
||||
uint32_t CLM3;
|
||||
uint32_t CLM4;
|
||||
uint32_t CLMS;
|
||||
uint32_t PG;
|
||||
uint32_t MG;
|
||||
|
||||
// helpers
|
||||
bool mConversionStarted;
|
||||
int mCurrentDataIndex;
|
||||
|
||||
// called when user writes to a register, to update internal state
|
||||
void UpdateData();
|
||||
|
||||
// Test pin on port C is configured as input
|
||||
bool IsPinConfigValid() {
|
||||
// clock enabled for port C
|
||||
if ( (SIM->SCGC5 & SIM_SCGC5_PORTC_MASK) == 0 ) {
|
||||
printf("Error: Clock for the port of ADC input pin it not enabled.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// pin function set to ADC
|
||||
if ( (PORTC->PCR[2] & PORT_PCR_MUX_MASK) != 0 ) {
|
||||
printf("Error: ADC input pin function not configured for ADC");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // SIMUL_ADC_H
|
||||
|
1070
simul_kl25z.cpp
1070
simul_kl25z.cpp
@ -1,535 +1,535 @@
|
||||
/* Simple simulator for Kinetis KL25Z MCU
|
||||
* Main implementation file.
|
||||
* Add this file to your project to be build with your sources.
|
||||
* Requires C++11 support.
|
||||
*/
|
||||
|
||||
#include "simul_kl25z.h"
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <conio.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Delay with time in milliseconds
|
||||
void delay(unsigned int mseconds)
|
||||
{
|
||||
clock_t goal = mseconds + clock();
|
||||
while (goal > clock() ) ;
|
||||
}
|
||||
|
||||
// simple delay with some default value
|
||||
void delay(void)
|
||||
{
|
||||
delay(500);
|
||||
}
|
||||
|
||||
// clear screen
|
||||
void clear(){
|
||||
#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
|
||||
system("clear");
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
system("cls");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Buffers used by drivers to print to screen
|
||||
char gLEDsBuffer[256];
|
||||
char gLCDBuffer[256];
|
||||
// mutex to protect access to screen
|
||||
std::mutex gScreenMutex;
|
||||
|
||||
void WriteLEDsToScreen(); // in drv_gpio
|
||||
void WriteLCDToScreen(); // in drv_lcd
|
||||
|
||||
void WriteLEDsToBuffer(char* buffer); // in drv_gpio
|
||||
void WriteLCDToBuffer(char* buffer); // in drv_lcd
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
|
||||
static SIM_Peripheral sim_peripheral_object;
|
||||
SIM_Peripheral* SIM = &sim_peripheral_object;
|
||||
|
||||
// Port C module (needed for ADC input on port C)
|
||||
static PORT_Peripheral portc_peripheral_object;
|
||||
PORT_Peripheral* PORTC = &portc_peripheral_object;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// GPIO driver code
|
||||
|
||||
static bool gInitialized;
|
||||
static FRDM_kit_pinmode gPinModes[LAST_PIN];
|
||||
static uint8_t gPinOutputValues[LAST_PIN];
|
||||
static const char* gLedNames[] = {"LD1", "LD2", "LD3", "RED", "GREEN", "BLUE" };
|
||||
|
||||
|
||||
// Status of input pins
|
||||
constexpr int MAX_SWITCHES = 4;
|
||||
static bool gSwitchInputs[MAX_SWITCHES];
|
||||
// mutex to protect the switch input variable
|
||||
std::mutex gMutexSwitches;
|
||||
|
||||
// Background thread to process key press
|
||||
void task1(std::string msg)
|
||||
{
|
||||
(void)msg;
|
||||
while(1) {
|
||||
char c = getch();
|
||||
gMutexSwitches.lock();
|
||||
switch(c) {
|
||||
case '1':
|
||||
// toggle input state when key is pressed
|
||||
gSwitchInputs[0] = !gSwitchInputs[0];
|
||||
break;
|
||||
case '2':
|
||||
gSwitchInputs[1] = !gSwitchInputs[1];
|
||||
break;
|
||||
case '3':
|
||||
gSwitchInputs[2] = !gSwitchInputs[2];
|
||||
break;
|
||||
case '4':
|
||||
gSwitchInputs[3] = !gSwitchInputs[3];
|
||||
break;
|
||||
}
|
||||
gMutexSwitches.unlock();
|
||||
} // while 1
|
||||
}
|
||||
|
||||
// Thread to process screen refresh....
|
||||
void taskScreen() {
|
||||
while(1) {
|
||||
clear();
|
||||
|
||||
printf("KL25Z Simulation, version %d.%d\n\n", VERSION_MAJOR, VERSION_MINOR);
|
||||
gScreenMutex.lock();
|
||||
printf(gLEDsBuffer);
|
||||
printf(gLCDBuffer);
|
||||
gScreenMutex.unlock();
|
||||
// print status of switches
|
||||
printf("\n\n%5c%5c%5c%5c",
|
||||
gSwitchInputs[0] ? 'X' : '-',
|
||||
gSwitchInputs[1] ? 'X' : '-',
|
||||
gSwitchInputs[2] ? 'X' : '-',
|
||||
gSwitchInputs[3] ? 'X' : '-' );
|
||||
printf("\n SW1 SW2 SW3 SW4\n");
|
||||
delay(80);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This will create thread when the program starts...
|
||||
std::thread t1(task1, "Hello");
|
||||
std::thread t2(taskScreen);
|
||||
|
||||
/* Initialize the gpio driver for LEDs and push buttons. */
|
||||
void GPIO_Initialize(void)
|
||||
{
|
||||
gInitialized = true;
|
||||
for ( int i=0; i<MAX_SWITCHES; i++ )
|
||||
gSwitchInputs[i] = false;
|
||||
}
|
||||
|
||||
/* Configure given pin to behave as input or output. */
|
||||
void pinMode(FRDM_kit_pin pin, FRDM_kit_pinmode mode )
|
||||
{
|
||||
if ( !gInitialized ) {
|
||||
printf("BSOD - Default ISR :) \nGPIO driver not initialized!\n");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
|
||||
switch (pin)
|
||||
{
|
||||
/* All LEDs are on port B */
|
||||
case LD1:
|
||||
case LD2:
|
||||
case LD3:
|
||||
case LED_RED:
|
||||
case LED_GREEN:
|
||||
case LED_BLUE:
|
||||
case SW1:
|
||||
case SW2:
|
||||
case SW3:
|
||||
case SW4:
|
||||
gPinModes[(int)pin] = mode;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Warning: Invalid pin %d in pinMode.\n", pin);
|
||||
//while (1) ; /* Error: invalid pin! */
|
||||
}
|
||||
}
|
||||
|
||||
/* Set value for given pin. The pin must be configured as output with pinMode first! */
|
||||
void pinWrite(FRDM_kit_pin pin, uint8_t value )
|
||||
{
|
||||
if ( !gInitialized ) {
|
||||
printf("BSOD - Default ISR :) \nGPIO driver not initialized!\n");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
switch(pin)
|
||||
{
|
||||
/* All LEDs are on port B */
|
||||
case LD1:
|
||||
case LD2:
|
||||
case LD3:
|
||||
case LED_RED:
|
||||
case LED_GREEN:
|
||||
case LED_BLUE:
|
||||
case SW1:
|
||||
case SW2:
|
||||
case SW3:
|
||||
case SW4:
|
||||
if ( gPinModes[(int)pin] == OUTPUT ) {
|
||||
// update screen
|
||||
gPinOutputValues[(int)pin] = value;
|
||||
WriteLEDsToBuffer(gLEDsBuffer);
|
||||
//WriteLEDsToScreen();
|
||||
|
||||
} else {
|
||||
// do nothing
|
||||
printf("Warning: Pin %d is not an output.\n", pin);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Warning: Invalid pin %d in pinWrite.\n", pin);
|
||||
//while(1) ; /* Error: invalid pin! */
|
||||
}
|
||||
}
|
||||
|
||||
/* Read value on given pin. The pin must be configured as input with pinMode first! */
|
||||
uint8_t pinRead(FRDM_kit_pin pin)
|
||||
{
|
||||
if ( !gInitialized ) {
|
||||
printf("BSOD - Default ISR :) \nGPIO driver not initialized!\n");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
uint8_t result = LOW;
|
||||
if ( gPinModes[(int)pin] == INPUT || gPinModes[(int)pin] == INPUT_PULLUP ) {
|
||||
|
||||
// Background thread reads the keyboard and sets gSwitchInputs
|
||||
gMutexSwitches.lock();
|
||||
switch(pin)
|
||||
{
|
||||
case SW1:
|
||||
result = (gSwitchInputs[0]) ? LOW : HIGH;
|
||||
break;
|
||||
case SW2:
|
||||
result = (gSwitchInputs[1]) ? LOW : HIGH;
|
||||
break;
|
||||
case SW3:
|
||||
result = (gSwitchInputs[2]) ? LOW : HIGH;
|
||||
break;
|
||||
case SW4:
|
||||
result = (gSwitchInputs[3]) ? LOW : HIGH;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Warning: Pin %d not supported for input in simulator.\n", pin);
|
||||
break;
|
||||
}
|
||||
gMutexSwitches.unlock();
|
||||
|
||||
} else {
|
||||
printf("Warning: Pin %d is not an input.\n", pin);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
// Helpers to print LED state to console
|
||||
#define GET_LED_SYMBOL(a) ((a == 0) ? 'X' : '-')
|
||||
#define PRINT_LED_FROM_MODE(mode, value) ((mode == OUTPUT) ? GET_LED_SYMBOL(value) : '-')
|
||||
|
||||
void WriteLEDsToBuffer(char* buffer) {
|
||||
|
||||
char buff[512];
|
||||
gScreenMutex.lock();
|
||||
buffer[0] = '\0';
|
||||
sprintf(buff, "%5c%5c%5c\t\t%3c%3c%3c\n",
|
||||
PRINT_LED_FROM_MODE(gPinModes[0], gPinOutputValues[0]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[1], gPinOutputValues[1]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[2], gPinOutputValues[2]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[3], gPinOutputValues[3]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[4], gPinOutputValues[4]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[5], gPinOutputValues[5])
|
||||
);
|
||||
strcat(buffer, buff);
|
||||
|
||||
sprintf(buff, "%5s%5s%5s\t\t%s/%s/%s\n", gLedNames[0], gLedNames[1], gLedNames[2],
|
||||
gLedNames[3], gLedNames[4], gLedNames[5]);
|
||||
strcat(buffer, buff);
|
||||
gScreenMutex.unlock();
|
||||
}
|
||||
|
||||
void WriteLEDsToScreen() {
|
||||
|
||||
printf("%5c%5c%5c\t\t%3c%3c%3c\n",
|
||||
PRINT_LED_FROM_MODE(gPinModes[0], gPinOutputValues[0]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[1], gPinOutputValues[1]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[2], gPinOutputValues[2]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[3], gPinOutputValues[3]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[4], gPinOutputValues[4]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[5], gPinOutputValues[5])
|
||||
);
|
||||
|
||||
printf("%5s%5s%5s\t\t%s/%s/%s\n", gLedNames[0], gLedNames[1], gLedNames[2],
|
||||
gLedNames[3], gLedNames[4], gLedNames[5]);
|
||||
|
||||
}
|
||||
|
||||
// end GPIO driver code
|
||||
//////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////
|
||||
// ADC code
|
||||
|
||||
// Simulated ADC values
|
||||
static uint16_t adc_values[] = { 10, 30, 60, 100, 110, 120, 130, 140, 150, 170, 200, 230, 255,
|
||||
230, 200, 170, 150, 130, 100, 60, 30, 0, 0 };
|
||||
static int MAX_ADC_VALUES = sizeof(adc_values)/sizeof(uint16_t);
|
||||
|
||||
|
||||
|
||||
|
||||
// Define the ADC0 module for use in user program
|
||||
static ADC_Peripheral adc_module_object;
|
||||
ADC_Peripheral* ADC0 = &adc_module_object;
|
||||
|
||||
void AdcValueWrite(unsigned int data) {
|
||||
(void)data; // just to remove unused param warning
|
||||
ADC0->UpdateData();
|
||||
}
|
||||
|
||||
// handler for write to CFG1[0] only to indicate we have valid settings
|
||||
void AdcStartConversion(unsigned int data) {
|
||||
//std::cout << "Start conversion " << data << '\n';
|
||||
|
||||
// For our pin - channel 11 check the pin config, for other channels just
|
||||
// skip test and simulated that conversion completed. This is needed for
|
||||
// calibration etc.
|
||||
int channel = (data & ADC_SC1_ADCH_MASK) >> ADC_SC1_ADCH_SHIFT;
|
||||
if ( channel == 11 ) {
|
||||
if ( ADC0->IsPinConfigValid() )
|
||||
ADC0->mConversionStarted = true;
|
||||
|
||||
} else {
|
||||
// conversion must be started for any other channel, also for calibration
|
||||
ADC0->mConversionStarted = true;
|
||||
}
|
||||
|
||||
ADC0->UpdateData();
|
||||
}
|
||||
|
||||
void ADC_Peripheral::UpdateData()
|
||||
{
|
||||
// test if clock is enabled
|
||||
if ( (SIM->SCGC6 & SIM_SCGC6_ADC0_MASK) == 0 ) {
|
||||
printf("BSOD - Default ISR :) \nADC - clock not enabled!\n");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
if ( mConversionStarted ) {
|
||||
// get next value for ADC if channel is 11
|
||||
if ( (SC1[0] & 0x1F) == ADC_SC1_ADCH(11) ) {
|
||||
// rozliseni
|
||||
int mode = (CFG1 & ADC_CFG1_MODE_MASK) >> ADC_CFG1_MODE_SHIFT;
|
||||
int shift = 0;
|
||||
switch ( mode) {
|
||||
case 0: // 8 bit
|
||||
shift = 0;
|
||||
PRINT_DGMSG("ADC resolution is 8 bit.");
|
||||
break;
|
||||
case 1: // 12 bit
|
||||
shift = 4;
|
||||
PRINT_DGMSG("ADC resolution is 12 bit.");
|
||||
break;
|
||||
case 2: // 10 bit
|
||||
shift = 2;
|
||||
PRINT_DGMSG("ADC resolution is 10 bit.");
|
||||
break;
|
||||
case 3: // 16 bit
|
||||
shift = 8;
|
||||
PRINT_DGMSG("ADC resolution is 16 bit.");
|
||||
break;
|
||||
}
|
||||
|
||||
R[0].data = adc_values[mCurrentDataIndex++] << shift;
|
||||
if ( mCurrentDataIndex >= MAX_ADC_VALUES )
|
||||
mCurrentDataIndex = 0;
|
||||
}
|
||||
|
||||
SC1[0].data |= ADC_SC1_COCO_MASK; // set conversion complete flag
|
||||
mConversionStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// end ADC driver code
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// LCD driver code
|
||||
static bool gLcdInitialized;
|
||||
|
||||
static char gDispData[4][21];
|
||||
static int gRow, gColumn;
|
||||
|
||||
void WriteLCDToScreen() {
|
||||
//clear();
|
||||
printf("\n\nLCD-----------------\n");
|
||||
//printf("123456789ABCDEFGHIJK\n");
|
||||
for ( int i=0; i<4; i++ )
|
||||
printf("%s\n", gDispData[i]);
|
||||
printf("---------------------\n");
|
||||
}
|
||||
|
||||
void WriteLCDToBuffer(char* buffer) {
|
||||
//clear();
|
||||
char buff[512];
|
||||
gScreenMutex.lock();
|
||||
buffer[0] = '\0';
|
||||
sprintf(buff, "\n\nLCD-----------------\n");
|
||||
strcat(buffer, buff);
|
||||
//printf("123456789ABCDEFGHIJK\n");
|
||||
for ( int i=0; i<4; i++ ) {
|
||||
sprintf(buff, "%s\n", gDispData[i]);
|
||||
strcat(buffer, buff);
|
||||
}
|
||||
|
||||
sprintf(buff, "---------------------\n");
|
||||
strcat(buffer, buff);
|
||||
gScreenMutex.unlock();
|
||||
}
|
||||
|
||||
/* initialize display */
|
||||
void LCD_initialize(void)
|
||||
{
|
||||
gLcdInitialized = true;
|
||||
gRow = 0; // 1 - 4
|
||||
gColumn = 0; // 1 - 20
|
||||
}
|
||||
|
||||
|
||||
void LCD_set_cursor(uint8_t line, uint8_t column) {
|
||||
if ( line > 0 && line < 5)
|
||||
gRow = line - 1;
|
||||
if ( column > 0 && column < 21 )
|
||||
gColumn = column - 1;
|
||||
}
|
||||
|
||||
void LCD_putch(char c) {
|
||||
if ( !gLcdInitialized ) {
|
||||
printf("BSOD - Default ISR :) \nLCD driver not initialized!\n");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
if ( gColumn > 19 ) {
|
||||
printf("Warning: LCD writing beyond last column!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( gRow > 3 ) {
|
||||
printf("Warning: LCD writing below last line!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gDispData[gRow][gColumn] = c;
|
||||
gColumn++;
|
||||
if ( gColumn > 19 )
|
||||
gColumn = 0;
|
||||
|
||||
// update screen
|
||||
WriteLCDToBuffer(gLCDBuffer);
|
||||
}
|
||||
|
||||
|
||||
void LCD_puts(const char* str) {
|
||||
if ( !gLcdInitialized ) {
|
||||
printf("BSOD - Default ISR :) \nLCD driver not initialized!\n");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
char* p = gDispData[gRow];
|
||||
int len = 20 - gColumn;
|
||||
if ( len > 0) {
|
||||
strncpy(p + gColumn, str, len);
|
||||
gDispData[gRow][gColumn+len] = '\0';
|
||||
gColumn += strlen(str);
|
||||
} else {
|
||||
printf("Warning: LCD writing beyond last column!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
WriteLCDToBuffer(gLCDBuffer);
|
||||
}
|
||||
|
||||
|
||||
void LCD_clear(void) {
|
||||
if ( !gLcdInitialized ) {
|
||||
printf("BSOD - Default ISR :) \nLCD driver not initialized!\n");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
gRow = 0; // 1 - 4
|
||||
gColumn = 0;
|
||||
|
||||
for ( int i = 0; i<4; i++ ) {
|
||||
for ( int j = 0; j<20; j++) {
|
||||
gDispData[i][j] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
WriteLCDToBuffer(gLCDBuffer);
|
||||
}
|
||||
|
||||
|
||||
void LCD_backlight_on(void) {
|
||||
printf("Warning: LCD_backlight_on not implemented.\n");
|
||||
}
|
||||
|
||||
|
||||
void LCD_backlight_off(void) {
|
||||
printf("Warning: LCD_backlight_off not implemented.\n");
|
||||
}
|
||||
|
||||
// end LCD driver code
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// SYSTICK driver code
|
||||
// Simulate systick driver functions
|
||||
// Functions implemented in simul_kl25z.cpp
|
||||
void SYSTICK_initialize(void)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
uint32_t SYSTICK_millis(void)
|
||||
{
|
||||
return (uint32_t)clock();
|
||||
}
|
||||
|
||||
uint32_t SYSTICK_micros(void)
|
||||
{
|
||||
return SYSTICK_millis() * 1000;
|
||||
}
|
||||
|
||||
void SYSTICK_delay_ms(uint32_t millis)
|
||||
{
|
||||
delay(millis);
|
||||
}
|
||||
|
||||
// end SYSTICK driver code
|
||||
//////////////////////////////////////////////////////////////////
|
||||
/* Simple simulator for Kinetis KL25Z MCU
|
||||
* Main implementation file.
|
||||
* Add this file to your project to be build with your sources.
|
||||
* Requires C++11 support.
|
||||
*/
|
||||
|
||||
#include "simul_kl25z.h"
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <conio.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Delay with time in milliseconds
|
||||
void delay(unsigned int mseconds)
|
||||
{
|
||||
clock_t goal = mseconds + clock();
|
||||
while (goal > clock() ) ;
|
||||
}
|
||||
|
||||
// simple delay with some default value
|
||||
void delay(void)
|
||||
{
|
||||
delay(500);
|
||||
}
|
||||
|
||||
// clear screen
|
||||
void clear(){
|
||||
#if defined(__linux__) || defined(__unix__) || defined(__APPLE__)
|
||||
system("clear");
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
system("cls");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Buffers used by drivers to print to screen
|
||||
char gLEDsBuffer[256];
|
||||
char gLCDBuffer[256];
|
||||
// mutex to protect access to screen
|
||||
std::mutex gScreenMutex;
|
||||
|
||||
void WriteLEDsToScreen(); // in drv_gpio
|
||||
void WriteLCDToScreen(); // in drv_lcd
|
||||
|
||||
void WriteLEDsToBuffer(char* buffer); // in drv_gpio
|
||||
void WriteLCDToBuffer(char* buffer); // in drv_lcd
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
|
||||
static SIM_Peripheral sim_peripheral_object;
|
||||
SIM_Peripheral* SIM = &sim_peripheral_object;
|
||||
|
||||
// Port C module (needed for ADC input on port C)
|
||||
static PORT_Peripheral portc_peripheral_object;
|
||||
PORT_Peripheral* PORTC = &portc_peripheral_object;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// GPIO driver code
|
||||
|
||||
static bool gInitialized;
|
||||
static FRDM_kit_pinmode gPinModes[LAST_PIN];
|
||||
static uint8_t gPinOutputValues[LAST_PIN];
|
||||
static const char* gLedNames[] = {"LD1", "LD2", "LD3", "RED", "GREEN", "BLUE" };
|
||||
|
||||
|
||||
// Status of input pins
|
||||
constexpr int MAX_SWITCHES = 4;
|
||||
static bool gSwitchInputs[MAX_SWITCHES];
|
||||
// mutex to protect the switch input variable
|
||||
std::mutex gMutexSwitches;
|
||||
|
||||
// Background thread to process key press
|
||||
void task1(std::string msg)
|
||||
{
|
||||
(void)msg;
|
||||
while(1) {
|
||||
char c = getch();
|
||||
gMutexSwitches.lock();
|
||||
switch(c) {
|
||||
case '1':
|
||||
// toggle input state when key is pressed
|
||||
gSwitchInputs[0] = !gSwitchInputs[0];
|
||||
break;
|
||||
case '2':
|
||||
gSwitchInputs[1] = !gSwitchInputs[1];
|
||||
break;
|
||||
case '3':
|
||||
gSwitchInputs[2] = !gSwitchInputs[2];
|
||||
break;
|
||||
case '4':
|
||||
gSwitchInputs[3] = !gSwitchInputs[3];
|
||||
break;
|
||||
}
|
||||
gMutexSwitches.unlock();
|
||||
} // while 1
|
||||
}
|
||||
|
||||
// Thread to process screen refresh....
|
||||
void taskScreen() {
|
||||
while(1) {
|
||||
clear();
|
||||
|
||||
printf("KL25Z Simulation, version %d.%d\n\n", VERSION_MAJOR, VERSION_MINOR);
|
||||
gScreenMutex.lock();
|
||||
printf(gLEDsBuffer);
|
||||
printf(gLCDBuffer);
|
||||
gScreenMutex.unlock();
|
||||
// print status of switches
|
||||
printf("\n\n%5c%5c%5c%5c",
|
||||
gSwitchInputs[0] ? 'X' : '-',
|
||||
gSwitchInputs[1] ? 'X' : '-',
|
||||
gSwitchInputs[2] ? 'X' : '-',
|
||||
gSwitchInputs[3] ? 'X' : '-' );
|
||||
printf("\n SW1 SW2 SW3 SW4\n");
|
||||
delay(80);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This will create thread when the program starts...
|
||||
std::thread t1(task1, "Hello");
|
||||
std::thread t2(taskScreen);
|
||||
|
||||
/* Initialize the gpio driver for LEDs and push buttons. */
|
||||
void GPIO_Initialize(void)
|
||||
{
|
||||
gInitialized = true;
|
||||
for ( int i=0; i<MAX_SWITCHES; i++ )
|
||||
gSwitchInputs[i] = false;
|
||||
}
|
||||
|
||||
/* Configure given pin to behave as input or output. */
|
||||
void pinMode(FRDM_kit_pin pin, FRDM_kit_pinmode mode )
|
||||
{
|
||||
if ( !gInitialized ) {
|
||||
printf("BSOD - Default ISR :) \nGPIO driver not initialized!\n");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
|
||||
switch (pin)
|
||||
{
|
||||
/* All LEDs are on port B */
|
||||
case LD1:
|
||||
case LD2:
|
||||
case LD3:
|
||||
case LED_RED:
|
||||
case LED_GREEN:
|
||||
case LED_BLUE:
|
||||
case SW1:
|
||||
case SW2:
|
||||
case SW3:
|
||||
case SW4:
|
||||
gPinModes[(int)pin] = mode;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Warning: Invalid pin %d in pinMode.\n", pin);
|
||||
//while (1) ; /* Error: invalid pin! */
|
||||
}
|
||||
}
|
||||
|
||||
/* Set value for given pin. The pin must be configured as output with pinMode first! */
|
||||
void pinWrite(FRDM_kit_pin pin, uint8_t value )
|
||||
{
|
||||
if ( !gInitialized ) {
|
||||
printf("BSOD - Default ISR :) \nGPIO driver not initialized!\n");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
switch(pin)
|
||||
{
|
||||
/* All LEDs are on port B */
|
||||
case LD1:
|
||||
case LD2:
|
||||
case LD3:
|
||||
case LED_RED:
|
||||
case LED_GREEN:
|
||||
case LED_BLUE:
|
||||
case SW1:
|
||||
case SW2:
|
||||
case SW3:
|
||||
case SW4:
|
||||
if ( gPinModes[(int)pin] == OUTPUT ) {
|
||||
// update screen
|
||||
gPinOutputValues[(int)pin] = value;
|
||||
WriteLEDsToBuffer(gLEDsBuffer);
|
||||
//WriteLEDsToScreen();
|
||||
|
||||
} else {
|
||||
// do nothing
|
||||
printf("Warning: Pin %d is not an output.\n", pin);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Warning: Invalid pin %d in pinWrite.\n", pin);
|
||||
//while(1) ; /* Error: invalid pin! */
|
||||
}
|
||||
}
|
||||
|
||||
/* Read value on given pin. The pin must be configured as input with pinMode first! */
|
||||
uint8_t pinRead(FRDM_kit_pin pin)
|
||||
{
|
||||
if ( !gInitialized ) {
|
||||
printf("BSOD - Default ISR :) \nGPIO driver not initialized!\n");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
uint8_t result = LOW;
|
||||
if ( gPinModes[(int)pin] == INPUT || gPinModes[(int)pin] == INPUT_PULLUP ) {
|
||||
|
||||
// Background thread reads the keyboard and sets gSwitchInputs
|
||||
gMutexSwitches.lock();
|
||||
switch(pin)
|
||||
{
|
||||
case SW1:
|
||||
result = (gSwitchInputs[0]) ? LOW : HIGH;
|
||||
break;
|
||||
case SW2:
|
||||
result = (gSwitchInputs[1]) ? LOW : HIGH;
|
||||
break;
|
||||
case SW3:
|
||||
result = (gSwitchInputs[2]) ? LOW : HIGH;
|
||||
break;
|
||||
case SW4:
|
||||
result = (gSwitchInputs[3]) ? LOW : HIGH;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Warning: Pin %d not supported for input in simulator.\n", pin);
|
||||
break;
|
||||
}
|
||||
gMutexSwitches.unlock();
|
||||
|
||||
} else {
|
||||
printf("Warning: Pin %d is not an input.\n", pin);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
// Helpers to print LED state to console
|
||||
#define GET_LED_SYMBOL(a) ((a == 0) ? 'X' : '-')
|
||||
#define PRINT_LED_FROM_MODE(mode, value) ((mode == OUTPUT) ? GET_LED_SYMBOL(value) : '-')
|
||||
|
||||
void WriteLEDsToBuffer(char* buffer) {
|
||||
|
||||
char buff[512];
|
||||
gScreenMutex.lock();
|
||||
buffer[0] = '\0';
|
||||
sprintf(buff, "%5c%5c%5c\t\t%3c%3c%3c\n",
|
||||
PRINT_LED_FROM_MODE(gPinModes[0], gPinOutputValues[0]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[1], gPinOutputValues[1]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[2], gPinOutputValues[2]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[3], gPinOutputValues[3]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[4], gPinOutputValues[4]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[5], gPinOutputValues[5])
|
||||
);
|
||||
strcat(buffer, buff);
|
||||
|
||||
sprintf(buff, "%5s%5s%5s\t\t%s/%s/%s\n", gLedNames[0], gLedNames[1], gLedNames[2],
|
||||
gLedNames[3], gLedNames[4], gLedNames[5]);
|
||||
strcat(buffer, buff);
|
||||
gScreenMutex.unlock();
|
||||
}
|
||||
|
||||
void WriteLEDsToScreen() {
|
||||
|
||||
printf("%5c%5c%5c\t\t%3c%3c%3c\n",
|
||||
PRINT_LED_FROM_MODE(gPinModes[0], gPinOutputValues[0]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[1], gPinOutputValues[1]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[2], gPinOutputValues[2]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[3], gPinOutputValues[3]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[4], gPinOutputValues[4]),
|
||||
PRINT_LED_FROM_MODE(gPinModes[5], gPinOutputValues[5])
|
||||
);
|
||||
|
||||
printf("%5s%5s%5s\t\t%s/%s/%s\n", gLedNames[0], gLedNames[1], gLedNames[2],
|
||||
gLedNames[3], gLedNames[4], gLedNames[5]);
|
||||
|
||||
}
|
||||
|
||||
// end GPIO driver code
|
||||
//////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////
|
||||
// ADC code
|
||||
|
||||
// Simulated ADC values
|
||||
static uint16_t adc_values[] = { 10, 30, 60, 100, 110, 120, 130, 140, 150, 170, 200, 230, 255,
|
||||
230, 200, 170, 150, 130, 100, 60, 30, 0, 0 };
|
||||
static int MAX_ADC_VALUES = sizeof(adc_values)/sizeof(uint16_t);
|
||||
|
||||
|
||||
|
||||
|
||||
// Define the ADC0 module for use in user program
|
||||
static ADC_Peripheral adc_module_object;
|
||||
ADC_Peripheral* ADC0 = &adc_module_object;
|
||||
|
||||
void AdcValueWrite(unsigned int data) {
|
||||
(void)data; // just to remove unused param warning
|
||||
ADC0->UpdateData();
|
||||
}
|
||||
|
||||
// handler for write to CFG1[0] only to indicate we have valid settings
|
||||
void AdcStartConversion(unsigned int data) {
|
||||
//std::cout << "Start conversion " << data << '\n';
|
||||
|
||||
// For our pin - channel 11 check the pin config, for other channels just
|
||||
// skip test and simulated that conversion completed. This is needed for
|
||||
// calibration etc.
|
||||
int channel = (data & ADC_SC1_ADCH_MASK) >> ADC_SC1_ADCH_SHIFT;
|
||||
if ( channel == 11 ) {
|
||||
if ( ADC0->IsPinConfigValid() )
|
||||
ADC0->mConversionStarted = true;
|
||||
|
||||
} else {
|
||||
// conversion must be started for any other channel, also for calibration
|
||||
ADC0->mConversionStarted = true;
|
||||
}
|
||||
|
||||
ADC0->UpdateData();
|
||||
}
|
||||
|
||||
void ADC_Peripheral::UpdateData()
|
||||
{
|
||||
// test if clock is enabled
|
||||
if ( (SIM->SCGC6 & SIM_SCGC6_ADC0_MASK) == 0 ) {
|
||||
printf("BSOD - Default ISR :) \nADC - clock not enabled!\n");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
if ( mConversionStarted ) {
|
||||
// get next value for ADC if channel is 11
|
||||
if ( (SC1[0] & 0x1F) == ADC_SC1_ADCH(11) ) {
|
||||
// rozliseni
|
||||
int mode = (CFG1 & ADC_CFG1_MODE_MASK) >> ADC_CFG1_MODE_SHIFT;
|
||||
int shift = 0;
|
||||
switch ( mode) {
|
||||
case 0: // 8 bit
|
||||
shift = 0;
|
||||
PRINT_DGMSG("ADC resolution is 8 bit.");
|
||||
break;
|
||||
case 1: // 12 bit
|
||||
shift = 4;
|
||||
PRINT_DGMSG("ADC resolution is 12 bit.");
|
||||
break;
|
||||
case 2: // 10 bit
|
||||
shift = 2;
|
||||
PRINT_DGMSG("ADC resolution is 10 bit.");
|
||||
break;
|
||||
case 3: // 16 bit
|
||||
shift = 8;
|
||||
PRINT_DGMSG("ADC resolution is 16 bit.");
|
||||
break;
|
||||
}
|
||||
|
||||
R[0].data = adc_values[mCurrentDataIndex++] << shift;
|
||||
if ( mCurrentDataIndex >= MAX_ADC_VALUES )
|
||||
mCurrentDataIndex = 0;
|
||||
}
|
||||
|
||||
SC1[0].data |= ADC_SC1_COCO_MASK; // set conversion complete flag
|
||||
mConversionStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// end ADC driver code
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// LCD driver code
|
||||
static bool gLcdInitialized;
|
||||
|
||||
static char gDispData[4][21];
|
||||
static int gRow, gColumn;
|
||||
|
||||
void WriteLCDToScreen() {
|
||||
//clear();
|
||||
printf("\n\nLCD-----------------\n");
|
||||
//printf("123456789ABCDEFGHIJK\n");
|
||||
for ( int i=0; i<4; i++ )
|
||||
printf("%s\n", gDispData[i]);
|
||||
printf("---------------------\n");
|
||||
}
|
||||
|
||||
void WriteLCDToBuffer(char* buffer) {
|
||||
//clear();
|
||||
char buff[512];
|
||||
gScreenMutex.lock();
|
||||
buffer[0] = '\0';
|
||||
sprintf(buff, "\n\nLCD-----------------\n");
|
||||
strcat(buffer, buff);
|
||||
//printf("123456789ABCDEFGHIJK\n");
|
||||
for ( int i=0; i<4; i++ ) {
|
||||
sprintf(buff, "%s\n", gDispData[i]);
|
||||
strcat(buffer, buff);
|
||||
}
|
||||
|
||||
sprintf(buff, "---------------------\n");
|
||||
strcat(buffer, buff);
|
||||
gScreenMutex.unlock();
|
||||
}
|
||||
|
||||
/* initialize display */
|
||||
void LCD_initialize(void)
|
||||
{
|
||||
gLcdInitialized = true;
|
||||
gRow = 0; // 1 - 4
|
||||
gColumn = 0; // 1 - 20
|
||||
}
|
||||
|
||||
|
||||
void LCD_set_cursor(uint8_t line, uint8_t column) {
|
||||
if ( line > 0 && line < 5)
|
||||
gRow = line - 1;
|
||||
if ( column > 0 && column < 21 )
|
||||
gColumn = column - 1;
|
||||
}
|
||||
|
||||
void LCD_putch(char c) {
|
||||
if ( !gLcdInitialized ) {
|
||||
printf("BSOD - Default ISR :) \nLCD driver not initialized!\n");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
if ( gColumn > 19 ) {
|
||||
printf("Warning: LCD writing beyond last column!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( gRow > 3 ) {
|
||||
printf("Warning: LCD writing below last line!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gDispData[gRow][gColumn] = c;
|
||||
gColumn++;
|
||||
if ( gColumn > 19 )
|
||||
gColumn = 0;
|
||||
|
||||
// update screen
|
||||
WriteLCDToBuffer(gLCDBuffer);
|
||||
}
|
||||
|
||||
|
||||
void LCD_puts(const char* str) {
|
||||
if ( !gLcdInitialized ) {
|
||||
printf("BSOD - Default ISR :) \nLCD driver not initialized!\n");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
char* p = gDispData[gRow];
|
||||
int len = 20 - gColumn;
|
||||
if ( len > 0) {
|
||||
strncpy(p + gColumn, str, len);
|
||||
gDispData[gRow][gColumn+len] = '\0';
|
||||
gColumn += strlen(str);
|
||||
} else {
|
||||
printf("Warning: LCD writing beyond last column!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
WriteLCDToBuffer(gLCDBuffer);
|
||||
}
|
||||
|
||||
|
||||
void LCD_clear(void) {
|
||||
if ( !gLcdInitialized ) {
|
||||
printf("BSOD - Default ISR :) \nLCD driver not initialized!\n");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
gRow = 0; // 1 - 4
|
||||
gColumn = 0;
|
||||
|
||||
for ( int i = 0; i<4; i++ ) {
|
||||
for ( int j = 0; j<20; j++) {
|
||||
gDispData[i][j] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
WriteLCDToBuffer(gLCDBuffer);
|
||||
}
|
||||
|
||||
|
||||
void LCD_backlight_on(void) {
|
||||
printf("Warning: LCD_backlight_on not implemented.\n");
|
||||
}
|
||||
|
||||
|
||||
void LCD_backlight_off(void) {
|
||||
printf("Warning: LCD_backlight_off not implemented.\n");
|
||||
}
|
||||
|
||||
// end LCD driver code
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// SYSTICK driver code
|
||||
// Simulate systick driver functions
|
||||
// Functions implemented in simul_kl25z.cpp
|
||||
void SYSTICK_initialize(void)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
uint32_t SYSTICK_millis(void)
|
||||
{
|
||||
return (uint32_t)clock();
|
||||
}
|
||||
|
||||
uint32_t SYSTICK_micros(void)
|
||||
{
|
||||
return SYSTICK_millis() * 1000;
|
||||
}
|
||||
|
||||
void SYSTICK_delay_ms(uint32_t millis)
|
||||
{
|
||||
delay(millis);
|
||||
}
|
||||
|
||||
// end SYSTICK driver code
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
212
simul_kl25z.h
212
simul_kl25z.h
@ -1,107 +1,105 @@
|
||||
/* Simple simulator for Kinetis KL25Z MCU
|
||||
* Main include file.
|
||||
* Include just this file in your source.
|
||||
* Requires C++11 support.
|
||||
*
|
||||
* Note: to simulate switch input use pinRead() with SW1 - SW4;
|
||||
* Keyboard key '1' is SW1, SW2 is key '2' etc.
|
||||
* Pressing a key toggles the switch On/Off.
|
||||
* So use '1' and '1' to simulate switch SW1 press and release.
|
||||
* This is because holding the key down results in the char being sent
|
||||
* repeatedly to the program - keyboard has autorepeat feature.
|
||||
*/
|
||||
|
||||
#ifndef SIMUL_KL25Z_H
|
||||
#define SIMUL_KL25Z_H
|
||||
|
||||
// Note: Include simulator headers at the end of this file
|
||||
// because they need definitions provided here...
|
||||
|
||||
#include "simul_regs.h"
|
||||
|
||||
// Version of the simulator
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 2
|
||||
|
||||
// Enable diagnostic messages
|
||||
#define VERBOSE_INFO 0
|
||||
|
||||
#if VERBOSE_INFO == 1
|
||||
#define PRINT_DGMSG(a) std::cout << a << std::endl
|
||||
#else
|
||||
#define PRINT_DGMSG(a)
|
||||
#endif
|
||||
|
||||
// Global functions
|
||||
void delay(unsigned int mseconds);
|
||||
void delay(void);
|
||||
|
||||
class SIM_Peripheral;
|
||||
class PORT_Peripheral;
|
||||
class ADC_Peripheral;
|
||||
|
||||
extern SIM_Peripheral* SIM;
|
||||
extern PORT_Peripheral* PORTC;
|
||||
extern ADC_Peripheral* ADC0;
|
||||
|
||||
// Universal property with value change handler
|
||||
// from https://stackoverflow.com/questions/9144819/c-function-calling-when-changing-member-value
|
||||
#include <functional>
|
||||
|
||||
template<typename T>
|
||||
class Property {
|
||||
friend class ADC_Peripheral;
|
||||
|
||||
public:
|
||||
Property(std::function<void(T)> callback) : data(), callback(callback) { }
|
||||
|
||||
Property& operator=(const T& newvalue) {
|
||||
data = newvalue;
|
||||
callback(data);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Property& operator|=(const T& newvalue) {
|
||||
data |= newvalue;
|
||||
callback(data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator T() const {
|
||||
return data;
|
||||
}
|
||||
|
||||
private:
|
||||
T data;
|
||||
std::function<void(T)> callback;
|
||||
|
||||
};
|
||||
|
||||
// SIM module
|
||||
class SIM_Peripheral {
|
||||
public:
|
||||
uint32_t SCGC5;
|
||||
uint32_t SCGC6;
|
||||
};
|
||||
|
||||
// Port module
|
||||
class PORT_Peripheral {
|
||||
public:
|
||||
uint32_t PCR[32]; // pin control register
|
||||
};
|
||||
|
||||
// simulate systick driver functions
|
||||
// Functions implemented in simul_kl25z.cpp
|
||||
void SYSTICK_initialize(void);
|
||||
uint32_t SYSTICK_millis(void);
|
||||
uint32_t SYSTICK_micros(void);
|
||||
void SYSTICK_delay_ms(uint32_t millis);
|
||||
|
||||
// include header for simulated ADC
|
||||
#include "simul_adc.h"
|
||||
#include "simul_drv_gpio.h"
|
||||
#include "simul_drv_lcd.h"
|
||||
|
||||
|
||||
#endif // SIMUL_KL25Z_H
|
||||
/* Simple simulator for Kinetis KL25Z MCU
|
||||
* Main include file.
|
||||
* Include just this file in your source.
|
||||
* Requires C++11 support.
|
||||
*
|
||||
* Note: to simulate switch input use pinRead() with SW1 - SW4;
|
||||
* Keyboard key '1' is SW1, SW2 is key '2' etc.
|
||||
* Pressing a key toggles the switch On/Off.
|
||||
* So use '1' and '1' to simulate switch SW1 press and release.
|
||||
* This is because holding the key down results in the char being sent
|
||||
* repeatedly to the program - keyboard has autorepeat feature.
|
||||
*/
|
||||
#ifndef SIMUL_KL25Z_H
|
||||
#define SIMUL_KL25Z_H
|
||||
// Note: Include simulator headers at the end of this file
|
||||
// because they need definitions provided here...
|
||||
|
||||
#include "simul_regs.h"
|
||||
|
||||
// Version of the simulator
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 2
|
||||
|
||||
// Enable diagnostic messages
|
||||
#define VERBOSE_INFO 0
|
||||
|
||||
#if VERBOSE_INFO == 1
|
||||
#define PRINT_DGMSG(a) std::cout << a << std::endl
|
||||
#else
|
||||
#define PRINT_DGMSG(a)
|
||||
#endif
|
||||
|
||||
// Global functions
|
||||
void delay(unsigned int mseconds);
|
||||
void delay(void);
|
||||
|
||||
class SIM_Peripheral;
|
||||
class PORT_Peripheral;
|
||||
class ADC_Peripheral;
|
||||
|
||||
extern SIM_Peripheral* SIM;
|
||||
extern PORT_Peripheral* PORTC;
|
||||
extern ADC_Peripheral* ADC0;
|
||||
|
||||
// Universal property with value change handler
|
||||
// from https://stackoverflow.com/questions/9144819/c-function-calling-when-changing-member-value
|
||||
#include <functional>
|
||||
|
||||
template<typename T>
|
||||
class Property {
|
||||
friend class ADC_Peripheral;
|
||||
|
||||
public:
|
||||
Property(std::function<void(T)> callback) : data(), callback(callback) { }
|
||||
|
||||
Property& operator=(const T& newvalue) {
|
||||
data = newvalue;
|
||||
callback(data);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Property& operator|=(const T& newvalue) {
|
||||
data |= newvalue;
|
||||
callback(data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator T() const {
|
||||
return data;
|
||||
}
|
||||
|
||||
private:
|
||||
T data;
|
||||
std::function<void(T)> callback;
|
||||
|
||||
};
|
||||
|
||||
// SIM module
|
||||
class SIM_Peripheral {
|
||||
public:
|
||||
uint32_t SCGC5;
|
||||
uint32_t SCGC6;
|
||||
};
|
||||
|
||||
// Port module
|
||||
class PORT_Peripheral {
|
||||
public:
|
||||
uint32_t PCR[32]; // pin control register
|
||||
};
|
||||
|
||||
// simulate systick driver functions
|
||||
// Functions implemented in simul_kl25z.cpp
|
||||
void SYSTICK_initialize(void);
|
||||
uint32_t SYSTICK_millis(void);
|
||||
uint32_t SYSTICK_micros(void);
|
||||
void SYSTICK_delay_ms(uint32_t millis);
|
||||
|
||||
// include header for simulated ADC
|
||||
#include "simul_adc.h"
|
||||
#include "simul_drv_gpio.h"
|
||||
#include "simul_drv_lcd.h"
|
||||
|
||||
|
||||
#endif // SIMUL_KL25Z_H
|
||||
|
Loading…
Reference in New Issue
Block a user