Hier wird eine dali_init Funktion für zwei Instanzen des DALI stack beschrieben.
Hinweis
Die meisten Teile sind auch in der API-Dokumentation beschrieben.
Zu Beginn der dali_init werden zuerst die Instanzen des Stacks erzeugt. Dann werden weitere Callbacks für den Low Level Treiber initialisiert und danach der Timer gestartet. Damit ist der Treiber einsatzbereit.
/**************************************************************/
/* Variables for two instances of the stack
**************************************************************/
// application controller
dalilib_action_t action;
uint8_t bDaliStackReady;
dalilib_instance_t pDaliStackInstance;
dalilib_cfg_t ctrl_device_config;
// LED DT6-Device
dalilib_action_t actionLED;
uint8_t bDaliStackReadyLED; // for LED
dalilib_instance_t pDaliStackInstanceLED; // for LED
dalilib_cfg_t ctrl_gear_config;
/**************************************************************/
/* initialize the HAL driver and the DALI stack
**************************************************************/
void dali_init(dalill_bus_t* pDalill_bus,dalill_bus_t *pDalill_bus2)
{
dalill_base_t dalill_base;
// For the application controller
pDaliStackInstance = NULL;
bDaliStackReady = 0;
// create new DALI stack instance
pDaliStackInstance = dalilib_createinstance();
if (NULL == pDaliStackInstance)
{ // error
return;
}
// Tell lowleveldriver from this instance of the stack
addInstance(pDalill_bus,pDaliStackInstance);
// create and configure DALI stack as single application controller
dali_create_application_controller_config();
// add Low Level structure to DALI stack instance and vice versa
ctrl_device_config.context = pDalill_bus;
// Only one initial value. This will be overwritten by the loop layer of the ll-Driver
pDalill_bus->context = pDaliStackInstance;
// initialize DALI stack instance
if (R_DALILIB_OK != dalilib_init(pDaliStackInstance , &ctrl_device_config))
{
// error
return;
}
// start DALI stack instance
if (R_DALILIB_OK != dalilib_start(pDaliStackInstance))
{
// error
return;
}
// For the ledDevice
pDaliStackInstanceLED = NULL;
bDaliStackReadyLED = 0;
// create new DALI stack instance
pDaliStackInstanceLED = dalilib_createinstance();
if (NULL == pDaliStackInstanceLED)
{ // error
return;
}
// Tell lowleveldriver from this instance of the stack
addInstance(pDalill_bus,pDaliStackInstanceLED);
// create and configure DALI stack as a LED (DT6-Device)
dali_create_gear_configLED();
// add Low Level structure to DALI stack instance and vice versa
ctrl_gear_config.context =pDalill_bus;
// initialize DALI stack instance
if (R_DALILIB_OK != dalilib_init(pDaliStackInstanceLED , &ctrl_gear_config))
{
// error
return;
}
// start DALI stack instance
if (R_DALILIB_OK != dalilib_start(pDaliStackInstanceLED))
{
// error
return;
}
// initialize callback functions for DALI Low Level Driver
dalill_base.debug_mode = 0;
dalill_base.max_frame_length = 32;
dalill_base.rx_high_offset = 40; // 60 DALI 2 click
dalill_base.rx_low_offset = 40; // 60 DALI 2 click
dalill_base.tx_high_offset = 20; // 35 DALI 2 click
dalill_base.tx_low_offset = 20; // 35 DALI 2 click
// Api functions
dalill_base.dalilltimingHelper = &dalill_timingHelper;
dalill_base.dalilltoDalilib = &dalill_toDalilib;
// funtions in dali_ll_hal.c
dalill_base.getCurrentTimerVal = &dalill_getCurrentTimerVal;
dalill_base.getTimerPeriod = &dalill_getTimerPeriod;
dalill_base.setTimerPeriod = &dalill_setTimerPeriod;
dalill_base.startTimer = &dalill_startTimer;
// It is important to set this to NULL if no signalling is used !!!
// or implement a dummy function in dali_ll_hal.c
dalill_base.signalToThread = &dalill_signalToThread;
// functions to block and release interrupts
// It is important to set this pointer to NULL if not used
dalill_base.enableIRQ = enableIRQ;
dalill_base.disableIRQ = disableIRQ;
// create all data for LL-Driver and start the timer
dalill_createBase(&dalill_base);
}
Die Variablen
int16_t dalill_base.rx_high_offset,
int16_t dalill_base.rx_low_offset,
int16_t dalill_base.tx_high_offset und
int16_t dalill_base.tx_low_offset werden genutzt, um die Schaltzeiten des Interfaces zwischen PCIO und dem DALI-Bus zu kompensieren.
Das ist notwendig, damit der Treiber beim Senden nicht seine eigenen Signale als Kollision interpretiert und sich damit selbst blockiert.
Die Variablen
rx_high_offset und
rx_low_offset dienen zur Steuerung des Empfangsprozesses.
tx_high_offset und
tx_low_offset dienen zur Steuerung des Sendeprozesses.
Die Einheit dieser Variablen ist Mikrosekunden.
Hinweis
Falls erforderlich sind hier auch negative Werte möglich!
Vorgehen zur Einstellung
Hinweis
Die Variablen für die Senderichtung können nur mit Unterstützung eines Dali Tracers oder eines Oszilloskops einstellen werden.
Sendeoffsets
Mit tx_high_offset kann die Zeit verändert werden, in der der Pegel eines Halb-Bits auf LOW bleiben soll. Ist diese Zeit zu kurz, muss der Parameter um die entsprechende Zahl vom Mikrosekunden verkleinert werden.
Mit tx_low_offset kann die Zeit verändert werden, in der der Pegel auf HIGH bleiben soll. Ist diese Zeit zu kurz, muss der Parameter vergrößert werden.
Die Namensgebung der Parameter bezieht sich dabei auf den Wechsel in den Zielzustand HIGH beziehungsweise LOW.
Beispiele
Im folgenden Beispiel sind beide Zeiten zu kurz:
Nach Verkleinerung von tx_high_offset um 10 Mikrosekunden erhält man folgendes Bild:
Nach Vergrößerung von tx_low_offset um 12 Mikrosekunden erhält man folgendes Bild:
Leseoffsets
Die Einstellung der Leseoffsets ist relativ einfach.
Zuerst werden rx_high_offset und rx_low_offset auf den Wert Null gesetzt.
Wenn ein anderes Device sendet, werden mit hoher Wahrscheinlichkeit vom Low Level Treiber Kollisionen gemeldet.
Die Offsets werden dann in 10er Schritten langsam erhöht.
Sobald die Kollisionen aufhören, wird dieser Wert festgehalten. Die Offsets werden dann weiter erhöht bis erneut Kollisionen gemeldet werden.
Der optimale Offset liegt in der Mitte zwischen dem unteren und dem oberen ermitteltem Wert. Damit sollte ein fehlerfreier Empfang möglich sein.
rx_high_offset und rx_low_offset haben normalerweise die gleiche Werte.