118 lines
3.8 KiB
C
118 lines
3.8 KiB
C
/**
|
|
* \file pwm_channels.c
|
|
* \brief Manages the values of the displayed channels.
|
|
* \author Thomas Stegemann
|
|
* \version $Id: pwm_channels.c,v 1.2 2006/09/29 22:30:03 rschaten Exp $
|
|
*
|
|
* License: See documentation.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "pwm_channels.h"
|
|
#include "pwm_timer.h"
|
|
#include "config_pwm_timer_impl.h"
|
|
#include "message_queue.h"
|
|
|
|
/** Structure to contain the state of one channel */
|
|
typedef struct S_pwm_Channels_ChannelBrightness {
|
|
pwm_Channels_Bitfield field; /**< Bitfield resembling one channel */
|
|
pwm_Timer_Cycles cycle; /**< Number of on-cycles */
|
|
} pwm_Channels_ChannelBrightness;
|
|
|
|
/**
|
|
* Initialize channels. Basically, only the PWM-timer is started.
|
|
*/
|
|
void pwm_Channels_init(void) {
|
|
pwm_Timer_init();
|
|
}
|
|
|
|
/**
|
|
* Clean up channels. Basically, the PWM-timer gets cleaned.
|
|
*/
|
|
void pwm_Channels_cleanup(void) {
|
|
pwm_Timer_cleanup();
|
|
}
|
|
|
|
/**
|
|
* Calculate the Channels_Message. Requires the channel-list to be sorted by
|
|
* cycles.
|
|
* \param channels Array of the channels.
|
|
* \return Current message.
|
|
*/
|
|
static pwm_Channels_Message pwm_Channels_Message_get(pwm_Channels_ChannelBrightness channels[CHANNELS]) {
|
|
int j; /* index of the current channel */
|
|
pwm_Channels_StepCounter i= 0; /* index of the current step */
|
|
pwm_Channels_Message message;
|
|
/* first step: switch on all channels at cycle 0 */
|
|
message.step[i].field = 0;
|
|
for (j = 0; j < CHANNELS; j++) {
|
|
message.step[i].field |= channels[j].field;
|
|
}
|
|
message.step[i].cycle= 0;
|
|
|
|
for (j = 0; j < CHANNELS; j++) {
|
|
if(channels[j].cycle == message.step[i].cycle) {
|
|
/* if cycle for this channel is reached
|
|
switch off channel in current step */
|
|
message.step[i].field&= ~channels[j].field;
|
|
} else {
|
|
/* need another step for this channel:
|
|
set end of the current step
|
|
use copy of current step for next step
|
|
and switch off this channel
|
|
*/
|
|
message.step[i].cycle= channels[j].cycle;
|
|
i++;
|
|
message.step[i]= message.step[i-1];
|
|
message.step[i].field&= ~channels[j].field;
|
|
}
|
|
}
|
|
/* last step ends at pwm_Timer_Cycles_Max */
|
|
message.step[i].cycle= pwm_Timer_Cycles_Max;
|
|
return message;
|
|
}
|
|
|
|
/**
|
|
* Calculate number of cycles from a brightness.
|
|
* \param brightness The brightness.
|
|
* \return The number of cycles.
|
|
*/
|
|
pwm_Timer_Cycles pwm_Channels_BrightnessToCycles(pwm_Channels_Brightness brightness) {
|
|
return brightness * brightness;
|
|
}
|
|
|
|
/**
|
|
* Compare the number of cycles in two channels. This is needed for the
|
|
* qsort-call in pwm_Channels_show().
|
|
* \param cmp1 First channel.
|
|
* \param cmp2 Second channel.
|
|
* \return A value <0 if cmp1 is smaller than cmp2, 0 if they are of the same
|
|
* length and a value >0 if cmp1 is larger than cmp2.
|
|
*/
|
|
int pwm_Channels_CompareChannels(const void * cmp1, const void * cmp2) {
|
|
return ((const pwm_Channels_ChannelBrightness*)cmp1)->cycle - ((const pwm_Channels_ChannelBrightness*)cmp2)->cycle;
|
|
}
|
|
|
|
/**
|
|
* Writes the current pattern to the message-queue. The pattern is built from
|
|
* the state of all channels.
|
|
* \param channels Array with the channel-states.
|
|
*/
|
|
void pwm_Channels_show(pwm_Channels channels) {
|
|
int i;
|
|
pwm_Channels_Message message;
|
|
pwm_Channels_ChannelBrightness channel_brightness[CHANNELS];
|
|
for (i = 0; i < CHANNELS; i++) {
|
|
channel_brightness[i].field = 1 << i; // 1 << i equals 2^i: the channel i, uses the bit i
|
|
channel_brightness[i].cycle = pwm_Channels_BrightnessToCycles(channels.channel[i]);
|
|
}
|
|
|
|
qsort(channel_brightness, CHANNELS, sizeof(pwm_Channels_ChannelBrightness), pwm_Channels_CompareChannels);
|
|
message= pwm_Channels_Message_get(channel_brightness);
|
|
while(!messageQueue_write(message)) {
|
|
pwm_Timer_idle();
|
|
}
|
|
}
|
|
|