Rev 150 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
BASE = 14bit (*256)SIZE = 20bitLOOPSTRT = 20bitADD=6+12bit (18)VOLS=6+6bit (12)OFFSET = 20+12 bit (32) [accumulator]LOOPENA = 1bitSURROUND = 1bit [add result to one channel, subtract from other]// OLDSMPL = 8bit [old byte value, for interpolation]// нет смысла хранить это значение// для шагов больше единицы! т.е. фетчить 2 раза// надо уметь всегда!total:=118bit (15 bytes)2mem * 256w * 16bit = 64 channels maxLOOP MODES:!!!ONLY simple forward loop!!!111INTERPOLATION:!!!ALWAYS!!! between neighboring bytes, even when ADD.int>0sample:012...N <= loop start, LOOPSTART points hereN+1N+2...N+M-1 <= last loop byte (total M bytes in loop)N+M <= 1 byte past loop (must be same as [N]), SIZE points here...loops shorter than 64 bytes must be unrolled to minimum 64 bytes long...LOOPSTART = NSIZE = N+Mplay algo{{carry,OFFSET.frac} = OFFSET.frac + ADD.fracnew_off = OFFSET.int + ADD.int + carryif( new_off >= SIZE ) // the very last byte of loop is SIZE-1, byte at SIZE must be same as at LOOPSTART{new_off = new_off-SIZE+LOOPSTART // TODO: worth having LOOPSTART-SIZE instead of simple LOOPSTART}OFFSET.int = new_offADDR = OFFSET.int + BASE*256val_left = fetch(ADDR) // two consecutive bytes for interpolationval_right = fetch(ADDR+1) //interpolated = ( val_left * (256-OFFSET.frac[higher 8 bits]) + val_right * OFFSET.frac[higher 8 bits] ) / 256volume_left = interpolated * (-1)^surround * VOL_LEFTvolume_right = interpolated * VOL_RIGHTsum_left += volume_leftsum_right += volume_right} ->> APPROVEDmore on mixing/interpolatingd, dn -- data, data_next (signed)fr -- frac for interpolating (unsigned)vl, vr -- volumes (signed)rl, rr -- result left, righti = d*(~fr) + dn*fr:ordinaty mul: add data or zero, shiftd*(~fr) + dn*fr: if bit[fr] add d else add dn, shiftinterrupts:1. period interrupt, goes 37500 Hz2. BPM interupt, goes every N periods, where N=2..4097interrupt registerbit 7: SET/RESETbit 3: BPM enablebit 2: BPM pendingbit 1: period enablebit 0: period pendingperiod and BPM interrupts coincide in the same cycle. BPM has priority over periodIM0/IM2 vectors:period -- #FF / RST #38BPM -- #F7 / RST #30pending bit is automatically cleared when the corresponding interrupt is taken (vector read)BPM period register: X=[11:0]X=0 => N=2,X=1 => N=3,...X=4095 => N=4097BPM algorithm:if( !ov ) cnt <= cnt + 1;else cnt <= 0;ov <= (cnt>=X) && !ov;X can change dynamically, since >= condition is importantSTRUCTURE:- после контроллера каналов данные через фифо: адрес выборки (для 1ого байта, 22 бита), frac, volume_left, volume_right.пишутся в fifo, младшие 3 бита задает контроллер каналов, остальные -- счётчики FIFOCHANNEL FORMAT:bytes[ 0:3 ]: OFFSET[31:0]bytes[ 4:7 ]: ADD[17:0], LOOPENA, SURROUND, VLEFT[5:0], VRIGHT[5:0]bytes[ 8:11]: NU[3:0], SIZE[19:0], BASE[ 7:0]bytes[12:15]: NU[3:0], LOOP-SIZE[19:0], BASE[15:8]addr=offs[31:12]+base[13:0],8'd021 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00a13 a12 a11 a10 a09 a08 a07 a06 a05 a04 a03 a02 a01 a00 - - - - - - - -- - o31 o30 o29 o28 o27 o26 o25 o24 o23 o22 o21 o20 o19 o18 o17 o16 o15 o14 o13 o12