file: channel.c

/* * This file contains the "channel" software module. It contains the * data structures and C functions that maintain and modify the DMX-512 * channel values. This module uses a repetitive timer to update the * DMX-512 channels every 50ms. This module also performs dimming * operations. */ # define __KERNEL__ #endif # define MODULE #endif #define __NO_VERSION__ #include <linux/module.h> #include <linux/version.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/sched.h> #include <linux/timer.h> #include <asm/param.h> #include <asm/system.h> /* local definitions */ #include "slh.h" /* prevent symbols from this file from * being accessed by any part of the * kernel outside of this driver. */ EXPORT_NO_SYMBOLS; /* interval timer in milliseconds */ #define TMR_INTERVAL 50 /* interval timer in clock ticks */ #define TMR_TICKS (HZ*TMR_INTERVAL/1000) /* DMX-512 channel status */ typedef struct { /* total amount channel is to change with dim */ long delta; /* current number of timer expirations into dim */ unsigned long tick; /* total number of timer expirations in dim */ unsigned long total_ticks; /* channel value at start of dim */ unsigned long start_value; /* current channel value */ unsigned long current_value; } CHAN_STATUS; CHAN_STATUS chan_status[NUM_DMX_CHANS]; /* "is the timer running?" flag */ static unsigned long timer_running; /* kernel timer structure */ static struct timer_list slh_timer; int slh_channel_mod_init() { /* initialize the "channel" software module * (called when the slh driver is loaded). */ /* zero the channel status structure */ memset( (void *)chan_status, 0, sizeof(chan_status) ); /* zero the kernel timer structure */ memset( (void *)&slh_timer, 0, sizeof(slh_timer) ); timer_running = 0; return ( 0 ); } void slh_channel_mod_cleanup() { /* cleanup the "channel" software module * (called when the slh driver is unloaded). */ /* stop the channel timer (if running) */ slh_channel_timer_stop(); } void slh_channel_dim( unsigned long chan, unsigned long new_value, unsigned long transition ) { /* dim a DMX-512 channel */ register CHAN_STATUS *stat; unsigned long flags; /* validate the DMX-512 channel number (it must be 1 -> 512) */ if ( (chan == 0) || (chan > NUM_DMX_CHANS) ) { return; } /* block interrupts */ save_flags( flags ); cli(); /* update channel data */ stat = &chan_status[ chan - 1 ]; stat->delta = new_value - stat->current_value; stat->tick = 0; stat->total_ticks = transition / TMR_INTERVAL; stat->start_value = stat->current_value; #if 0 new_value, stat->delta, stat->current_value, stat->start_value); #endif /* allow interrupts */ restore_flags( flags ); } void slh_channel_timeout( unsigned long data ) { /* When the kernel timer expires, this function is called. * It will perform dimmer calculations, update channel data, * start the SoundLight board to send the DMX-512 channel data, * and restart the kernel channel timer. */ register unsigned long i; register CHAN_STATUS *stat; timer_running = 0; /* set the channel status pointer */ stat = &chan_status[0]; /* The 1512b board requires at least one channel be * set before it will transmit the DMX channel data... * so we will always set channel 0. */ slh_board_chan_set( 0, stat->current_value ); /* loop through the channel status structure looking for * channels currently being dimmed. */ for ( i = 0; i < NUM_DMX_CHANS; i++, stat++ ) { /* check if channel is being dimmed */ if ( stat->delta == 0L ) { continue; } /* increment the count of timer expirations * for this channel being dimmed. */ stat->tick += 1; /* check if this is an immediate or gradual * change to the new channel value */ if ( stat->total_ticks ) { /* gradual change */ stat->current_value = stat->start_value + (long) (stat->tick * stat->delta) / (long)stat->total_ticks; } else { /* immediate change */ stat->current_value = stat->start_value + stat->delta; } /* set channel value */ slh_board_chan_set( i, stat->current_value ); /* check if the dim is complete */ if ( stat->tick >= stat->total_ticks ) { stat->delta = 0; } } /* end for ( ... ) */ /* start board DMX-512 transmitter */ slh_board_start(); /* start timer */ slh_channel_timer_start(); } void slh_channel_timer_start() { /* start kernel channel timer */ if ( timer_running ) { return; } timer_running = 1; /* initialize timer */ init_timer( &slh_timer ); slh_timer.function = slh_channel_timeout; slh_timer.data = 0; slh_timer.expires = jiffies + TMR_TICKS; /* start timer */ add_timer( &slh_timer ); } void slh_channel_timer_stop() { /* stop kernel channel timer */ if ( !timer_running ) { return; } del_timer( &slh_timer ); timer_running = 0; } int slh_channel_load() { /* load all channel values to SoundLight board */ register unsigned long i; register CHAN_STATUS *stat; unsigned long flags; /* block interrupts */ save_flags( flags ); cli(); for ( i = 0, stat = chan_status; i < NUM_DMX_CHANS; i++, stat++ ) { /* set channel value */ slh_board_chan_set( i, stat->current_value ); } /* end for ( ... ) */ /* allow interrupts */ restore_flags( flags ); return ( 0 ); } void slh_channel_read( unsigned char *buffer ) { /* read into a buffer all current channel values */ register unsigned long i; register CHAN_STATUS *stat; unsigned long flags; /* block interrupts */ save_flags( flags ); cli(); for ( i = 0, stat = chan_status; i < NUM_DMX_CHANS; i++, stat++ ) { /* save channel value */ *buffer++ = stat->current_value; } /* end for ( ... ) */ /* allow interrupts */ restore_flags( flags ); }


Back to Source File Index


C++ to HTML Conversion by ctoohtml