Electronic – Unexpected bits when shifting out (ATtiny85)

433mhzattiny85avr-gccremoteshift-register

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   

Best Answer

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.

Related Topic