Root/fw/sweep.c

Source at commit 63a4b895d3d7da5a8b71ab383976ae835db52e99 created 10 years 11 months ago.
By Werner Almesberger, tornado/cpu/cpu.sch (CON3): nISP and nRESET were swapped
1/*
2 * fw/image.c - Image sweep
3 *
4 * Written 2012 by Werner Almesberger
5 * Copyright 2012 Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13
14#include <stdbool.h>
15#include <stdint.h>
16
17#include <avr/io.h>
18#include <avr/interrupt.h>
19
20#include "image.h"
21#include "sweep.h"
22
23
24volatile bool sweeping = 0;
25
26
27static volatile uint32_t t_up; /* uptime, in timer ticks (wraps in 4295 s) */
28static volatile uint32_t t_sw; /* cumulative number of timer ticks in sweep */
29
30static uint16_t wait_periods; /* number of periods to wait before image */
31static uint16_t wait_period; /* ticks in wait period */
32static uint16_t wait_short; /* ticks to wait after periods */
33
34static uint16_t pixel_ticks; /* number of ticks per pixel */
35static const struct line *curr_line;
36static const struct line *end_line;
37static bool forward;
38
39
40ISR(TIMER1_OVF_vect)
41{
42    uint16_t t;
43
44    /* update the time counters */
45
46    t = ICR1;
47    t_sw += t;
48    t_up += t;
49
50    /* if at the end of the image, only update the time */
51
52    if (curr_line == end_line) {
53        PORTB &= 0x3f;
54        PORTC = 0;
55        PORTD = 0;
56        ICR1 = 0xffff;
57        sweeping = 0;
58        return;
59    }
60
61    /* wait before starting the image */
62
63    if (wait_periods) {
64        if (!--wait_periods)
65            ICR1 = wait_short;
66        return;
67    }
68
69    /* if done, lights out and slow down */
70
71    /* output the next line */
72
73    set_line(*curr_line);
74
75    /* move to the next line */
76
77    if (forward)
78        curr_line++;
79    else
80        curr_line--;
81
82    /* wait until the next pixel */
83
84    ICR1 = pixel_ticks;
85}
86
87
88uint32_t uptime_irq(void)
89{
90    uint32_t t;
91
92    t = t_up+TCNT1;
93    if (TIFR1 & TOV1)
94        t += ICR1;
95    return t;
96}
97
98
99uint32_t uptime(void)
100{
101    uint32_t a, b;
102    uint16_t d;
103
104    do {
105        cli();
106        a = t_up;
107        d = TCNT1;
108        cli();
109        b = t_up;
110        sei();
111    }
112    while (a != b);
113    return a+d;
114}
115
116
117void sweep_image(const struct sweep *sweep)
118{
119    uint32_t t;
120
121    /* calculate start time */
122
123    t = uptime();
124    if (sweep->start_ticks <= t)
125        return;
126    t = sweep->start_ticks-t;
127
128    TCCR1B = 0; /* stop the timer */
129
130    cli();
131
132    /* shut down all the LEDs, in case we're still in a sweep */
133
134    PORTB &= 0x3f;
135    PORTC = 0;
136    PORTD = 0;
137
138    /* image pointers and sweep direction */
139
140    forward = sweep->forward;
141    if (forward) {
142        curr_line = image+sweep->left;
143        end_line = image+sweep->right+1;
144    } else {
145        curr_line = image+sweep->right;
146        end_line = image+sweep->left-1;
147    }
148
149    /* timing parameters */
150
151    pixel_ticks = sweep->pixel_ticks;
152    wait_periods = t >> 16;
153    if (wait_periods) {
154         wait_short = t;
155        wait_period = 0xffff;
156
157        /*
158         * Make sure we have plenty of time to update ICR1 after an
159         * interrupt.
160         */
161        if (wait_short < 256) {
162            wait_period -= 128;
163            wait_short += wait_periods << 7;
164        }
165        ICR1 = wait_period;
166    } else {
167         ICR1 = t;
168    }
169
170    /* prepare the hardware timer */
171
172    t_sw = 0; /* reset the time */
173    TCNT1 = 0;
174    TIFR1 = 1 << TOV1; /* clear interrupt */
175    
176    /* start the timer */
177
178    TCCR1B =
179        1 << WGM13 | /* WG Mode 14, continued */
180        1 << WGM12 |
181        1 << CS11; /* clkIO/8 */
182
183    sweeping = 1;
184
185    sei();
186}
187
188
189void sweep_init(void)
190{
191    TCCR1A =
192        1 << WGM11; /* WG Mode 14 (Fast PWM to ICR1) */
193
194    TCNT1 = 0;
195
196    TIMSK1 = 1 << TOIE1; /* enable timer interrupts */
197}
198

Archive Download this file

Branches:
master
tornado-v1



interactive