Project

General

Profile

Revision 812788aa

ID812788aa5bc592cf417de345fdd8a74933d7a0c8
Parent 0e77683c
Child cc9ca04e

Added by Thomas Mullins almost 4 years ago

Moved some sensors to different timers

Most notably, change the ROS millisecond counter to share the BOM 38 kHz
timer instead of having its own. The range sensor and BOM rx will now
share timer 5, but they both have to be fixed for the higher F_CPU.

View differences:

scout_avr/Makefile
11 11
#PROG=avrispMKII
12 12
PROG=stk600
13 13

  
14
F_CPU=8000000
14
F_CPU=16000000
15 15
SRC=src/*.cpp src/ros_lib/*.cpp
16 16
HDR=src/*.h
17 17
FLAGS=-Isrc/ros_lib -Isrc -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL -funsigned-char -Os -fpack-struct -Wall
scout_avr/src/Atmega128rfa1.cpp
1 1
#include "Atmega128rfa1.h"
2
#include "bom.h"
2 3

  
3 4
extern "C"
4 5
{
......
7 8
  void __cxa_pure_virtual(void) {}
8 9
}
9 10

  
11
#define T0_KHZ 76
12
#define T0_OCR (F_CPU / 1000 / T0_KHZ) // 210 ticks
13
#define T0_ERROR (F_CPU / 1000 - T0_OCR*T0_KHZ) // 40 ticks/ms
14

  
15
unsigned char t0_count, t0_error;
10 16
unsigned long millis;
11 17

  
12 18
int rx_start = 0, rx_end = 0;
......
18 24

  
19 25
ISR(TIMER0_COMPA_vect)
20 26
{
21
  millis++;
27
  bom_isr();
28

  
29
  // F_CPU = T0_OCR * T0_KHZ + T0_ERROR
30
  // every millisecond, accumulate T0_ERROR, and when it reaches T0_OCR skip
31
  // one iteration
32
  t0_count++;
33
  if (t0_count >= T0_KHZ) {
34
    t0_error += T0_ERROR;
35
    if (t0_error < T0_OCR) {
36
      t0_count = 0;
37
    } else {
38
      t0_count = -1;
39
      t0_error -= T0_OCR;
40
    }
41
    millis++;
42
  }
22 43
}
23 44

  
24 45
ISR(USART0_RX_vect)
......
54 75
  // === init time ===
55 76
  // COM0x = 0, pin OC0x not used
56 77
  // WGM0 = 2, clear timer on compare match, TOP = OCRA
57
  // CS0 = 3, 64 prescaler
78
  // CS0 = 1, no prescaler
58 79
  TCCR0A = _BV(WGM01);
59
  TCCR0B = _BV(CS01) | _BV(CS00);
80
  TCCR0B = _BV(CS00);
60 81
  // enable interrupt on compare match A
61 82
  TIMSK0 = _BV(OCIE0A);
62
  // 1 ms with 1/64 prescaler
63
  OCR0A = F_CPU / 1000 / 64;
83
  OCR0A = T0_OCR;
64 84
  millis = 0;
65 85

  
66 86
  sei();
scout_avr/src/bom.cpp
12 12
 *   0: 1ms period
13 13
 *  Signal:
14 14
 *   38kHz pulse for 320us, then off for rest of time (680us or 1680us)
15
 * BOM uses timer 4 for period timing, and timer 3 for 38kHz signal
15
 * BOM uses timer 4 for period timing, and timer 0 for 38kHz signal
16 16
 */
17 17

  
18
#define TIME_KHZ(khz, prescale) (F_CPU / 1000 / (khz) / (prescale))
19 18
#define TIME_MICROS(us, prescale) (F_CPU / 1000000 * (us) / (prescale))
20 19

  
21 20
typedef uint16_t sharp_msg_t;
......
52 51
  return robot_id;
