-
Notifications
You must be signed in to change notification settings - Fork 0
/
dac.c
177 lines (135 loc) · 4.5 KB
/
dac.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#include <p18f2523.h>
#include <spi.h>
#define DAC_CS LATCbits.LATC2
#define SET_TIMER0(t) TMR0H = (t>>8); TMR0L = (t&0xff)
#define SET_TIMER1(t) TMR1H = (t>>8); TMR1L = (t&0xff)
unsigned char V_dac_val_1[4];
unsigned char V_dac_val_2[4];
unsigned char I_dac_val_1[4];
unsigned char I_dac_val_2[4];
char dac_dither_pos = 0;
unsigned int _timer1_val;
unsigned int _current_tick = 0;
unsigned int _line_frequency = 0;
unsigned int get_line_frequency(void)
{
return _line_frequency;
}
void write_dac_V(int val)
{
unsigned int dac_val = 0, dac_val2 = 0;
char dac_lsb = 0, x = 4;
dac_lsb = val&0x3;
dac_val = (val >> 2);
dac_val2 = dac_val + 1;
// Stop the timer interrupts from updating the DAC
PIE1bits.TMR1IE = 1; // Enable interrupts on this timer (terminal count of ZERO)
PIR1bits.TMR1IF = 0; // Clear interrupt flag (just in case)
do {
x--;
if(dac_lsb >= x)
{
V_dac_val_1[x] = 0x10 + ((dac_val2 & 0x0f00) >> 8);
V_dac_val_2[x] = dac_val2 & 0xff;
}
else
{
V_dac_val_1[x] = 0x10 + ((dac_val & 0x0f00) >> 8);
V_dac_val_2[x] = dac_val & 0xff;
}
} while(x);
dac_dither_pos = 0;
PIE1bits.TMR1IE = 1; // Enable interrupts on this timer (terminal count of ZERO)
SET_TIMER1(_timer1_val);
}
void write_dac_I(int val)
{
unsigned int dac_val = 0, dac_val2 = 0;
char dac_lsb = 0, x = 4;
dac_lsb = val&0x3;
dac_val = (val >> 2);
dac_val2 = dac_val + 1;
// Stop the timer interrupts from updating the DAC
PIE1bits.TMR1IE = 1; // Enable interrupts on this timer (terminal count of ZERO)
PIR1bits.TMR1IF = 0; // Clear interrupt flag (just in case)
do {
x--;
if(dac_lsb >= x)
{
I_dac_val_1[x] = 0x90 + ((dac_val2 & 0x0f00) >> 8);
I_dac_val_2[x] = dac_val2 & 0xff;
}
else
{
I_dac_val_1[x] = 0x90 + ((dac_val & 0x0f00) >> 8);
I_dac_val_2[x] = dac_val & 0xff;
}
} while(x);
dac_dither_pos = 0;
PIE1bits.TMR1IE = 1; // Enable interrupts on this timer (terminal count of ZERO)
SET_TIMER1(_timer1_val);
}
void spi_init(void)
{
// Emsure that our DAC chip select is high
DAC_CS = 1;
// Open our SPI pheripheral
OpenSPI(SPI_FOSC_4, MODE_00, SMPEND);
write_dac_V(0);
write_dac_I(0);
_timer1_val = 63780; // We are generating 1000 interrupts per second
// on the high speed timer which means our dither
// rate is 250 cycles per second with tro bit
// resolution.
// This is also used to calculate the 50/60Hz line
// frequency so it needs to be as close to 1Khz as
// possible
// Enable Timer 1, 16bit mode, prescale @ 1:1, 100ns per tick-the highest resolution we can get running
// the MCU @ 40MHz (HS4)
T1CON = 0x85; // 16bit, 1:1 Prescale, No Osc, No TSync, Fosc/4 Clk Src, Enabled (10000101b)
PIR1bits.TMR1IF = 0; // Clear interrupt flag (just in case)
IPR1bits.TMR1IP = 1; // Make interrupts high priority
PIE1bits.TMR1IE = 1; // Enable interrupts on this timer (terminal count of ZERO)
SET_TIMER1(_timer1_val);
}
void high_pri_interrupt_handler(void);
#pragma code _hi_pri_interrupt = 0x8
void _hi_pri_interrupt(void)
{
_asm goto high_pri_interrupt_handler _endasm
}
#pragma code
#pragma interrupt high_pri_interrupt_handler
void high_pri_interrupt_handler(void)
{
unsigned char x;
if(PIR1bits.TMR1IF)
{
// Re-start the timer with teh current timer value
SET_TIMER1(_timer1_val);
// We have a high speed timer (TIMER1) interrupt, reset the flag ready for the next one
PIR1bits.TMR1IF = 0;
LATCbits.LATC0 = 0;
DAC_CS = 0;
WriteSPI(V_dac_val_1[dac_dither_pos]);
WriteSPI(V_dac_val_2[dac_dither_pos]);
DAC_CS = 1;
DAC_CS = 0;
WriteSPI(I_dac_val_1[dac_dither_pos]);
WriteSPI(I_dac_val_2[dac_dither_pos]);
DAC_CS = 1;
dac_dither_pos++;
dac_dither_pos &= 0x3;
LATCbits.LATC0 = 1;
_current_tick++;
}
else
if(INTCONbits.INT0F)
{
// Clear the falg, ready for next one
INTCONbits.INT0F = 0;
// _current_tick is incremented 10 times every second
_line_frequency = _current_tick * 5;
_current_tick = 0;
}
}