8bit counter will fit in 8 bit variable. 8 bit counter is enough if you are clever.
Ok.. so how many cycles your code takes to update 12 channels? What is confusing for me is that you say that your code takes ~50 cycles, but then you say that my 128 cycles is not feasible..
Believe me or not, but I know the compiler and the hardware and I know exactly what every line of C code does and how it translates to asm. And I can tell you that asm programmers vs C programmers.. the C compiler wins. The compiler is the result of many years of development and written by experienced asm programmers etc.
I have not seen any code from you that updates the channels in 4 cycles.. maybe you did not understand fully my example.. there is one increment, two comparisons and then setting or clearing a bit in register.. and setting the counter to zero. Impossible in 4 cycles.. well maybe possible if you have registers to spare, but like you said, you need to save and restore execution context when you enter/exit the function (interrupt). Write full code, simulate it and post the results.. or shut up. Or does it take you full day to write 100 lines of asm and another day to debug it?That's nothing to believe or not to believe here. Assember code that I posted runs at roughly 4 cycles per channel per interrupt, and the C code that you posted runs at roughly 15 cycles per channel
Are you happy with that? It will sound dreadfulall you get is 12 square wave frequency outputs
Are you happy with that? It will sound dreadful. Personally I'd want a reasonable sine (or other melodic) wave from. That would require n waveform samples per note cycle, so would push up the data rate by a factor of n and probably require one processor per note of a top octave!
True, but the OP wants polyphonic individual outputs to 12 speakers; not a mix.8 bit microcontroller can do a lot if you mix all the notes and sounds in software and output one high freq pwm signal
True, but the OP wants polyphonic individual outputs to 12 speakers; not a mix.
Me too I would like to understand that as well.I am not an audiophile.. could somebody explain why you would need dedicated speakers for all notes (and then try to save money in the driver that generates the notes)..??
In this link:http://www.pic24.ru/doku.php/en/osa/articles/pk2_osa_pianoI agree. 8 bit microcontroller can do a lot if you mix all the notes and sounds in software and output one high freq pwm signal to a proper low pass filter.
12 channels with AVR should be no problem
Write full code, simulate it and post the results.. or shut up. Or does it take you full day to write 100 lines of asm and another day to debug it?
Seriously? It is not enough for you to see the code for 1 channel?
process_channel_1_first_byte:
LDS R24, channel_1_counter
DEC R24
STS channel_1_counter, R24
BREQ process_channel_1_second_byte
process_channel_1_second_byte:
LDS R24, channel_1_counter+1
DEC R24
STS channel_1_counter+1, R24
BRCC process_channel_2_first_byte ; I hope I got this opcode right?
; our counter has expired
; toggle the LED here. This is my first exercise with AVR.
; I assume this can be done in 6 instructions
; I skip this part
LDI R24, lsb_byte_of_the_channel_1_tick_count
STS channel_1_counter, R24
LDI R24, msb_byte_of_the_channel_1_tick_count
STS channel_1_counter+1, R24
JMP process_channel_2_first_byte
and say that it toggles the output pin at controlled frequency in 4 cycles.. then yes.. I do not see anything from your code. I'm blinded by stupidness.
#include <avr/io.h>
#include <stdint.h>
#define sbi(b,n) (b |= (1<<n)) /* Set bit number n in byte b */
#define cbi(b,n) (b &= (~(1<<n))) /* Clear bit number n in byte b */
#define fbi(b,n) (b ^= (1<<n)) /* Flip bit number n in byte b */
register uint8_t counter1 asm("r2");
register uint8_t counter2 asm("r3");
register uint8_t counter3 asm("r4");
register uint8_t counter4 asm("r5");
register uint8_t counter5 asm("r6");
register uint8_t counter6 asm("r7");
register uint8_t counter7 asm("r8");
register uint8_t counter8 asm("r9");
register uint8_t counter9 asm("r10");
register uint8_t counter10 asm("r11");
register uint8_t counter11 asm("r12");
register uint8_t counter12 asm("r13");
const uint8_t top[12] = {112, 119, 126, 134, 141, 150, 159, 168, 178, 189, 200, 212};
int main(void)
{
while(1)
{
/* Decrement each counter */
counter1--;
counter2--;
counter3--;
counter4--;
counter5--;
counter6--;
counter7--;
counter8--;
counter9--;
counter10--;
counter11--;
counter12--;
/* Check if counter is zero */
if (counter1 == 0) {counter1 = 112; fbi(PORTB, 0);}
if (counter2 == 0) {counter2 = 119; fbi(PORTB, 0);}
if (counter3 == 0) {counter3 = 126; fbi(PORTB, 0);}
if (counter4 == 0) {counter4 = 134; fbi(PORTB, 0);}
if (counter5 == 0) {counter5 = 141; fbi(PORTB, 0);}
if (counter6 == 0) {counter6 = 150; fbi(PORTB, 0);}
if (counter7 == 0) {counter7 = 159; fbi(PORTB, 0);}
if (counter8 == 0) {counter8 = 168; fbi(PORTB, 0);}
if (counter9 == 0) {counter9 = 178; fbi(PORTB, 0);}
if (counter10 == 0) {counter10 = 189; fbi(PORTB, 0);}
if (counter11 == 0) {counter11 = 200; fbi(PORTB, 0);}
if (counter12 == 0) {counter12 = 212; fbi(PORTB, 0);}
}
}
#include <stdio.h>
#define F 100000 // half a period for 200kHz interrupt
#define COUNTER_BITS 11
#define ASIZE (1<<COUNTER_BITS)
#define MASK (ASIZE-1)
// assuming 16-bit ints
int x[ASIZE];
int p;
int f[12] = { F/207, F/220, F/233, F/247, F/262, F/277, F/294, F/311, F/330, F/349, F/370, F/392 };
void pwm_init() {
int i;
int mask;
for (i = 0; i < ASIZE; i++) {
x[i] = 0;
}
mask = 1;
for (i = 0; i < 12; i++) {
x[f[i]] |= mask;
mask <<= 1;
}
p = 0;
}
inline void toggle(int i) {
// toggles PWM on channel i
}
void interrupt_routine() {
int i;
int z;
int mask;
p++;
z = x[p&MASK];
if (z) {
x[p&MASK] = 0;
mask = 1;
for (i = 0; i <12; i++) {
if (z&mask) {
toggle(i);
x[(p+f[i])&MASK] |= mask;
}
mask <<= 1;
}
}
}
void main() {
pwm_init();
while (1) {
// should really be run in the interrupt
interrupt_routine();
}
}
takes 48 cycles, best case, and 99 cycles worst case (all counters zero) to update all channels. That is roughly the same as your asm code. Can't compete with C.
process_channel_1_first_byte:
LDS R24, channel_1_counter
DEC R24
STS channel_1_counter, R24
BREQ process_channel_1_second_byte
process_channel_1_first_byte:
DEC R2
BREQ process_channel_1_second_byte
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?