53 52
}
54 53

  
55
ISR(TIMER3_COMPA_vect) {
54
void bom_isr() {
56 55
  if (out_high) {
57 56
    BOM_EMIT ^= out_pin_mask;
58 57
  }
......
62 61
  out_high = 0;
63 62
  out_pin_mask = 0;
64 63
  
65
  // timer 3 mode CTC (clear timer on compare), TOP = OCRA
66
  TCCR3A = 0;
67
  TCCR3B = _BV(WGM32);
68
  TCCR3C = 0;
69
  
70
  // toggling at 38kHz * 2 gives 38kHz wave
71
  OCR3A = TIME_KHZ(38 * 2, 1);
72
  
73
  // enable interrupt
74
  TIMSK3 = _BV(OCIE3A);
75
  
76
  // start timer 3 at F_CPU, no prescaling
77
  TCCR3B |= _BV(CS30);
64
  // timer configuration now done in Atmega128rfa1.cpp
78 65
}
79 66

  
80 67
static void start_38kHz_signal() {
......
92 79
  // timer 4 mode CTC (clear timer on compare), TOP = OCRA
93 80
  TCCR4A = 0;
94 81
  TCCR4B = _BV(WGM42);
95
  TCCR3C = 0;
96 82
  
97 83
  // run interrupt immediately when timer started
98 84
  OCR4A = 0;
......
166 152
  if (is_rising) {
167 153
    // TODO check 320us? or have 320us timeout on rising edge?
168 154
  } else {
169
    // uses timer 1, assuming prescale 1/8
170
    // timer 1 is set up by range_init()
155
    // uses timer 5, assuming prescale 1/8
156
    // timer 5 is set up by range_init()
171 157
    // this should be in units of microseconds
172
    int now = TCNT1 * (F_CPU / 1000000 / 8);
158
    int now = TCNT5 / (F_CPU / 8 / 1000000);
173 159
    
174 160
    if (rx->count) {
175 161
      int diff = now - rx->last_time;
scout_avr/src/bom.h
53 53
void bom_send(char dir);
54 54
int bom_get(char dir);
55 55

  
56
// toggles output - should be called at around 76 kHz
57
void bom_isr();
58

  
56 59
#endif
scout_avr/src/main.cpp
5 5

  
6 6
ros::Publisher *ptest_out;
7 7

  
8
void debug(const char *str) {
8
void debug(const char *str)
9
{
9 10
}
10 11

  
11 12
void callback(const std_msgs::Int16& msg)
......
49 50

  
50 51
Atmega128rfa1 avr;
51 52

  
52
void debug(const char *str) {
53
void debug(const char *str)
54
{
53 55
  avr.puts(str);
54 56
}
55 57

  
......
68 70
    now = avr.time();
69 71
    if (now > next) {
70 72
      next = now + 100;
73
      ultoa(now, buf, 10);
74
      avr.puts(buf);
75
      avr.puts("\r\n");
71 76
      id++;
72 77
      if (id == 0x40) {
73 78
        id = 0;
......
79 84
      avr.puts(", ");
80 85
      utoa(range_get(1), buf, 10);
81 86
      avr.puts(buf);*/
82
      for (i = 0; i < 4; i++) {
87
      /*for (i = 0; i < 4; i++) {
83 88
        bom_send(i);
84 89
        int msg = bom_get(i);
85 90
        if (msg != BOM_NO_DATA) {
......
94 99
          avr.puts(buf);
95 100
          avr.puts(")\r\n");
96 101
        }
97
      }
102
      }*/
98 103
    }
99 104
  }
100 105
  return 0;
scout_avr/src/range.cpp
33 33
static void on_edge(int which)
34 34
{
35 35
  unsigned char int_high;
36
  // TODO centralize timer 1
36
  // TODO centralize timer 5
37 37
  // TODO ensure this is in microseconds even for 16MHz
38
  unsigned int time = TCNT1;
38
  unsigned int time = TCNT5;
39 39
  
40 40
  if (which)
41 41
  {
......
76 76
  
77 77
  // CS1 = 2, 1/8 prescaler
78 78
  // if this is changed, remember to change recv_edge in bom.cpp!
79
  TCCR1B = _BV(CS11);
79
  TCCR5B = _BV(CS51);
80 80
  
81 81
  range[0].value = RANGE_ERR;
82 82
  range[1].value = RANGE_ERR;

Also available in: Unified diff