On Sat, 29 Aug 2015, Josh Koffman wrote: > Hi Sergio, > > That's pretty similar to what I've sketched out in many parts. I > haven't tried mine as I'm waiting on PCBs. I do have a few questions > though: > >> // from what I've read, there is no advantage to storing >> // chan_buff[][7] as BAM_buff[0] so using left shifts in the >> // following code just makes things much more complicated for >> // no added benefit > > I don't understand this comment. Do you mean using left shifts at all, > or just in the init section? Hi Josh, In my code the "mask" is left shifted which is equivalent to right=20 shifting the BAM "value" out onto the BAM "channel" (i.e. least sig bit=20 first, most sig bit last). i.e. instead of if ((val & 1) =3D=3D 0) { bit =3D 0; } else { bit =3D 1; } val =3D val >> 1; I have used mask =3D 1; if ((val & mask) =3D=3D 0) { bit =3D 0; } else { bit =3D 1; } mask =3D mask << 1; The comment is a "global" comment refering to the overall process of=20 shifting the BAM value out of the BAM channel in either left or right=20 direction (i.e. MSB or LSB). I have chosen to use "right shift out" (LSB)=20 and do not think it is appropriote to comment all the points in the code=20 where changes should occure to allow for "left shift out" (MSB). I feel=20 doing so would just clutter the code. > >> void set_channel_value(unsigned char indx, unsigned char val) >> { > >> // disable interrupts >> di(); >> >> BAM_PORT =3D BAM_buff[bit_pos]; >> >> // enable interrupts >> ei(); >> } > > Why are you stuffing the output port in the set_channel_value() > function? I would have thought it should only happen in the ISR? > I have done this because in some cases there would be a large delay=20 between changing the BAM value and it being updated correctly on the BAM=20 channel. Consider the case where the BAM is on tick 128, the current=20 BAM value is 0x80 and you change the BAM value to 0x00. It will now take=20 at least 127 ticks for the BAM channel to change from 1 to the new value=20 0. >> if (bit_cnt =3D=3D 0) >> { >> // don't calculate bit_mask from bit_pos in the ISR as >> // as variable shifts are expensive and unnecessary in >> // this case >> >> if ((bit_mask & 0x80) =3D=3D 0) >> { >> bit_mask <<=3D 1; >> bit_pos++; >> } >> else >> { bit_mask =3D 1; >> bit_pos =3D 0; >> } >> >> bit_cnt =3D bit_mask; >> >> // I'm assuming the output pins are defined as a group a= t compile time >> >> BAM_PORT =3D BAM_buff[bit_pos]; >> } > > Ok, I understand that you're using a counter variable to know when to > trigger the next output. I need to reread this a few more times to get > a handle on the logic, but I get that you are essentially comparing a > mask to a counter as you're calling the BAM ISR routine based on a > regular timer interrupt. >From what I have read, the BAM value gets shifted out onto the BAM channel= =20 using a clock tick which is essentially 2^n (read that as 2 to the power=20 n). Here, 2^n can be calculated in C as: pow2 =3D 1 << n; which is equivalent to "bit_mask" which is calculated as bit_mask =3D 1 << bit_pos; to make the code more efficent "bit_mask" is calculated based on the=20 previous value of "bit_pos" and "bit_mask". i.e. "bit_pos" starts at 0 and "bit_mask" starts at 1 (which is the same=20 as saying) bit_pos =3D 0; bit_mask =3D 1 << bit_pos; when "bit_pos" changes, the result is: new_bit_pos =3D bit_pos + 1; new_bit_mask =3D 1 << (bit_pos + 1); bit_pos =3D new_bit_pos; bit_mask =3D new_bit_mask; after a lot of juggling we can rewrite it as: new_bit_pos =3D bit_pos + 1; new_bit_mask =3D (1 << bit_pos) << 1; bit_pos =3D new_bit_pos; bit_mask =3D new_bit_mask; and if we preserve "bit_mask" between calls: new_bit_pos =3D bit_pos + 1; new_bit_mask =3D bit_mask << 1; bit_pos =3D new_bit_pos; bit_mask =3D new_bit_mask; or: bit_pos =3D bit_pos + 1; bit_mask =3D bit_mask << 1; In retrospect, perhaps "bit_mask" should be renamed "bit_pow2". The "if ((bit_mask & 0x80) =3D=3D 0)" is just an efficent way of checking if the last bit of the BAM value has finished being output. > I was considering dedicating a timer to this, > and loading specific values into it. It means my ISRs will be longer, > but it does mean I can tune the timings a bit more. I'm not entirely > sure which is the best way to go to be honest. I think this really depends on what you are using this BAM thing for. From= =20 "full off" to "full on" with a smooth increment of "one" per BAM cycle=20 will take 255 * 256 ticks. To do this over a period of 1 second means you=20 would need about 64k ticks (interrupts) per second. Given the simple ISR=20 as I have shown, this high interrupt rate should be easily achiveable. If you decide to use different tick periods depending on the bit being=20 output, you could always have a simple lookup table that would contain the= =20 next interrupt timer value depending on the bit being output. However you=20 would still need to ensure that the minumum timer period (tick between n=3D= 0=20 and n=3D1) is achiveable. Regards Sergio Masci --=20 http://www.piclist.com/techref/piclist PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist .