Project

General

Profile

Statistics
| Branch: | Revision:

scoutos / scout_avr / bom / bom.c @ cbe25c0a

History | View | Annotate | Download (2.49 KB)

1
#include <stdint.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include "tiny-twi.h"
5
#include "bomi2c.h"
6

    
7
char last_bit;
8
char count;
9
uint16_t data;
10
volatile char currently_sending;
11
char sending_counter;
12
uint16_t sending_data;
13

    
14
#define READ_BIT(pin, bit) (((pin) >> bit) & 1)
15
#define SET_BIT(pin, bit) ((pin) |= (1 << (bit)))
16
#define CLEAR_BIT(pin, bit) ((pin) &= ~(1 << (bit)))
17
#define PRESCALAR 8
18
#define TIME_US(us) (F_CPU * (us) / 1000000 / PRESCALAR)
19

    
20
#define ADDRESS 0x3 
21

    
22
static void bom_start(void) {
23
  data = 0;
24
  count = 0;
25
  last_bit = 1;
26
  // TODO disable interrupt
27
  // TODO start timer0
28
}
29

    
30
static void bom_stop(void) {
31
  // TODO stop timer
32
  // TODO restart INT0
33
}
34

    
35
static void bom_init(void) {
36

    
37
  // setup INT0
38
  //EICRA |= _BV(ISC01) | _BV(ISC00);
39
  //EIMSK |= _BV(INT0);
40

    
41
  // setup timer 0
42
  TCCR0B |= _BV(CS01);
43
  TIMSK |= _BV(OCIE0A);
44

    
45
  // setup timer 1 for output
46
  OCR1B = TIME_US(320); // Set match b to fire every 320 us
47
  TIMSK |= _BV(OCIE1A) | _BV(OCIE1B); // Enable interrupt for match a and b
48
  TCCR1 |= _BV(CTC1);   // Enables resetting timer1 after matches match c
49

    
50
  // setup output pin
51
  SET_BIT(DDRB, 4);
52

    
53
  sei();
54
  bom_start();
55
}
56

    
57
ISR(TIMER0_COMPA_vect) {
58

    
59
  char this_bit = READ_BIT(PINB, PB2);
60

    
61
  if (this_bit == 0) {
62
    if (last_bit == 0) {
63
      bom_stop();
64
    }
65
  } else {
66
    data = data << 1 | (~last_bit & 1);
67
    count++;
68
  }
69

    
70
  last_bit = this_bit;
71

    
72
  if (count == 15) {
73
    smb_send_data(&data, sizeof(data));
74
    bom_stop();
75
  }
76
}
77

    
78
static void send_next_bit() {
79
  char next_bit = sending_data >> (14 - sending_counter) & 1;
80
  char ocr_temp = next_bit ? TIME_US(2000-40) : TIME_US(1000-20);
81
  OCR1A = ocr_temp;
82
  OCR1C = ocr_temp;
83
}
84

    
85
ISR(TIMER1_COMPA_vect) {
86
  SET_BIT(PORTB, PB4);
87
  sending_counter++;
88
  send_next_bit();
89
}
90

    
91
ISR(TIMER1_COMPB_vect) {
92
  CLEAR_BIT(PORTB, PB4);
93
  if (sending_counter >= 15) {
94
    currently_sending = 0;
95
    TCCR1 &= ~0x0F; // Stop the timer without clearing CTC1
96
  }
97
}
98

    
99
static void send_data(uint16_t data) {
100
  sending_data = data;
101
  sending_counter = 0;
102
  currently_sending = 1;
103
  TCNT1 = 0;
104
  TCCR1 |= _BV(CS12);  // Set prescalar to 8 and start timer
105
  SET_BIT(PORTB, PB4);
106
  send_next_bit();
107
}
108

    
109
ISR(INT0_vect) {
110
  bom_start();
111
}
112

    
113

    
114

    
115
static void slave_rx(uint8_t *buf, int len) {
116
  if (len >= 3) {
117
    switch (buf[0]) {
118
      case BOM_I2C_SEND:
119
        if (!currently_sending) send_data((uint16_t) buf[1] << 8 | buf[2]);  
120
        break;
121
    }
122
  }
123
}
124

    
125

    
126

    
127
int main() {
128
  bom_init();
129
  smb_init(slave_rx);
130
  smb_set_address(ADDRESS);
131
  for (;;);;;;;;;;;;;;;;;;; 
132
}