Rev Author Line No. Line
4119 kaklik 1 // Atomic counter with I2C and RS232 output
2  
3 // Usage conditions:
4 // 1. The first I2C or RS232 readout can be performed minimally 20 s after power up.
5 // 2. The I2C internal address 0 has to be read first.
6 // 3. An I2C readout can be performed at 15-th, 35-th and 55-th second of UTC.
7 //
8 // Counter gives 32 bit value:
9 // I2C register address 0 = LSB
10 // I2C register address 3 = MSB
11  
12 #define ID "$Id: main.c 3741 2014-10-25 22:30:12Z kakl $"
13 #include "main.h"
14 #use i2c(SLAVE, Fast, sda=PIN_C4, scl=PIN_C3, force_hw, address=0xA2)
15  
16 #include <string.h>
17  
18 #define LED PIN_B3 // heartbeat indicator
19 #define SEL0 PIN_E0 // external counter division ratio
20 #define SEL1 PIN_E1 // external counter division ratio
21 #define MR PIN_E2 // external counter master reset
22 #define CLKI PIN_C0 // internal counter input
23  
24 unsigned int32 count; // count per second
25  
26 int1 fire_setup; // flag for sending setup to GPS
27  
28 #define BUF_LEN 4
29 int8 buffer[BUF_LEN]; // I2C buffer
30 int8 address=0;
31  
32 unsigned int16 of=0; // count of overflow
33  
34 // 1x 100 us per 10 s UTC synchronised; 40 configuration bytes
35 char cmd[50]={40, 0xB5, 0x62, 0x06, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x80, 0x96, 0x98, 0x00, 0xE0, 0xC8, 0x10, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0xC6, 0x51};
36  
37 // configure GPS
38 void setup_GPS()
39 {
40 int n;
41 int len;
42 len=cmd[0];
43 for (n=1;n<=len;n++) putc(cmd[n]);
44 }
45  
46 #INT_SSP
47 void ssp_interupt ()
48 {
49 int8 incoming, state;
50  
51 state = i2c_isr_state();
52  
53 if(state < 0x80) //Master is sending data
54 {
55 incoming = i2c_read(); // Read byte
56  
57 if(state == 1) //Second received byte is address of register
58 {
59 address = incoming;
60 }
61  
62 if(state == 2) //Thid received byte are configuration data
63 {
64 if ((address==0)&&(incoming==0))
65 {
66 fire_setup = 1; // Write configuration to the GPS if configuration data length is 0
67 }
68 else
69 {
70 cmd[address] = incoming; // Store byte to configuration sentence
71 }
72 }
73 }
74 if(state == 0x80) //Master is requesting data
75 {
76 //i2c_read(); // Dummy read of I2C device address
77  
78 if(address == 0) // Change buffer atomically at reading of the first byte
79 {
80 buffer[0]=make8(count,0);
81 buffer[1]=make8(count,1);
82 buffer[2]=make8(count,2);
83 buffer[3]=make8(count,3);
84 }
85 if(address <= BUF_LEN)
86 {
87 i2c_write(buffer[address]); // Prepare one byte to SSP buffer
88 }
89 else
90 {
91 i2c_write(0x00); // There is nothing to prepare, so zero
92 }
93 }
94  
95 if(state == 0x81) //Master is requesting data
96 {
97 i2c_write(buffer[1]); // Prepare next byte to SSP buffer
98 }
99 if(state == 0x82) //Master is requesting data
100 {
101 i2c_write(buffer[2]); // Prepare next byte to SSP buffer
102 }
103 if(state == 0x83) //Master is requesting data
104 {
105 i2c_write(buffer[3]); // Prepare next byte to SSP buffer
106 }
107  
108 if(state > 0x83) //Master is requesting data
109 {
110 i2c_write(0x00); // There is nothing to prepare, so zero
111 }
112 }
113  
114  
115  
116 #int_EXT // Interrupt from 1PPS (RB0)
117 void EXT_isr(void)
118 {
119 unsigned int16 countH;
120 unsigned int8 countL;
121 int16 of2;
122  
123 of2=of; // read overflow counter
124 countH=get_timer1(); // read internal counter
125 countL=0;
126 output_low(SEL0);
127 output_low(SEL1);
128 countL=input(CLKI); // read bit 0 of external counter
129 output_high(SEL0);
130 // output_low(SEL1);
131 countL|=input(CLKI)<<1; // read bit 1 of external counter
132 output_low(SEL0);
133 output_high(SEL1);
134 countL|=input(CLKI)<<2; // read bit 2 of external counter
135 output_high(SEL0);
136 // output_high(SEL1);
137 countL|=input(CLKI)<<3; // read bit 3 of external counter
138  
139 output_toggle(LED); // heartbeat
140 output_low(MR); // External counter Master Reset
141 output_high(MR);
142 set_timer1(0); // Internal counter reset
143 of=0; // Overflow counter reset
144  
145 count=((unsigned int32)of2<<20)+((unsigned int32)countH<<4)+(unsigned int32)countL; // concatenate
146  
147 // printf("%010Lu\r\n", count);
148 }
149  
150 #int_TIMER1 // Interrupf from overflow
151 void TIMER1_isr(void)
152 {
153 of++;
154 }
155  
156 void main()
157 {
158 setup_adc_ports(NO_ANALOGS|VSS_VDD);
159 setup_adc(ADC_OFF);
160 // setup_spi(SPI_SS_DISABLED); //must not be set if I2C are in use!
161 setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
162 setup_wdt(WDT_2304MS);
163 setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
164 setup_timer_2(T2_DISABLED,0,1);
165 setup_comparator(NC_NC_NC_NC);
166 setup_vref(FALSE);
167  
168 restart_wdt();
169 delay_ms(1000);
170 restart_wdt();
171  
172 // setup GPS
173 setup_GPS();
174  
175 ext_int_edge( L_TO_H ); // set 1PPS active edge
176 enable_interrupts(INT_TIMER1);
177 enable_interrupts(INT_EXT);
178 enable_interrupts(INT_SSP);
179 enable_interrupts(GLOBAL);
180  
181 buffer[0]=0x0; // Clear I2C output buffer
182 buffer[1]=0x0;
183 buffer[2]=0x0;
184 buffer[3]=0x0;
185  
186 //printf("\r\ncvak...\r\n");
187  
188 fire_setup = 0;
189  
190 while(true)
191 {
192 restart_wdt();
193 delay_ms(1000);
194 if (fire_setup)
195 {
196 setup_GPS(); // Write configuration to the GPS
197 fire_setup = 0;
198 }
199 output_toggle(LED); // heartbeat
200 //printf("%X %X %X %X\r\n", buffer[0],buffer[1],buffer[2],buffer[3]);
201 //printf("%010Lu\r\n", count);
202 }
203 }