3
\$\begingroup\$

I'm trying to spoof a 433 MHz remote and I have a sequence of 32 bytes that I want to repeatedly shift out to one of ATtiny85's pins. The signal then goes to a cheap Chinese-type 433 Mhz transmitter.

I utilized the built-in 8-bit Timer/Counter0. Unfortunately, in constant places in my sequence there are glitches in form of repeated bits.

For example (byte no. 5):

Bit number (starting from 0) 40 41 42 43 44 45 46 47
Correct                       0  0  1  0  0  1  0  0
Actual                        0  0  0  1  0  0  1  0

enter image description here

My code:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

#define OUT PB2

uint8_t bit = 0; // current bit
const uint8_t data[32] PROGMEM = {
        0b10101010,
        0b10101010,
        0b10101010,
        0b00000000,
        0b01001001,
        0b00100100,
        0b11010011,
        0b01101101,
        0b00110100,
        0b10010011,
        0b01001101,
        0b10100110,
        0b11010010,
        0b01001101,
        0b10100100,
        0b10011010,
        0b01101001,
        0b10110110,
        0b10011010,
        0b01101101,
        0b10110100,
        0b11011011,
        0b01101101,
        0b10110110,
        0b11011010,
        0b01101101,
        0b10110100,
        0b11011010,
        0b01101000,
        0b00000000,
        0b00000000,
        0b00000000,
};

int main() {
    DDRB |= _BV(OUT);

    TCCR0A |= _BV(WGM01); // clear timer on compare match
    TIMSK |= _BV(OCIE0A);

    // 2 kbps
    TCCR0B |= _BV(CS01); // prescaler: 8
    OCR0A = 62; // timer counts to 62 instead of 255

    sei();

    while (1) { }
}

ISR (TIMER0_COMPA_vect) {
    if (pgm_read_byte(&(data[bit / 8])) & (1 << bit % 8)) { // read current bit from progmem array
        PORTB |= _BV(OUT);
    } else {
        PORTB &= ~_BV(OUT);
    }

    // I tried
    // if (bit == 255) bit = 0; else bit++;
    // but it made no difference, so i left it like this
    // because it's shorter
    bit++; // let it overflow
}

I wondered if somebody could help me to troubleshoot this or maybe propose a better solution to this task which is just shifting out bytes without a clock.

EDIT: A comparison between "measured" and correct sequence (always the same, even after looping many times)

Bit Correct Measured

