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();
 | 
						|
    }
 | 
						|
}
 | 
						|
 |