00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <string.h>
00021
00022 #include <aversive.h>
00023 #include <aversive/parts.h>
00024 #include <aversive/timers.h>
00025
00026 #include "pwm_ng.h"
00027
00028
00029 #define PWM_SIGNIFICANT_BITS 12
00030 #define PWM_MAX ((1<< PWM_SIGNIFICANT_BITS)-1)
00031 #define PWM_MIN (-PWM_MAX)
00032
00033 #define PWM_NG_TYPE_8 0
00034 #define PWM_NG_TYPE_16 1
00035
00036 #define PWM_NG_NBITS_8 0
00037 #define PWM_NG_NBITS_9 1
00038 #define PWM_NG_NBITS_10 2
00039
00040 void pwm_ng_init(struct pwm_ng *pwm, uint8_t timer_nbits,
00041 uint8_t pwm_nbits, uint8_t pwm_mode,
00042 volatile void *ocrn,
00043 uint8_t com0, volatile uint8_t *tccrn,
00044 volatile uint8_t *pwm_port, uint8_t pwm_bit,
00045 volatile uint8_t *sign_port, uint8_t sign_bit)
00046 {
00047 memset(pwm, 0, sizeof(*pwm));
00048
00049 if (timer_nbits == 8) {
00050 pwm->type = PWM_NG_TYPE_8;
00051 pwm->u.ocr8 = ocrn;
00052 *pwm->u.ocr8 = 0;
00053 }
00054 else {
00055 pwm->type = PWM_NG_TYPE_16;
00056 pwm->u.ocr16 = ocrn;
00057 *pwm->u.ocr16 = 0;
00058 }
00059 switch (pwm_nbits) {
00060 case 9:
00061 pwm->nbits = PWM_NG_NBITS_9;
00062 break;
00063 case 10:
00064 pwm->nbits = PWM_NG_NBITS_10;
00065 break;
00066 case 8:
00067 default:
00068 pwm->nbits = PWM_NG_NBITS_8;
00069 break;
00070 }
00071 pwm->mode = pwm_mode;
00072
00073 *tccrn &= ~(0x03 << com0);
00074 if (pwm_mode & PWM_NG_MODE_REVERSE)
00075 *tccrn |= (0x01 << com0);
00076 else
00077 *tccrn |= (0x02 << com0);
00078
00079 DDR(*pwm_port) |= (1 << pwm_bit);
00080
00081 if ((pwm_mode & PWM_NG_MODE_SIGNED) && (sign_port))
00082 DDR(*sign_port) |= (1 << sign_bit);
00083 pwm->sign_port = sign_port;
00084 pwm->sign_bit = sign_bit;
00085 }
00086
00087 static inline void pwm_sign_set(struct pwm_ng *pwm)
00088 {
00089 if (pwm->mode & PWM_NG_MODE_SIGN_INVERTED)
00090 *pwm->sign_port &= ~(1 << pwm->sign_bit);
00091 else
00092 *pwm->sign_port |= (1 << pwm->sign_bit);
00093 }
00094
00095 static inline void pwm_sign_reset(struct pwm_ng *pwm)
00096 {
00097 if (pwm->mode &PWM_NG_MODE_SIGN_INVERTED)
00098 *pwm->sign_port |= (1 << pwm->sign_bit);
00099 else
00100 *pwm->sign_port &= ~(1 << pwm->sign_bit);
00101 }
00102
00103 static inline int32_t pwm_invert_value(struct pwm_ng *pwm, int32_t value)
00104 {
00105 if (pwm->mode & PWM_NG_MODE_SPECIAL_SIGN)
00106 return value & PWM_MAX;
00107 else
00108 return -value;
00109 }
00110
00111 #include <stdio.h>
00112 void pwm_ng_set(void *data, int32_t value)
00113 {
00114 struct pwm_ng *pwm = data;
00115 uint8_t nbits = 8 + pwm->nbits;
00116
00117 MAX(value, PWM_MAX);
00118 if (pwm->mode & PWM_NG_MODE_SIGNED) {
00119 MIN(value, PWM_MIN);
00120 if (value < 0) {
00121 pwm_sign_set(pwm);
00122 value = pwm_invert_value(pwm, value);
00123 }
00124 else {
00125 pwm_sign_reset(pwm);
00126 }
00127 }
00128 else {
00129 MIN(value, 0);
00130 }
00131 if (pwm->type == PWM_NG_TYPE_8)
00132 *pwm->u.ocr8 = (uint8_t) (value >> (PWM_SIGNIFICANT_BITS - 8));
00133 else
00134 *pwm->u.ocr16 = (value >> (PWM_SIGNIFICANT_BITS - nbits));
00135 }
00136