From the ATtiny85 Datasheet:
The mode of operation, i.e., the behavior of the Timer/Counter and the
Output Compare pins, is defined by the combination of the Waveform
Generation mode (WGM0[2:0]) and Compare Output mode (COM0x[1:0]) bits.
The Compare Output mode bits do not affect the counting sequence,
while the Waveform Generation mode bits do. The COM0x[1:0] bits
control whether the PWM output generated should be inverted or not
(inverted or non-inverted PWM).
Table 11-5 shows how to set the Mode.
Mode WGM WGM WGM Timer/Counter Mode TOP Update of TOV Flag
c0 02 01 00 of Operation OCRx at Set on
==========================================================================
0 0 0 0 Normal 0xFF Immediate MAX(1)
1 0 0 1 PWM, Phase Correct 0xFF TOP BOTTOM
2 0 1 0 CTC OCRA Immediate MAX
3 0 1 1 Fast PWM 0xFF BOTTOM MAX
4 1 0 0 Reserved – – –
5 1 0 1 PWM, Phase Correct OCRA TOP BOTTOM
6 1 1 0 Reserved – – –
7 1 1 1 Fast PWM OCRA BOTTOM TOP
You want a Fast PWM mode (so either mode 3 or mode 7). If you want to vary the duty cycle, and it sounds like you do, you want mode 7 and vary duty cycle by setting OCRA.
Table 11-3 shows how to set the compare output mode for Fast PWM mode.
COM0A1/ COM0A0/
COM0B1 COM0B0 Description
===============================================================================
0 0 Normal port operation, OC0A/OC0B disconnected.
0 1 Reserved
1 0 Clear OC0A/OC0B on Compare Match, set OC0A/OC0B at BOTTOM
(non-inverting mode)
1 1 Set OC0A/OC0B on Compare Match, clear OC0A/OC0B at BOTTOM
(inverting mode)
That is to say, you can set the OC0A output to go low when the Timer value == OCR0A and high when the Timer value == 0x00 by setting COM0A1:COM0A0 = 0b10. Or vise versa by setting COM0A1:COM0A0 = 0b11. And likewise for OC0B, OCR0B, COM0B0, COM0B1.
The PWM frequency is determined by the I/O Clock (8MHz it sounds like for you) and your timer prescaler setting. And the equation is given as f_clk_IO / (N * 256) for Fast PWM mode.
So you can use OC0A for "normal" polarity and OC0B for "inverted" polarity by setting OCR0A and OCR0B to the same value and setting COM0A1:COM0A0 = 0b10 and COM0B1:COM0B0 to 0b11.
UPDATE
Given you want to toggle the output as fast as possible and you are using the Mega328 operating at 16MHz, the CTC operating mode will allow you to obtain a switching frequency of:
f_OCnA = f_clk_IO / (2 * N * [1 + OCRnA) = 16e6 / (2 * 1 * [1 + 1]) = 4MHz
The Fast PWM mode will let you toggle the pin at:
f_OCnxPWM = f_clk_IO / (N * [1 + TOP]) = 16e6 / (1 * [1 + 1]) = 8MHz
So I still think you want Fast PWM mode. Specifically Mode 3 with OCR0A = OCR0B = 0x80 for 50% duty cycle. And set COM0A bits to 0x3 and COM0B bits to 0x2 to make the two waveforms on OC0A and OC0B inversions of one another.
Update #2
More the Mega328 Try this Arduino code:
#define tick 9
#define tock 10
void setup(){
pinMode(tick, OUTPUT);
pinMode(tock, OUTPUT);
// Setup Waveform Generation Mode 15
// OC1A Compare Output Mode = inverting mode
// OC1B Compare Output Mode = non-inverting mode
// Timer Prescaler = 1
// TOP = OCR1A = 1
//COM1A[1:0] = 0b11, COM1B[1:0] = 0b10, WGM1[1:0] = 0b11
TCCR1A = _BV(COM1A1) | _BV(COM1A0) | _BV(COM1B1) | _BV(WGM11) | _BV(WGM10);
//WGM1[3:2] = 0b11, CS1[2:0] = 0b001
TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);
OCR1A = 0x0001;
OCR1B = 0x0001;
}
void loop(){
}
Best Answer
So the idea is to drive the grayscale clock (GSCLK) from the ATtiny, and everything else from the R-Pi?
Driving the TLC5940 with two different sources does not look impossible to get working.
However it will likely create extra complexity. Debugging the source of an error may be very challenging. As this is your first major electronics project, I'd recommend making it easy to get working, and then make it better.
I think I might be somewhat concerned about using the R-Pi for such a complex timing-sensitive device too. (As you have identified, the interaction between the grayscale clock and blanking signals seems complex, though with experiments it might actually be simpler in practice)
However, if you already have one, I would try the R-Pi and see. Do this initially without using grayscale, as that removes the ATtiny's role, and so it will implement everything else. IIRC there is a simple PWM generator on a R-Pi. It takes a bit pattern, and shifts that out to produce some sort of square wave.
If the R-Pi wasn't good enough, or you haven't got one already, I would suggest a cheap Arduino Nano clone from one of the well-know shopping sites (not Arduino Mini, which is lacking USB, unless you already have a USB-to-serial converter).
The Arduino has enough pins to drive everything, so there is only one place to debug.
Programming an Arduino will be easier than an ATtiny, and there are lots more people who might help if you have problems.
Once the system is working, and if you are still determined to implement your original approach, you could still reverse back to your initial idea, using the Arduino to play the ATtiny's role. Once that works, swap out the Arduino, and use the ATtiny.
This might seem more complex than your original plan. However, being able to implement a project in smaller stages, and get each stage working, with debuggable pieces, can significantly reduce the time to complete everything.
Edit:
If low-cost is part of what interests you, and you plan to do several projects in this area, consider getting a USB-to-serial converter. Then you can use Arduino Mini clones, which are available for under £2/€2/$2.50. It would be pretty hard to make something using retail price ATtiny's and components at lower-cost. The mini is easier to program than an ATtiny, and has a lot more resources. Even if all you use it for is a square wave generator and a bit of logic, it is economical, flexible, quick-to-use and well supported.
If low-cost is part of the interest, I might look for something lower-cost than TL5940 (though they are surprisingly low-cost), and do some of its functions (e.g. grayscale) in the Arduino. However, try to keep the project easy to do in small steps.
I wouldn't use an R-Pi, unless there is more to the projects than you have described in your question.