0   1   1   
1   0   0   
2   1   1   
3   0   0   
4   1   1   
5   0   0   
6   1   1   
7   0   0   
8   1   1   
9   0   0   
10  1   1   
11  0   0   
12  1   1   
13  0   0   
14  1   1   
15  0   0   
16  1   1   
17  0   0   
18  1   1   
19  0   0   
20  1   1   
21  0   0   
22  1   1   
23  0   0   
24  0   0   
25  0   0   
26  0   0   
27  0   0   
28  0   0   
29  0   0   
30  0   0   
31  0   1   DIFFERENT
32  0   0   
33  1   0   DIFFERENT
34  0   1   DIFFERENT
35  0   0   
36  1   0   DIFFERENT
37  0   1   DIFFERENT
38  0   0   
39  1   0   DIFFERENT
40  0   0   
41  0   1   DIFFERENT
42  1   0   DIFFERENT
43  0   0   
44  0   1   DIFFERENT
45  1   0   DIFFERENT
46  0   0   
47  0   1   DIFFERENT
48  1   1   
49  1   0   DIFFERENT
50  0   0   
51  1   1   
52  0   0   
53  0   1   DIFFERENT
54  1   1   
55  1   1   
56  0   0   
57  1   1   
58  1   1   
59  0   0   
60  1   1   
61  1   1   
62  0   0   
63  1   0   DIFFERENT
64  0   0   
65  0   1   DIFFERENT
66  1   0   DIFFERENT
67  1   1   
68  0   1   DIFFERENT
69  1   0   DIFFERENT
70  0   0   
71  0   1   DIFFERENT
72  1   1   
73  0   0   
74  0   0   
75  1   1   
76  0   0   
77  0   0   
78  1   1   
79  1   1   
80  0   0   
81  1   1   
82  0   1   DIFFERENT
83  0   0   
84  1   0   DIFFERENT
85  1   1   
86  0   0   
87  1   0   DIFFERENT
88  1   1   
89  0   1   DIFFERENT
90  1   0   DIFFERENT
91  0   0   
92  0   1   DIFFERENT
93  1   0   DIFFERENT
94  1   1   
95  0   0   
96  1   1   
97  1   0   DIFFERENT
98  0   0   
99  1   1   
100 0   0   
101 0   1   DIFFERENT
102 1   1   
103 0   1   DIFFERENT
104 0   0   
105 1   1   
106 0   1   DIFFERENT
107 0   0   
108 1   0   DIFFERENT
109 1   1   
110 0   0   
111 1   0   DIFFERENT
112 1   0   DIFFERENT
113 0   1   DIFFERENT
114 1   0   DIFFERENT
115 0   0   
116 0   1   DIFFERENT
117 1   0   DIFFERENT
118 0   1   DIFFERENT
119 0   0   
120 1   1   
121 0   0   
122 0   1   DIFFERENT
123 1   1   
124 1   0   DIFFERENT
125 0   0   
126 1   1   
127 0   1   DIFFERENT
128 0   0   
129 1   0   DIFFERENT
130 1   1   
131 0   0   
132 1   1   
133 0   1   DIFFERENT
134 0   0   
135 1   0   DIFFERENT
136 1   1   
137 0   1   DIFFERENT
138 1   0   DIFFERENT
139 1   1   
140 0   1   DIFFERENT
141 1   0   DIFFERENT
142 1   1   
143 0   0   
144 1   1   
145 0   0   
146 0   1   DIFFERENT
147 1   1   
148 1   0   DIFFERENT
149 0   0   
150 1   1   
151 0   1   DIFFERENT
152 0   0   
153 1   1   
154 1   1   
155 0   0   
156 1   1   
157 1   1   
158 0   0   
159 1   0   DIFFERENT
160 1   0   DIFFERENT
161 0   1   DIFFERENT
162 1   0   DIFFERENT
163 1   1   
164 0   1   DIFFERENT
165 1   0   DIFFERENT
166 0   1   DIFFERENT
167 0   1   DIFFERENT
168 1   1   
169 1   0   DIFFERENT
170 0   1   DIFFERENT
171 1   1   
172 1   0   DIFFERENT
173 0   1   DIFFERENT
174 1   1   
175 1   1   
176 0   0   
177 1   1   
178 1   1   
179 0   0   
180 1   1   
181 1   1   
182 0   0   
183 1   0   DIFFERENT
184 1   1   
185 0   1   DIFFERENT
186 1   0   DIFFERENT
187 1   1   
188 0   1   DIFFERENT
189 1   0   DIFFERENT
190 1   1   
191 0   0   
192 1   1   
193 1   0   DIFFERENT
194 0   1   DIFFERENT
195 1   1   
196 1   0   DIFFERENT
197 0   1   DIFFERENT
198 1   1   
199 0   1   DIFFERENT
200 0   0   
201 1   1   
202 1   1   
203 0   0   
204 1   1   
205 1   1   
206 0   0   
207 1   0   DIFFERENT
208 1   0   DIFFERENT
209 0   1   DIFFERENT
210 1   0   DIFFERENT
211 1   1   
212 0   1   DIFFERENT
213 1   0   DIFFERENT
214 0   1   DIFFERENT
215 0   0   
216 1   1   
217 1   0   DIFFERENT
218 0   1   DIFFERENT
219 1   1   
220 1   0   DIFFERENT
221 0   1   DIFFERENT
222 1   1   
223 0   0   
224 0   0   
225 1   0   DIFFERENT
226 1   1   
227 0   0   
228 1   1   
229 0   1   DIFFERENT
230 0   0   
231 0   0   
232 0   0   
233 0   0   
234 0   0   
235 0   0   
236 0   0   
237 0   0   
238 0   0   
239 0   0   
240 0   0   
241 0   0   
242 0   0   
243 0   0   
244 0   0   
245 0   0   
246 0   0   
247 0   0   
248 0   0   
249 0   0   
250 0   0   
251 0   0   
252 0   0   
253 0   0   
254 0   0   
255 0   0   
256     0   
\$\endgroup\$
6
  • \$\begingroup\$ To start, unless you turn that off with directives, your attempt of "if(==255) =0; else ++" will be optimised to just ++ by the compiler, because it's a cleverclogs, so that will indeed make no difference at all. Do these fixed positions happen consistently even if bit has wrapped around. I.e. at 5th byte and 37th byte, etc, or does the location in your 32byte series change after a wrap? Try what happens if you don't sleep the controller. It's been long since I used the x5 series, so can't remember, but there may be issues with some sleep states and missed IRQs in a few "older" Tinies. \$\endgroup\$
    – Asmyldof
    Commented Jul 18, 2017 at 23:22
  • \$\begingroup\$ Thanks for your reply! Sleeping doesn't impact this behavior, I've checked. The actual wrong sequence is repeated the same even after 2nd, 3rd, 4th, etc. cycle. \$\endgroup\$
    – Protecto
    Commented Jul 18, 2017 at 23:42
  • \$\begingroup\$ What happens if you out data in RAM instead of flash? \$\endgroup\$
    – vicatcu
    Commented Jul 19, 2017 at 1:01
  • 3
    \$\begingroup\$ Your 'Correct' sequence is not actually correct - according to the code you've written. You're starting with the Least Significant bit from each data byte, so what you should see with that code is 0, 1, 0, 1, 0, 1, 0, 1, etc - not 1, 0, ... \$\endgroup\$
    – brhans
    Commented Jul 19, 2017 at 1:03
  • \$\begingroup\$ Good eye @brhans \$\endgroup\$
    – vicatcu
    Commented Jul 19, 2017 at 1:10

2 Answers 2

4
\$\begingroup\$

You're reading your binary constants backwards when calculating your expected 'Correct' bits.

Your code which reads the individual bits:
pgm_read_byte(&(data[bit / 8])) & (1 << bit % 8))
starts with the Least significant bit (the one on the right), not the one on the left.
So your actual 'correct' sequence (at least according to the code you've written) is:
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 1 1 0 0 1 0 1 1 etc...
which exactly matches what you're seeing from your output.

If this is not what you want, then you'll need to reverse the order you're pulling the bits out by doing something like:
pgm_read_byte(&(data[bit / 8])) & (0x80 >> bit % 8))
instead.

\$\endgroup\$
-1
\$\begingroup\$

You should declare bit to be volatile since it is modified in an interrupt, though I don't know if that is your problem for sure.

\$\endgroup\$
3
  • \$\begingroup\$ He's only accessing 'bit' in the interrupt so this doesn't matter. 'volatile' is necessary when the variable is modified in both 'main' and interrupt code. \$\endgroup\$
    – brhans
    Commented Jul 19, 2017 at 1:04
  • \$\begingroup\$ I understand that, just betting pedantic, compiler might care. Maybe he isn't showing his whole program. \$\endgroup\$
    – vicatcu
    Commented Jul 19, 2017 at 1:05
  • \$\begingroup\$ it is actually the whole program \$\endgroup\$
    – Protecto
    Commented Jul 19, 2017 at 1:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.