Project

General

Profile

Statistics
| Branch: | Revision:

root / scout_avr / bom / bom.c @ a75b176a

History | View | Annotate | Download (4 KB)

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