Hello, and welcome to the forum.
Note that for a PPM signal, the gap width will indicate the current bit state, and there will be one more pulse than there are gaps. It is unclear whether you need 32 gaps and 33 pulses, or 33 gaps and 34 pulses. I suspect it is the first combination. So the overall PPM sequence may be perceived as a "start" pulse, followed by the required number of gap-pulse combinations, or alternatively as the required number of pulse-gap combinations, followed by an "end" pulse.
The use of PWM mode to generate this signal has difficulties because of the coherency mechanism associated with altering the TPM1MOD setting. The TPM1MOD value will not be updated until just prior to overflow occurring (and the pulse output going high), just prior to the next output pulse. Additionally, the update of TPM1MOD will need to be synchronised for each bit, requiring that an interrupt occur every TPM overflow period.
A simpler process for the data synchronisation, would be to make use of output compare mode for a free-running TPM module, with the penalty of twice as many interrupts - one for each pulse edge. With this method, the TPM1C0V setting provides the delay to the next edge, whether positive or negative.
I also have a general comment - the code will be more efficient for a 8-bit MCU, if 'unsigned char' (or 'byte') sized variables are used, rather than 'unsigned int', where the smaller size will suffice. For your constant tables, this will also halve the storage space required.
The following code snippet example demonstrates the use of output compare mode. It uses 33 pulse-gap combinations, as set by the macro BITMAX, followed by an "end" pulse to terminate the sequence.
// Global variables:volatile byte *gp; // Global pointer to pulse sequence datavolatile byte flag; // Pulse sequence complete flagconst byte Mode[] = { 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1 };const byte SeekPlus[] = { 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1 };const byte SeekMinus[] = { 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1 };const byte VolumePlus[] = { 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1 };const byte VolumeMinus[] = { 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1 };// Function prototypes:void start_seq( byte *p);
// Timing values, assuming TPM1 clock is 1 MHz#define PULSEW 565#define GAPW_0 1125#define GAPW_1 2250#define BITMAX 33 // Number of gaps in pulse sequence/***********************************************************************/// Start pulse output sequence// On entry, p points to the start of the required sequence datavoid start_seq( byte *p){ // Wait for completion of previous sequence while (flag) __RESET_WATCHDOG(); flag = 1; // Commence new sequence gp = p; // Initialise global pointer TPM1C0V += 10; // Arbitrary delay to first pulse of sequence TPM1C0SC_CH0F = 0; // Ensure flag is clear TPM1C0SC = 0x5C; // Set channel output on next compare}/***********************************************************************/// ISR functions:// TPM1 module, channel 0:__interrupt VectorNumber_Vtpm1ch0 void ISR_TPM1CH0( void){ static byte i = 0; // Bit (gap) counter TPM1C0SC_CH0F = 0; // Clear flag if (TPM1C0SC_ELS0A) { // Channel output last set (start of pulse) TPM1C0V += PULSEW; // Next compare at end of pulse TPM1C0SC = 0x58; // Clear output on next compare } else { // Channel output last cleared (gap period) if (i < BITMAX) { // Sequence not yet complete if (*gp) // Next logic 1 TPM1C0V += GAPW_1; else // Next logic 0 TPM1C0V += GAPW_0; gp++; i++; TPM1C0SC = 0x5C; // Set output on next compare } else { // Pulse sequence is complete TPM1C0SC = 0x00; // Disable further interrupts i = 0; // Ready for next sequence flag = 0; // Flag completion } }}
You may start a PPM sequence with the following invocation example. The cast avoids a compiler warning message because the data pointed is 'const'.
start_seq( (byte *)SeekPlus);
If the actual data sequence happened to consist of 32 bits, each sequence could be expressed as a 32-bit value, greatly compressing the constant data. Obviously this would need a different method to access each bit value.
Regards,
Mac