Advertisement
Harry_L

8bit PWM w. n SRs

Mar 19th, 2019
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.51 KB | None | 0 0
  1. /*
  2.  * pwm8.c
  3.  *
  4.  *  Created on: 10.03.2019
  5.  *      Author: harry
  6.  */
  7.  
  8. #include "avr/io.h"
  9. #include <avr/interrupt.h>
  10. #include "pwm8.h"
  11.  
  12. #define LED_NUM     8               // must be a multiple of 8
  13. #define SR_NUM      (LED_NUM / 8)
  14.  
  15. #define DEBUG
  16.  
  17. #define LATCH_PIN   PB1     // STCP
  18. #define OE_PIN      PB2     // OE
  19. #define MOSI_PIN    PB3     // Din
  20. #define CLK_PIN     PB5     // SHCP
  21.  
  22. #define PORT_DIR    DDRB
  23. #define LED_PORT    PORTB
  24.  
  25. #define LATCH()     LED_PORT |= (1 << LATCH_PIN),LED_PORT &= ~(1 << LATCH_PIN)
  26.  
  27. #ifdef DEBUG
  28. #define TRIGGER_PIN PD2     // Debug-pin for triggering
  29. #define TRIGGER_DIR DDRD
  30. #define TRIGGER_PORT    PORTD
  31. #define TRIGGER()   TRIGGER_PORT ^= (1 << TRIGGER_PIN) //,PULSE_PORT &= ~(1 << TRIGGER_PIN)
  32. #endif
  33.  
  34. #define TIM_BSY()   tim_bsy = TRUE
  35. #define TIM_RDY()   tim_bsy = FALSE
  36. #define SPI_BSY()   spi_bsy = TRUE
  37. #define SPI_RDY()   spi_bsy = FALSE
  38.  
  39. /*
  40.  * timingg-setting
  41.  */
  42. #define DEADTIME    24
  43.  
  44. static volatile uint8_t pwm_buf[SR_NUM][8];
  45.  
  46. static volatile uint8_t tim_bsy = FALSE;
  47. static volatile uint8_t spi_bsy = FALSE;
  48. static volatile uint8_t bit_cnt = 0;
  49. static volatile uint8_t sr_cnt;
  50. static volatile uint8_t dummy;
  51.  
  52. /*
  53.  * Public Functions
  54.  */
  55. void pwm8Init(void)
  56. {
  57.     // Initialize GPIOs
  58.     PORT_DIR |= ((1 << LATCH_PIN) | (1 << OE_PIN)
  59.              | (1 << MOSI_PIN) | (1 << CLK_PIN));   // define Outputs
  60.     LED_PORT &= ~((1 << LATCH_PIN) | (1 << OE_PIN));    // Reset Latch and OE
  61.  
  62. #ifdef DEBUG
  63.     TRIGGER_DIR |= (1 << TRIGGER_PIN);
  64. #endif
  65.  
  66.     // Initialize SPI
  67.     SPCR = (1 << SPIE) | (1 << SPE) | (1 << MSTR);  // enable SPI
  68.     dummy = SPSR;   // clear pending interrupts
  69.     dummy = SPDR;
  70.  
  71.     // Initialize Timer
  72.     TCCR1A = (1 << COM1B1) | (1 << WGM11);
  73.     TCCR1B = (1 << WGM12) | (1 << WGM13)
  74.             | (1 << CS11);      // fast PWM-Mode
  75.     TCNT1 = 0;
  76.     GTCCR = ((1 << PSRSYNC) | (1 << TSM) | (1 << PSRASY));  // disable & synchronize prescaler
  77.  
  78.     TIFR1 = (1 << OCF1B);   // clear any pending interrupt
  79.     TIMSK1 = (1 << ICIE1);  // enable OC0A interrupt
  80.     sei();
  81.  
  82.     // Start first SPI-transfer
  83.     sr_cnt = 0;
  84.     SPDR = pwm_buf[sr_cnt][bit_cnt];
  85.     SPI_BSY();
  86. }
  87.  
  88. /*
  89.  * Set LED Nr. lednr
  90.  * to PWM-Value pwm_val
  91.  */
  92. void pwm8SetLED(uint8_t lednr, uint8_t pwm_val)
  93. {
  94. uint8_t pwm_mask, led_mask;
  95. uint8_t sr, ln;
  96.  
  97.     sr = lednr >> 3;
  98.     ln = lednr & 0b000001111;
  99.     pwm_mask = 1;
  100.     led_mask = 1 << ln;
  101.     for (uint8_t i = 0; i < 8; i++)
  102.     {
  103.         if ((pwm_val & pwm_mask) == 0)
  104.         {
  105.             pwm_buf[sr][i] = pwm_buf[sr][i] | led_mask;
  106.         }
  107.         else
  108.         {
  109.             pwm_buf[sr][i] = pwm_buf[sr][i] & ~led_mask;
  110.         }
  111.         pwm_mask <<= 1;
  112.     }
  113. }
  114.  
  115. /*
  116.  * Private Functions
  117.  */
  118.  
  119.     // stat next Cycle
  120. static void pwm8KickCycle(void)
  121. {
  122.  
  123.     LATCH();    // enable new data
  124. #ifdef DEBUG
  125.     if (bit_cnt == 0)
  126.         TRIGGER();
  127. #endif
  128.  
  129.     // setup one-pulse-timer
  130.     ICR1 = (1 << bit_cnt) + DEADTIME;
  131.     OCR1B = DEADTIME;
  132.  
  133.     TCNT1 = 0;
  134.     GTCCR = 0;              // enable Prescaler and start Timer
  135.     TIM_BSY();              // timer running
  136.  
  137.     bit_cnt = (bit_cnt +1) & 0b00000111; // advance to next cycle
  138.     SPDR = pwm_buf[0][bit_cnt]; // send next pattern in advance
  139.     SPI_BSY();              // SPI running
  140. }
  141.  
  142. /*
  143.  * Interrupts
  144.  *
  145.  */
  146.     // SPI-Interrupt
  147. ISR( SPI_STC_vect )
  148. {
  149.     dummy = SPDR;
  150.     if (++sr_cnt == SR_NUM)
  151.     {
  152.         SPI_RDY();
  153.         sr_cnt = 0;
  154.         if (tim_bsy == FALSE)
  155.             pwm8KickCycle();        // in this special case, where the
  156.                                     // SPI-transfer takes longer than the timer-cycle
  157.     }
  158.     else
  159.     {
  160.         SPDR = pwm_buf[sr_cnt][bit_cnt];
  161.     }
  162. }
  163.  
  164.      // Timer Interrupt
  165. ISR( TIMER1_CAPT_vect )
  166. {
  167.     GTCCR = (1<<TSM) | (1<<PSRASY) | (1<<PSRSYNC); // halt all timers
  168.     TIM_RDY();
  169.     if (spi_bsy == FALSE)
  170.         pwm8KickCycle();
  171. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement