Project

General

Profile

Statistics
| Branch: | Revision:

root / scout_avr / bom / bom.c @ e4d78d85

History | View | Annotate | Download (3.72 KB)

1 f572eaeb Tom Mullins
#include <stdint.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4 cbe25c0a tmullins
#include "tiny-twi.h"
5 f572eaeb Tom Mullins
#include "bomi2c.h"
6
7
char last_bit;
8
char count;
9
uint16_t data;
10 f8c1522b Aaron Perley
volatile char currently_sending;
11
char sending_counter;
12
uint16_t sending_data;
13 f572eaeb Tom Mullins
14
#define READ_BIT(pin, bit) (((pin) >> bit) & 1)
15
#define SET_BIT(pin, bit) ((pin) |= (1 << (bit)))
16 c7445989 Tom Mullins
#define CLEAR_BIT(pin, bit) ((pin) &= ~(1 << (bit)))
17 f8c1522b Aaron Perley
#define PRESCALAR 8
18
#define TIME_US(us) (F_CPU * (us) / 1000000 / PRESCALAR)
19 f572eaeb Tom Mullins
20 cbe25c0a tmullins
#define ADDRESS 0x3 
21 1b05b4cc Aaron Perley
#define DETECT PB3
22 b2554c5c Aaron Perley
#define EMIT PB4
23 f572eaeb Tom Mullins
24 1b05b4cc Aaron Perley
#if DETECT == PB3
25
  #define PCINT_DETECT PCINT3
26
#endif
27
#if DETECT == PB4
28
  #define PCINT_DETECT PCINT4
29
#endif
30 f572eaeb Tom Mullins
31 1b05b4cc Aaron Perley
static void bom_init(void) {
32
  init_detect();
33 f8c1522b Aaron Perley
34 b2554c5c Aaron Perley
  init_timer1();
35 f572eaeb Tom Mullins
36 c7445989 Tom Mullins
  sei();
37 f572eaeb Tom Mullins
}
38
39 b2554c5c Aaron Perley
////////////////////////////////// Receiving ///////////////////////////////////
40
41 1b05b4cc Aaron Perley
static void init_detect(void) {
42 e4d78d85 Julian Binder
  TCCR0A |= _BV(WGM01);    // enable reset on compare A
43 b2554c5c Aaron Perley
  TIMSK  |= _BV(OCIE0A);   // enable timer0 compare match A
44 1b05b4cc Aaron Perley
45
  GIMSK  |= _BV(PCIE);   // Enable pin change interrupt for detection
46
  PCMSK  |= _BV(PCINT_DETECT); // Enable interrupt on detect pin
47
}
48
49
// Disables the interrupt that begins the detect process while it is running
50
static void disable_detect_interrupt(void) {
51
  PCMSK &= ~_BV(PCINT_DETECT);
52 b2554c5c Aaron Perley
}
53
54
static void start_timer0(void) {
55
  TCNT0 = 0; // Reset timer 0 count to 0
56
  TCCR0B |= _BV(CS01);     // setup clkio and start the timer
57
}
58
59
static void start_detect(void) {
60 1b05b4cc Aaron Perley
  disable_detect_interrupt();
61 b2554c5c Aaron Perley
  data = 0;
62
  count = 0;
63
  last_bit = 1;
64
  start_timer0();
65
}
66
67 1b05b4cc Aaron Perley
static void restart_detect(void) {
68 b2554c5c Aaron Perley
  TCCR0B &= ~0x07; // Stop timer0
69 1b05b4cc Aaron Perley
  PCMSK  |= _BV(PCINT_DETECT); // Enable interrupt on detect pin
70
}
71
72
ISR(PCINT0_vect) {
73
  start_detect();
74 b2554c5c Aaron Perley
}
75
76 f572eaeb Tom Mullins
ISR(TIMER0_COMPA_vect) {
77
78 b2554c5c Aaron Perley
  char this_bit = READ_BIT(PINB, DETECT);
79 f572eaeb Tom Mullins
80
  if (this_bit == 0) {
81
    if (last_bit == 0) {
82 1b05b4cc Aaron Perley
      restart_detect();
83 f572eaeb Tom Mullins
    }
84
  } else {
85
    data = data << 1 | (~last_bit & 1);
86
    count++;
87
  }
88
89
  last_bit = this_bit;
90
91
  if (count == 15) {
92 1b05b4cc Aaron Perley
    restart_detect();
93 e4d78d85 Julian Binder
    smb_send_data((uint8_t*) &data, sizeof(data));
94 f572eaeb Tom Mullins
  }
95
}
96
97 b2554c5c Aaron Perley
////////////////////////////////////////////////////////////////////////////////
98
99
//////////////////////////////////// Sending ///////////////////////////////////
100
101
static void start_timer1() {
102
  TCNT1 = 0; // Reset timer 1 count to 0
103 e4d78d85 Julian Binder
  TCCR1 |= _BV(CS12); // Set prescalar to 8 and start timer1
104 b2554c5c Aaron Perley
}
105
106
static void stop_timer1() {
107
  TCCR1 &= ~0x0F; // Stop the timer without clearing CTC1
108
}
109
110
static void init_timer1() {
111
  OCR1B = TIME_US(320); // Set match b to fire every 320 us
112
  TIMSK |= _BV(OCIE1A) | _BV(OCIE1B); // Enable interrupt for match a and b
113
  TCCR1 |= _BV(CTC1);   // Enables resetting timer1 after matches match c
114
}
115
116
static void send_data(uint16_t data) {
117
  sending_data = data;
118
  sending_counter = 0;
119
  currently_sending = 1;
120
  SET_BIT(PORTB, EMIT);
121
122
  start_timer1();
123
  send_next_bit();
124
}
125
126 f8c1522b Aaron Perley
static void send_next_bit() {
127 c7445989 Tom Mullins
  char next_bit = sending_data >> (14 - sending_counter) & 1;
128
  char ocr_temp = next_bit ? TIME_US(2000-40) : TIME_US(1000-20);
129 b2554c5c Aaron Perley
  OCR1A = ocr_temp; // Compare A - Turns on transmitter
130
  OCR1C = ocr_temp; // Reset the timer when match a fires
131 f572eaeb Tom Mullins
}
132
133 b2554c5c Aaron Perley
// Compare A - Turns on transmitter
134 f8c1522b Aaron Perley
ISR(TIMER1_COMPA_vect) {
135 b2554c5c Aaron Perley
  SET_BIT(PORTB, EMIT); 
136 c7445989 Tom Mullins
  sending_counter++;
137
  send_next_bit();
138
}
139
140 b2554c5c Aaron Perley
// Compare B - Turns off transmitter after 320us
141 c7445989 Tom Mullins
ISR(TIMER1_COMPB_vect) {
142 b2554c5c Aaron Perley
  CLEAR_BIT(PORTB, EMIT);
143 c7445989 Tom Mullins
  if (sending_counter >= 15) {
144 f8c1522b Aaron Perley
    currently_sending = 0;
145 b2554c5c Aaron Perley
    stop_timer1();
146 f572eaeb Tom Mullins
  }
147
}
148
149 b2554c5c Aaron Perley
////////////////////////////////////////////////////////////////////////////////
150
151 c7445989 Tom Mullins
152 cbe25c0a tmullins
static void slave_rx(uint8_t *buf, int len) {
153
  if (len >= 3) {
154
    switch (buf[0]) {
155
      case BOM_I2C_SEND:
156
        if (!currently_sending) send_data((uint16_t) buf[1] << 8 | buf[2]);  
157
        break;
158
    }
159
  }
160
}
161
162
163 c7445989 Tom Mullins
164 f572eaeb Tom Mullins
int main() {
165
  bom_init();
166 cbe25c0a tmullins
  smb_init(slave_rx);
167
  smb_set_address(ADDRESS);
168
  for (;;);;;;;;;;;;;;;;;;; 
169 f572eaeb Tom Mullins
}