metachris/RPIO — pull request #20 by PaulPenson (2014-02-06 22:52:53+00:00)
Title: Adding low level buffer operations ro RPIO.PWM

This change adds functionality that allows the assignment of individual GPIO channel commands to the DMA ring buffer. This allows pulses length to be changed with minimal cost.

Below is an example python usage, it demonstrates a single dma channel being used to control 9 channels of PWM output [three banks of RGB leds]. The LED color can be faded with no flickers or glitches, and there is a minimal cost to change the pulse width. The on and off commands are pre-setup to allow each of the channels to start at a different phase of the cycle to reduce the current surge.

The on instructions are at fixed positions so that we do no attempt to reassign them to off instructions.

from RPIO import PWM

class LightController:
dmachannel = 0
channels = [24,23,25,15,18,14,9,11,10]
starts = [0,333,666,999,1332,1665,1998,2331,2664]
lastPos = [0,333,666,999,1332,1665,1998,2331,2664]

def __init__(self):
PWM.set_loglevel(PWM.LOG_LEVEL_ERRORS)
PWM.setup(1,PWM.DELAY_VIA_PCM)
PWM.init_channel(self.dmachannel,3000)
for x in range(self.dmachannel, 2999):
PWM.buffer_set_off(self.dmachannel,x)
for p in self.starts:
PWM.buffer_set_on(self.dmachannel,p)
self.setcolor(0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1)
self.setcolor(0,0,0,0,0,0,0,0,0)

def setchannel( self, index, brightness ):
start = self.starts[index]
channel = self.channels[index]
last = self.lastPos[index]
end = start + int((brightness**2)*2999)
if end>=3000:
end -= 3000
if end!=start:
for p in self.starts:
if end==p:
end = end+1
if end!=last:
PWM.buffer_assign(self.dmachannel,channel,end)
if last==start:
PWM.buffer_assign(self.dmachannel,channel,start)
else:
PWM.buffer_unassign(self.dmachannel,channel,last)
else:
if last!=start:
PWM.buffer_unassign(self.dmachannel,channel,start)
PWM.buffer_unassign(self.dmachannel,channel,last)
self.lastPos[index]=end

def setcolor( self, r1, g1, b1, r2, g2, b2, r3, g3, b3 ):
self.setchannel(0,r1)
self.setchannel(1,g1)
self.setchannel(2,b1)
self.setchannel(3,r2)
self.setchannel(4,g2)
self.setchannel(5,b2)
self.setchannel(6,r3)
self.setchannel(7,g3)
self.setchannel(8,b3)