-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathchaser.c
116 lines (96 loc) · 2.37 KB
/
chaser.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/** @file chaser.c
@author M. P. Hayes, UCECE
@date 15 May 2007
@brief
*/
#include <limits.h>
#include "chaser.h"
#include "flasher.h"
#include "font.h"
/* Each chaser can control a number of flashers where each flasher
usually controls a LED. The font provides a mapping between the
next character in the chaser sequence and the flashers (and thus
the LEDs) to activate. Currently, only two flash patterns are
supported; one pattern for the "on" LEDs and one for the "off"
LEDs. */
chaser_t
chaser_init (chaser_obj_t *dev, flasher_t *flashers,
uint8_t flasher_num)
{
dev->flasher_num = flasher_num;
dev->flashers = flashers;
dev->step = 0;
dev->dir = 1;
dev->mode = CHASER_MODE_NORMAL;
return dev;
}
void
chaser_sequence_set (chaser_t chaser, chaser_sequence_t seq)
{
chaser_obj_t *dev = chaser;
dev->seq = seq;
dev->step = 0;
dev->dir = 1;
}
void
chaser_mode_set (chaser_t chaser, chaser_mode_t mode)
{
chaser_obj_t *dev = chaser;
dev->mode = mode;
dev->step = 0;
dev->dir = 1;
}
static void
chaser_pixel_set (void *data, font_t *font, uint8_t col, uint8_t row, bool val)
{
chaser_obj_t *dev = data;
bool invert;
invert = dev->mode == CHASER_MODE_INVERT
|| dev->mode == CHASER_MODE_CYCLE_INVERT;
flasher_pattern_set (dev->flashers[row * font->width + col], val ^ invert
? dev->on_pattern : dev->off_pattern);
}
int8_t
chaser_update (chaser_t chaser)
{
chaser_obj_t *dev = chaser;
bool cycle;
if (!dev->seq)
return 0;
cycle = dev->mode == CHASER_MODE_CYCLE
|| dev->mode == CHASER_MODE_CYCLE_INVERT;
font_display (dev->seq[dev->step], dev->font,
chaser_pixel_set, dev);
/* Update chaser state. */
if (dev->dir > 0)
{
/* Moving forward. */
dev->step++;
if (!dev->seq[dev->step])
{
if (! cycle)
{
/* Reached end of sequence. */
dev->step = 0;
return 1;
}
dev->dir = -1;
dev->step -= 2;
}
}
else
{
/* Moving backward. */
if (!dev->step)
{
dev->dir = 1;
dev->step = 1;
return 1;
}
else
{
dev->step--;
}
}
return 0;
}