void start_task(void) { uint16_t dtycyl, adc_val; init_display(); while(1) { adc_val = adc_read(0); dtycyl = duty_cycle(adc_val); if (red != dtycyl) { red = dtycyl; VT100_cur_pos(ROW_A, COL_A + 4); printf("%04d", adc_val); Timer1_set_dtcyl(red); } adc_val = adc_read(1); dtycyl = duty_cycle(adc_val); if (green != dtycyl) { green = dtycyl; VT100_cur_pos(ROW_B, COL_B + 4); printf("%04d", adc_val); Timer2_set_dtcyl(green); } adc_val = adc_read(2); dtycyl = duty_cycle(adc_val); if (blue != dtycyl) { blue = dtycyl; VT100_cur_pos(ROW_C, COL_C + 4); printf("%04d", adc_val); Timer0_set_dtcyl(blue); } } }
void loop() { static unsigned s_idx_a = 0, s_idx_b = 0; static unsigned t_idx_a = 0, t_idx_b = 0; static unsigned u_idx_a = 0, u_idx_b = 0; static unsigned v_idx_a = 0, v_idx_b = 0; static bool s_dir_a = false, s_dir_b = false; static bool t_dir_a = false, t_dir_b = false; static bool u_dir_a = false, u_dir_b = false; static bool v_dir_a = false, v_dir_b = false; static unsigned i = 0; if (i % 101 == 0) Sa::write(duty_cycle(s_idx_a, s_dir_a) > 31); if (i % 103 == 0) Sb::write(duty_cycle(s_idx_b, s_dir_b) > 31); if (i % 107 == 0) T::output_compare_register<channel_a>() = duty_cycle(t_idx_a, t_dir_a); if (i % 109 == 0) T::output_compare_register<channel_b>() = duty_cycle(t_idx_b, t_dir_b); if (i % 113 == 0) U::output_compare_register<channel_a>() = duty_cycle(u_idx_a, u_dir_a); if (i % 127 == 0) U::output_compare_register<channel_b>() = duty_cycle(u_idx_b, u_dir_b); if (i % 131 == 0) V::output_compare_register<channel_a>() = duty_cycle(v_idx_a, v_dir_a); if (i % 137 == 0) V::output_compare_register<channel_b>() = duty_cycle(v_idx_b, v_dir_b); ++i; delay_us(250); }
// This function read instrument data and outputs info on the screen or on the verbose file // it's not actually needed to convert the data to SF2 format, but is very useful for debugging static void verbose_instrument(const inst_data inst, bool recursive) { // Do nothing with unused instruments if(!force_output_unused && inst.word0 == 0x3c01 && inst.word1 == 0x02 && inst.word2 == 0x0F0000) return; uint8_t instr_type = inst.word0 & 0xff; fprintf(out_txt, " Type : 0x%x ", instr_type); switch(instr_type) { // Sampled instruments case 0 : case 8 : case 0x10 : case 0x18 : case 0x20 : case 0x28 : case 0x30 : case 0x38 : { uint32_t sadr = inst.word1 & 0x3ffffff; fprintf(out_txt, "(sample @0x%x)\n", sadr); try { if(fseek(inGBA, sadr, SEEK_SET)) throw -1; struct { uint32_t loop; uint32_t pitch; uint32_t loop_pos; uint32_t len; } ins; fread(&ins, 4, 4, inGBA); fprintf(out_txt, " Pitch : %u\n", ins.pitch/1024); fprintf(out_txt, " Length : %u\n", ins.len); if(ins.loop == 0) fputs(" Not looped\n", out_txt); else if(ins.loop == 0x40000000) fprintf(out_txt, " Loop enabled at : %u\n", ins.loop_pos); else if(ins.loop == 0x1) fputs(" BDPCM compressed\n", out_txt); else fputs(" Unknown loop type\n", out_txt); adsr(inst.word2); } catch (...) { fputs("Invalid instrument (an exception occured)", out_txt); } } break; // Pulse channel 1 instruments case 1 : case 9 : { fputs("(GB pulse channel 1)", out_txt); if((char)inst.word0 != 8) // Display sweep if enabled on GB channel 1 fprintf(out_txt, " Sweep : 0x%x\n", inst.word0 & 0xFF); adsr(inst.word2); duty_cycle(inst.word1); } break; // Pulse channel 2 instruments case 2 : case 10 : case 18 : { fputs("(GB pulse channel 2)", out_txt); adsr(inst.word2); duty_cycle(inst.word1); } break; // Channel 3 instruments case 3 : case 11 : { fputs("(GB channel 3)", out_txt); adsr(inst.word2); fputs(" Waveform : ", out_txt); try { // Seek to waveform's location if(fseek(inGBA, inst.word1&0x3ffffff, SEEK_SET)) throw -1; int waveform[32]; for(int j=0; j<16; j++) { uint8_t a = fgetc(inGBA); waveform[2*j] = a>>4; waveform[2*j+1] = a & 0xF; } // Display waveform in text format for(int j=7; j>=0; j--) { for(int k=0; k!=32; k++) { if(waveform[k] == 2*j) fputc('_', out_txt); else if(waveform[k] == 2*j+1) fputc('-', out_txt); else fputc(' ', out_txt); } fputc('\n', out_txt); } } catch(...) { fputs("Invalid instrument (an exception occured)", out_txt); } } break; // Noise instruments case 4 : case 12 : fputs("(GB noise channel 4)", out_txt); adsr(inst.word2); if(inst.word1 == 0) fputs(" long random sequence\n", out_txt); else fputs(" short random sequence\n", out_txt); break; // Key-split instruments case 0x40 : fputs("Key-split instrument", out_txt); if(!recursive) { bool *keys_used = new bool[128](); try { // seek to key table's location if(fseek(inGBA, inst.word2&0x3ffffff, SEEK_SET)) throw -1; for(int k = 0; k!= 128; k++) { uint8_t c = fgetc(inGBA); if(c & 0x80) continue; // Ignore entries with MSB set (invalid) keys_used[c] = true; } int instr_table = inst.word1 & 0x3ffffff; for(int k = 0; k!= 128; k++) { // Decode instruments used at least once in the key table if(keys_used[k]) { try { // Seek to the addressed instrument if(fseek(inGBA, instr_table + 12*k, SEEK_SET)) throw -1; inst_data sub_instr; // Read the addressed instrument fread(&sub_instr, 4, 3, inGBA); fprintf(out_txt, "\n Sub_intrument %d", k); verbose_instrument(sub_instr, true); } catch(...) { fputs("Invalid sub-instrument (an exception occurred)", out_txt); } } } } catch (...) {} delete[] keys_used; } else fputs(" Illegal double-recursive instrument !", out_txt); break; // Every key split instruments case 0x80 : fputs("Every key split instrument", out_txt); if(!recursive) { uint32_t address = inst.word1 & 0x3ffffff; for(int k = 0; k<128; ++k) { try { if(fseek(inGBA, address + k*12, SEEK_SET)) throw -1; inst_data key_instr; fread(&key_instr, 4, 3, inGBA); fprintf(out_txt, "\n Key %d", k); verbose_instrument(key_instr, true); } catch(...) { fputs("Illegal sub-instrument (an exception occured)", out_txt); } } } else // Prevent instruments with multiple recursivities fputs(" Illegal double-recursive instrument !", out_txt); break; default : fputs("Unknown instrument type", out_txt); return; } if(recursive) fprintf(out_txt, " Key : %d, Pan : %d\n", (inst.word1>>8) & 0xFF, inst.word1>>24); }
void main(void) { init(); PSC_Init(0x00, MAX_PWM); uart_init(UART_BAUD_SELECT_DOUBLE_SPEED(UART_BAUDRATE, F_CPU)); while(1) { /* Communicate with Big Brother :-) */ communication(); /* Sampling */ if (Flag_IT_timer0) { if ( !(timer % 100) ) { /* This led shows that program is running */ GPIO_TOGGLE(WD_LED); } if ( !(timer % 10) ) { GPIO_TOGGLE(LED); /* Read meashured speed from Timer2 */ Omega_meas = TCNT1 * 10; TCNT1 = 0; /* PID controller */ pid_output = update_pid(reference_val.omega - Omega_meas, Omega_meas); Command = ((int32_t)pid_output * 131) >> 10; /* Update immediate vals */ instant_val.time = timer; instant_val.omega = Omega_meas; instant_val.error = reference_val.omega - Omega_meas; instant_val.pid_output = pid_output; instant_val.command = Command; } /* direction management : extract sign and absolute value */ if (Command > (int16_t)(0)) { direction = 0; OmegaTe = Command; } else { direction = 1; OmegaTe = (~Command) + 1; } if (OmegaTe > K_scal) { // ------------------------ V/f law -------------------------- amplitude = controlVF(OmegaTe); // ------------------ natural PWN algorithm ------------------ PWM0 = duty_cycle(theta1,amplitude); PWM1 = duty_cycle(theta2,amplitude); PWM2 = duty_cycle(theta3,amplitude); } else { PWM0 = 0; PWM1 = 0; PWM2 = 0; } // -------- load the PSCs with the new duty cycles ----------- PSC0_Load(PWM0, PWM0 + DeadTime); if (!direction) { PSC1_Load(PWM1, PWM1 + DeadTime); PSC2_Load(PWM2, PWM2 + DeadTime); } else { PSC2_Load(PWM1, PWM1 + DeadTime); PSC1_Load(PWM2, PWM2 + DeadTime); } // 3 integrators for the evolution of the angles theta1 = (K_scal * theta1 + OmegaTe) / K_scal; theta2 = theta1 + 160; theta3 = theta1 + 320; if (theta1>=MAX_THETAx4) theta1 -= MAX_THETAx4; if (theta2>=MAX_THETAx4) theta2 -= MAX_THETAx4; if (theta3>=MAX_THETAx4) theta3 -= MAX_THETAx4; Flag_IT_timer0 = 0; } }