Rev Author Line No. Line
3470 kakl 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  
3463 kaklik 12 #define ID "$Id: main.c 2916 2013-04-14 17:42:03Z kaklik $"
3458 kaklik 13 #include "main.h"
3463 kaklik 14 #use i2c(SLAVE, Fast, sda=PIN_C4, scl=PIN_C3, force_hw, address=0xA2)
3458 kaklik 15  
3470 kakl 16 #include <string.h>
3458 kaklik 17  
3462 kaklik 18 #define SEL0 PIN_E0 // external counter division ratio
19 #define SEL1 PIN_E1 // external counter division ratio
20 #define MR PIN_E2 // external counter master reset
21 #define CLKI PIN_C0 // internal counter input
3458 kaklik 22  
3470 kakl 23 unsigned int32 count; // count per second
3458 kaklik 24  
3470 kakl 25 #define BUF_LEN 4
26 int8 buffer[BUF_LEN]; // I2C buffer
3463 kaklik 27 int8 address=0;
3462 kaklik 28  
29 unsigned int16 of=0; // count of overflow
3734 kakl 30  
31 // configure GPS
32 void setup_GPS()
33 {
34 // 1x 100 us per 10 s UTC synchronised
35 const char cmd[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 int n;
37 for (n=0;n<40;n++) putc(cmd[n]);
38 }
3462 kaklik 39  
3458 kaklik 40 #INT_SSP
41 void ssp_interupt ()
42 {
3470 kakl 43 int8 incoming, state;
3458 kaklik 44  
45 state = i2c_isr_state();
3470 kakl 46  
47 if(state < 0x80) //Master is sending data
48 {
49 incoming = i2c_read(); // Read byte
50  
51 if(state == 1) //Second received byte is address of register
3458 kaklik 52 {
3470 kakl 53 address = incoming;
3458 kaklik 54 }
55 }
56 if(state == 0x80) //Master is requesting data
57 {
3470 kakl 58 //i2c_read(); // Dummy read of I2C device address
59  
60 if(address == 0) // Change buffer atomically at reading of the first byte
61 {
62 buffer[0]=make8(count,0);
63 buffer[1]=make8(count,1);
64 buffer[2]=make8(count,2);
65 buffer[3]=make8(count,3);
66 }
67 if(address <= BUF_LEN) i2c_write(buffer[address]); // Prepare one byte to SSP buffer
68 else
69 {
70 i2c_write(0x00); // There is nothing to prepare, so zero
71 }
3458 kaklik 72 }
3470 kakl 73  
74 if(state == 0x81) //Master is requesting data
75 {
76 i2c_write(buffer[1]); // Prepare next byte to SSP buffer
77 }
78 if(state == 0x82) //Master is requesting data
79 {
80 i2c_write(buffer[2]); // Prepare next byte to SSP buffer
81 }
82 if(state == 0x83) //Master is requesting data
83 {
84 i2c_write(buffer[3]); // Prepare next byte to SSP buffer
3734 kakl 85  
86 setup_GPS();
3470 kakl 87 }
88  
89 if(state > 0x83) //Master is requesting data
90 {
91 i2c_write(0x00); // There is nothing to prepare, so zero
92 }
3458 kaklik 93 }
94  
95  
3463 kaklik 96  
3470 kakl 97 #int_EXT // Interrupt from 1PPS (RB0)
3462 kaklik 98 void EXT_isr(void)
99 {
100 unsigned int16 countH;
101 unsigned int8 countL;
3470 kakl 102 int16 of2;
3462 kaklik 103  
3470 kakl 104 of2=of; // read overflow counter
105 countH=get_timer1(); // read internal counter
3462 kaklik 106 countL=0;
107 output_low(SEL0);
108 output_low(SEL1);
109 countL=input(CLKI); // read bit 0 of external counter
110 output_high(SEL0);
3470 kakl 111 // output_low(SEL1);
3462 kaklik 112 countL|=input(CLKI)<<1; // read bit 1 of external counter
113 output_low(SEL0);
114 output_high(SEL1);
115 countL|=input(CLKI)<<2; // read bit 2 of external counter
116 output_high(SEL0);
3470 kakl 117 // output_high(SEL1);
3462 kaklik 118 countL|=input(CLKI)<<3; // read bit 3 of external counter
119  
120 output_low(MR); // External counter Master Reset
121 output_high(MR);
122 set_timer1(0); // Internal counter reset
3470 kakl 123 of=0; // Overflow counter reset
3462 kaklik 124  
3470 kakl 125 count=((unsigned int32)of2<<20)+((unsigned int32)countH<<4)+(unsigned int32)countL; // concatenate
3462 kaklik 126  
3501 kakl 127 // printf("%010Lu\r\n", count);
3462 kaklik 128 }
129  
130 #int_TIMER1 // Interrupf from overflow
131 void TIMER1_isr(void)
132 {
133 of++;
134 }
135  
3458 kaklik 136 void main()
137 {
3470 kakl 138 setup_adc_ports(NO_ANALOGS|VSS_VDD);
3458 kaklik 139 setup_adc(ADC_OFF);
3470 kakl 140 // setup_spi(SPI_SS_DISABLED); //must not be set if I2C are in use!
3458 kaklik 141 setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
3470 kakl 142 setup_wdt(WDT_2304MS);
3458 kaklik 143 setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
3470 kakl 144 setup_timer_2(T2_DISABLED,0,1);
3458 kaklik 145 setup_comparator(NC_NC_NC_NC);
146 setup_vref(FALSE);
3463 kaklik 147  
3470 kakl 148 restart_wdt();
149 delay_ms(1000);
150 restart_wdt();
151  
152 // setup GPS
3734 kakl 153 setup_GPS();
3463 kaklik 154  
3470 kakl 155 ext_int_edge( L_TO_H ); // set 1PPS active edge
156 enable_interrupts(INT_TIMER1);
157 enable_interrupts(INT_EXT);
3463 kaklik 158 enable_interrupts(INT_SSP);
159 enable_interrupts(GLOBAL);
3458 kaklik 160  
3470 kakl 161 buffer[0]=0x0; // Clear I2C output buffer
162 buffer[1]=0x0;
163 buffer[2]=0x0;
164 buffer[3]=0x0;
3458 kaklik 165  
3470 kakl 166 printf("\r\ncvak...\r\n");
3463 kaklik 167  
3458 kaklik 168 while(true)
3462 kaklik 169 {
3470 kakl 170 restart_wdt();
3501 kakl 171 delay_ms(1500);
172 // printf("%X %X %X %X\r\n", buffer[0],buffer[1],buffer[2],buffer[3]);
173 printf("%010Lu\r\n", count);
3458 kaklik 174 }
175 }