skookum as frig!
BIN
demo_site/6502.png
Normal file
After Width: | Height: | Size: 86 KiB |
434
demo_site/demo.js
Normal file
@ -0,0 +1,434 @@
|
||||
|
||||
//2017-09-17 Jorge Chamorro Bieling, jorge@jorgechamorro.com
|
||||
|
||||
window.onload= function boot () {
|
||||
|
||||
|
||||
Array.prototype.shuffle= function shuffle (a,b,i) {
|
||||
a= [];
|
||||
b= this;
|
||||
while (b.length) {
|
||||
i= rnd(b.length);
|
||||
a[a.length]= b[i];
|
||||
b.splice(i,1);
|
||||
}
|
||||
return a;
|
||||
};
|
||||
|
||||
|
||||
function $ (id) { return document.getElementById(id) }
|
||||
|
||||
|
||||
function rnd (i) {
|
||||
return Math.floor(i* Math.random());
|
||||
}
|
||||
|
||||
|
||||
[ 'homer 1.png',
|
||||
'homer 2.png',
|
||||
'homer 3.png',
|
||||
'homer 4.png',
|
||||
'homer 5.png',
|
||||
'homer 6.png',
|
||||
'homer 7.png',
|
||||
'homer 8.png',
|
||||
'f666.png',
|
||||
'6502.png',
|
||||
'6502.png',
|
||||
'6502.png'].shuffle().forEach(setup);
|
||||
|
||||
|
||||
function setup (src) {
|
||||
|
||||
var div= document.createElement('div');
|
||||
div.className= 'crop';
|
||||
var canvas= div.appendChild(document.createElement('canvas'));
|
||||
canvas.width= 280;
|
||||
canvas.height= 192;
|
||||
var img= document.createElement('img');
|
||||
img.onload= function onload (h,v) {
|
||||
img.onload= h= v= 0;
|
||||
if ((img.width>280) && (img.height>192)) {
|
||||
h= rnd(img.width-280);
|
||||
v= rnd(img.height-192);
|
||||
}
|
||||
canvas.getContext('2d').drawImage(img, -h, -v);
|
||||
div._hex= foto2hex(canvas);
|
||||
div.onclick= function onclick () {
|
||||
var samples= silence(48000/10)+ idle_turbo();
|
||||
for (var i=0 ; i<8192 ; i+=256) {
|
||||
var hex= div._hex.substr(2*i, 2*256);
|
||||
samples+= sync_turbo();
|
||||
samples+= hex_to_samples_turbo(hex);
|
||||
samples+= idle_turbo();
|
||||
}
|
||||
samples+= silence(48000/10);
|
||||
play(samples);
|
||||
}
|
||||
};
|
||||
img.src= src;
|
||||
div._img= img;
|
||||
div._canvas= canvas;
|
||||
document.body.appendChild(div);
|
||||
|
||||
function foto2hex (canvas) {
|
||||
var data= canvas.getContext('2d').getImageData(0,0,280,192);
|
||||
var bytes= [];
|
||||
for (var y=0 ; y<192 ; y+=1) {
|
||||
for (var x=0 ; x<280 ; x+=7) {
|
||||
var byte= 0;
|
||||
for (var i=6 ; i>=0 ; i-=1) {
|
||||
var pixel= data.data[4*((y*280)+(x+i))];
|
||||
byte= (2*byte)+ (pixel ? 1 : 0);
|
||||
}
|
||||
byte= byte.toString(16);
|
||||
while (byte.length<2) byte= '0'+ byte;
|
||||
bytes[get_hgr_offset(x,y)]= byte;
|
||||
}
|
||||
}
|
||||
var hex= '';
|
||||
for (var i=0 ; i<8192 ; i++) hex+= bytes[i] ? bytes[i] : '00';
|
||||
return hex;
|
||||
}
|
||||
|
||||
var hgr_offsets= [0, 1024, 2048, 3072, 4096, 5120, 6144, 7168, 128, 1152,
|
||||
2176, 3200, 4224, 5248, 6272, 7296, 256, 1280, 2304, 3328, 4352,
|
||||
5376, 6400, 7424, 384, 1408, 2432, 3456, 4480, 5504, 6528, 7552,
|
||||
512, 1536, 2560, 3584, 4608, 5632, 6656, 7680, 640, 1664, 2688,
|
||||
3712, 4736, 5760, 6784, 7808, 768, 1792, 2816, 3840, 4864, 5888,
|
||||
6912, 7936, 896, 1920, 2944, 3968, 4992, 6016, 7040, 8064, 40, 1064,
|
||||
2088, 3112, 4136, 5160, 6184, 7208, 168, 1192, 2216, 3240, 4264,
|
||||
5288, 6312, 7336, 296, 1320, 2344, 3368, 4392, 5416, 6440, 7464,
|
||||
424, 1448, 2472, 3496, 4520, 5544, 6568, 7592, 552, 1576, 2600,
|
||||
3624, 4648, 5672, 6696, 7720, 680, 1704, 2728, 3752, 4776, 5800,
|
||||
6824, 7848, 808, 1832, 2856, 3880, 4904, 5928, 6952, 7976, 936,
|
||||
1960, 2984, 4008, 5032, 6056, 7080, 8104, 80, 1104, 2128, 3152,
|
||||
4176, 5200, 6224, 7248, 208, 1232, 2256, 3280, 4304, 5328, 6352,
|
||||
7376, 336, 1360, 2384, 3408, 4432, 5456, 6480, 7504, 464, 1488,
|
||||
2512, 3536, 4560, 5584, 6608, 7632, 592, 1616, 2640, 3664, 4688,
|
||||
5712, 6736, 7760, 720, 1744, 2768, 3792, 4816, 5840, 6864, 7888,
|
||||
848, 1872, 2896, 3920, 4944, 5968, 6992, 8016, 976, 2000, 3024,
|
||||
4048, 5072, 6096, 7120, 8144];
|
||||
|
||||
function get_hgr_offset (x,y) {
|
||||
return hgr_offsets[y]+ Math.floor(x/7);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Audio cosas comunes
|
||||
|
||||
var playing= [];
|
||||
var audio_context = new (window.AudioContext || window.webkitAudioContext)();
|
||||
var sample_rate= audio_context.sampleRate;
|
||||
var invert= 0;
|
||||
|
||||
function mute () {
|
||||
while (playing.length) {
|
||||
var f= playing.pop();
|
||||
try { f() } catch (e) { ; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function silence (how_much) {
|
||||
var str= '';
|
||||
while (how_much--) str+= '0';
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
function play (samples) {
|
||||
|
||||
mute();
|
||||
|
||||
var channels= 1;
|
||||
var audio_buffer = audio_context.createBuffer(channels, samples.length, sample_rate);
|
||||
var channel_data= audio_buffer.getChannelData(0);
|
||||
var symbol2level= {H:1, h:0.5, 0:0, L:-1, l:-0.5};
|
||||
for (var i=0 ; i<samples.length ; i++) {
|
||||
var c= samples[i];
|
||||
if (invert) {
|
||||
if (c === 'L') c= 'H';
|
||||
else if (c === 'H') c= 'L';
|
||||
}
|
||||
channel_data[i]= symbol2level[c];
|
||||
}
|
||||
var audio_node = audio_context.createBufferSource();
|
||||
audio_node.buffer= audio_buffer;
|
||||
audio_node.connect(audio_context.destination);
|
||||
audio_node.onended= cleanup;
|
||||
playing.push(cleanup);
|
||||
console.log("START PLAY");
|
||||
audio_node.start();
|
||||
|
||||
function cleanup () {
|
||||
audio_node.disconnect(audio_context.destination);
|
||||
//audio_context.suspend();
|
||||
//audio_context.close();
|
||||
var where= playing.indexOf(cleanup);
|
||||
if (where >= 0) playing.splice(where, 1);
|
||||
console.log("END PLAY");
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// **** Audio turbo
|
||||
|
||||
function idle_turbo () {
|
||||
return 'LLLLLLLLLLLLHHHHHHHHHHH';
|
||||
}
|
||||
|
||||
function sync_turbo () {
|
||||
return 'HHLLLLLLLLHHHHHHHLL';
|
||||
};
|
||||
|
||||
function hex_to_samples_turbo (hex) {
|
||||
|
||||
hex= hex.toLowerCase();
|
||||
var hex2value= { 0:0, 1:1, 2:2, 3:3, 4:4, 5:5, 6:6, 7:7,
|
||||
8:8, 9:9, a:10, b:11, c:12, d:13, e:14, f:15 };
|
||||
|
||||
var bin= '';
|
||||
for (var i=0 ; i<hex.length ; i++) {
|
||||
var nibble= hex2value[hex[i]].toString(2);
|
||||
while (nibble.length<4) nibble= '0'+ nibble;
|
||||
bin+= nibble;
|
||||
}
|
||||
hex= '';
|
||||
|
||||
var manchester= '';
|
||||
var bit2samples= { 0:'LLHH', 1:'HHLL' };
|
||||
for (var i=0 ; i<bin.length ; i++) manchester+= bit2samples[bin[i]];
|
||||
bin= '';
|
||||
|
||||
var tweaked= '';
|
||||
var hi_ctr= 0;
|
||||
for (var i=0 ; i<manchester.length ; i++) {
|
||||
var c= manchester[i];
|
||||
if (c === 'L') {
|
||||
for (var j=1 ; j<hi_ctr ; j++) c= 'H'+ c;
|
||||
tweaked+= c;
|
||||
hi_ctr= 0;
|
||||
}
|
||||
else hi_ctr+= 1;
|
||||
}
|
||||
for (var j=1 ; j<hi_ctr ; j++) tweaked+= 'H';
|
||||
manchester= ''
|
||||
|
||||
return tweaked;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Audio normal
|
||||
|
||||
|
||||
function applesoft_hex_to_samples (hex) {
|
||||
|
||||
hex= hex.toLowerCase();
|
||||
|
||||
//4s @770 + sync + bytes + eor(bytes)
|
||||
|
||||
var samples= '';
|
||||
samples+= silence(sample_rate/5); //0.2 s
|
||||
samples+= header_770_normal(4);
|
||||
samples+= sync_bit_normal();
|
||||
samples+= applesoft_header(hex);
|
||||
samples+= end_cycle(samples);
|
||||
samples+= extend_last(sample_rate/10, samples);
|
||||
|
||||
samples+= header_770_normal(5);
|
||||
samples+= sync_bit_normal();
|
||||
|
||||
var eor= 0xff;
|
||||
var hex2value= {0:0, 1:1, 2:2, 3:3, 4:4, 5:5, 6:6, 7:7, 8:8,
|
||||
9:9, a:10, b:11, c:12, d:13, e:14, f:15};
|
||||
for (var i=0 ; (i+1)<hex.length ; i+=2) {
|
||||
var hi_nibble= hex2value[hex[i]];
|
||||
var lo_nibble= hex2value[hex[i+1]];
|
||||
var byte= lo_nibble+ (16* hi_nibble);
|
||||
eor^= byte;
|
||||
samples+= byte_normal(byte);
|
||||
}
|
||||
samples+= byte_normal(eor);
|
||||
samples+= end_cycle(samples);
|
||||
samples+= extend_last(10, samples);
|
||||
samples+= silence(sample_rate/5); //0.2 s
|
||||
|
||||
return samples;
|
||||
}
|
||||
|
||||
|
||||
function assembly_hex_to_samples (hex) {
|
||||
|
||||
hex= hex.toLowerCase();
|
||||
|
||||
//4s @770 + sync + bytes + eor(bytes)
|
||||
|
||||
var samples= '';
|
||||
samples+= silence(sample_rate/5); //0.2 s
|
||||
samples+= header_770_normal(4);
|
||||
samples+= sync_bit_normal();
|
||||
|
||||
var eor= 0xff;
|
||||
var hex2value= {0:0, 1:1, 2:2, 3:3, 4:4, 5:5, 6:6, 7:7, 8:8,
|
||||
9:9, a:10, b:11, c:12, d:13, e:14, f:15};
|
||||
for (var i=0 ; (i+1)<hex.length ; i+=2) {
|
||||
var hi_nibble= hex2value[hex[i]];
|
||||
var lo_nibble= hex2value[hex[i+1]];
|
||||
var byte= lo_nibble+ (16* hi_nibble);
|
||||
eor^= byte;
|
||||
samples+= byte_normal(byte);
|
||||
}
|
||||
samples+= byte_normal(eor);
|
||||
samples+= end_cycle(samples);
|
||||
samples+= extend_last(10, samples);
|
||||
samples+= silence(sample_rate/5); //0.2 s
|
||||
|
||||
return samples;
|
||||
}
|
||||
|
||||
function header_770_normal (segundos) {
|
||||
//~segundos @770 Hz
|
||||
var samples= '';
|
||||
var ciclos= 770*segundos;
|
||||
var samples_por_semiciclo= Math.round(sample_rate/(770*2));
|
||||
var samples_total= ciclos* (2*samples_por_semiciclo);
|
||||
for (var i=0 ; i<samples_total ; i++) {
|
||||
var bit= !(Math.floor(i/samples_por_semiciclo)%2);
|
||||
samples+= bit ? 'H' : 'L';
|
||||
}
|
||||
return samples;
|
||||
}
|
||||
|
||||
|
||||
function sync_bit_normal () {
|
||||
//1 pulso de 200µs + 1 pulso de 250µs
|
||||
var samples= '';
|
||||
var up= Math.round(sample_rate*200e-6);
|
||||
var down= Math.round(sample_rate*250e-6);
|
||||
for (var i=0 ; i<up ; i++) samples+= 'H';
|
||||
for (var i=0 ; i<down ; i++) samples+= 'L';
|
||||
return samples;
|
||||
}
|
||||
|
||||
|
||||
function bit_nomal (bit) {
|
||||
var samples= '';
|
||||
var len= Math.round(sample_rate* (+bit ? 500e-6 : 250e-6));
|
||||
for (var i=0 ; i<len ; i++) samples+= 'H';
|
||||
for (var i=0 ; i<len ; i++) samples+= 'L';
|
||||
return samples;
|
||||
}
|
||||
|
||||
|
||||
function byte_normal (byte) {
|
||||
var samples= '';
|
||||
byte= byte.toString(2);
|
||||
while (byte.length<8) byte= '0'+ byte;
|
||||
for (var i=0 ; i<8 ; i++) samples+= bit_nomal(byte[i]);
|
||||
return samples;
|
||||
}
|
||||
|
||||
|
||||
function applesoft_header (hex) {
|
||||
var samples= '';
|
||||
var eor= 0xff;
|
||||
var lock= 0x80;
|
||||
var len= (hex.length/2)-1;
|
||||
var hi= Math.floor(len/256);
|
||||
var lo= len%256;
|
||||
eor^= lo;
|
||||
samples+= byte_normal(lo);
|
||||
eor^= hi;
|
||||
samples+= byte_normal(hi);
|
||||
eor^= lock;
|
||||
samples+= byte_normal(lock);
|
||||
samples+= byte_normal(eor);
|
||||
return samples;
|
||||
}
|
||||
|
||||
|
||||
function end_cycle (samples) {
|
||||
var last= samples[samples.length-1];
|
||||
return (last === 'H') ? 'L' : 'H';
|
||||
}
|
||||
|
||||
|
||||
function extend_last (n, samples) {
|
||||
var s= '';
|
||||
var last= samples[samples.length-1];
|
||||
for ( var i=0 ; i<n ; i++) s+= last;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
var prgm_applesoft= "13080a00b938322c303a8c323038303a800000000a27272727272727272727";
|
||||
|
||||
var prgm_assembly= "203aff8d10c020b009204608ad00c03005b0ed4c29088d10c0297fc91bd0e18d53c08d51c060a9208dc2088dd8084c640900a200a00838ad60c0305dad60c03058ad60c03053ad60c0304ead60c03049ad60c03044ad60c0303fad60c03040ad60c0303bad60c03036ad60c03031ad60c0302cad60c03027ad60c03022ad60c0301dad60c03018ad60c03013ad60c0300ead60c030094c47099004184cea08183e00203888d028e8f07da0084cf4089004184c5c08383e00203888d084e8f067a0084c6608ad60c010e5ad60c010e0ad60c010dbad60c010d6ad60c010d1ad60c010ccad60c010c7ad60c010c8ad60c010c3ad60c010bead60c010b9ad60c010b4ad60c010afad60c010aaad60c010a5ad60c010a0ad60c0109bad60c01096ad60c010914c4709c000d015e000d011aec208e8e040f00b8ec2088ed8084c640938601860ad30c0a209ad60c08d5108ad00c030ecad60c04d510810f3ad510810e3ca3007ad60c010f830d9a209ca30d4ad60c010f83000a209ca3007ad60c030f810c1a209ca30bcad60c030f84c520820e2f38d52c0a9018d9a3a8d3a268dba2d8dc1248d19378dc1208d42248d37378d3d3d8d3a228d9b338d9b3f8dbb288d9b3b8d373b8d363a8dba298d9a3e8d42308d363e8d9b378dbb2ca9028dbd208db733a9038db7238db73a8d3f308d383a8d42288d3f208d1a278d383e8dbb228db7368d5e288dbb308dbc298dbd248d422c8d3f2c8d3f288d1a2b8d38368d3a2a8d353b8d35338db6268db8228db8268dbc2d8dbb348d3a2e8dbc318d3f248d98338d352f8d373f8db6228d35378d1a23a9048d383ba9068d3c2d8d3f298d973b8d98278d973f8d3c29a9078dbd288d1a2f8d982f8db62a8db72e8d3f218d392b8db72f8d38328dbd218d382e8db72a8dbb388db82a8d193f8db62e8d982b8d382f8db72b8d983b8dbc398d98378dbd2c8db7328d352b8d5e248d3f348db7278db82e8dbc358d1a338dbb3c8d3a328d3b3e8d193ba9088dbc2ca90c8dbc348d1a3f8dbc30a90e8d3f3c8d382a8dbc3c8db63a8dbc388d3c228db8368d3c258d3c218d99278d1a3b8d3c318dbd348d40208d3c268db6368d1a378dbd308d3b25a90f8d39278dbc3d8d3e3d8d3b3a8db73e8db8328d5e208d3f388d3f258d983f8d38338d3b218d99238db6328d3a36a9188db6378d99228d9a238d9a27a91c8d3b268d3b2a8dbf288d3e388dbb398d3e348d3b2d8dbb3d8d992f8db62f8d36238db63e8dbf248dbd3c8dbd2d8d3b328dbb358d3b2e8db63b8d99268d3b228d4028a91e8d3b298dbd388db62b8d992b8d98238db63f8d40248dbf208d38378db83a8d3c358d3b36a91f8d39238d3e398d3a3a8dbd258d3723a9308db53ea9388d39368d3b358dbe208d99378d3e3c8d992e8d40308db6338d3d258db93a8d3b398d393aa9398dbf308dbf2ca93c8d3d218d99338d402c8d3b318db83e8db93e8d992aa93e8dbd298d3523a93f8d35278d3e318d3e35a9408dbe3c8db9218d34338d342f8d34378d41308d412c8d343f8dbe388d3e218dbc288dba388dba348dba288d192b8db5268d343b8db9258db52a8d3e258d37368dbc24a9418d37338d4220a9438dbc258dba25a9448d373aa9468db7228d373ea9478db726a94e8dbb318d3e2ca94f8dbb2d8db623a95c8d3932a95e8d3e308d392ea95f8db627a9608dbe2c8db9318d35328db9298d353e8d972b8d19278d41288d9a2f8dbe308d3e298db9398d363b8d3d398dc0208dc0248dba2c8dc0288d41248d19238dba308d3e248db9358db92d8d5d288d9a3f8d3d358db5228d5d208dbe34a9618d372f8d382b8db93da9638dbc21a9678dbb298d39228d363f8dbb25a96c8d3e28a96f8d392a8d3926a9708d38278d3e208db9368db92a8db83d8d18378dbe288d993f8dbe248d3d2d8d993a8db9268d35368d353a8d41208d993e8d393e8d36338dba268d40388d9a338d403c8d5d248db9228d3e2d8d9a378db9328db92e8d9a3b8d99368d3d318d3637a9718d3b3da9738dbf388dbb21a9778dbf3ca9788d38228d183b8d362f8d38238d362b8d3d298d993b8d40348d99328d972f8d3627a9798d372ba97b8d3c3d8dbf34a97c8dba228d183f8d3a398d9733a97e8d3c398d38268d3a3d8d3a3e8d9737a97f8d37278d353f8dba218db5238db52760000000";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Listeners
|
||||
|
||||
(function setup_listeners () {
|
||||
|
||||
$("b_mute").onclick= mute;
|
||||
|
||||
$("b_load_applesoft").onclick= function () {
|
||||
play(applesoft_hex_to_samples(prgm_applesoft+prgm_assembly));
|
||||
};
|
||||
|
||||
$("b_load_assembly").onclick= function () {
|
||||
play(assembly_hex_to_samples(prgm_assembly));
|
||||
};
|
||||
|
||||
$("b_reset").onclick= function () {
|
||||
var samples= '';
|
||||
samples+= silence(sample_rate/10);
|
||||
samples+= idle_turbo();
|
||||
samples+= sync_turbo();
|
||||
samples+= extend_last(10, samples);
|
||||
samples+= silence(sample_rate/10);
|
||||
play(samples);
|
||||
};
|
||||
|
||||
|
||||
$("b_invert").onclick= function () {
|
||||
invert= !invert;
|
||||
$("b_invert").value= invert ? 'NOW INVERTED' : 'NOW NOT INVERTED';
|
||||
};
|
||||
|
||||
$("b_reload").onclick= function () { location.reload() };
|
||||
|
||||
$("b_github").onclick= function () { location.href= 'https://github.com/xk/Turbo-Cassette-for-the-Apple-II' };
|
||||
|
||||
$("b_csa2").onclick= function () { location.href= 'https://groups.google.com/forum/#!topic/comp.sys.apple2/V_S7-0pv3CA/discussion' };
|
||||
|
||||
$("b_loop").onclick= function () { alert('Sorry not yet.') };
|
||||
|
||||
$("o_sample_rate").innerHTML= "Sample rate is "+ sample_rate+ " sps";
|
||||
})();
|
||||
|
||||
|
||||
};
|
BIN
demo_site/f666.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
demo_site/homer 1.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
demo_site/homer 2.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
demo_site/homer 3.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
demo_site/homer 4.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
demo_site/homer 5.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
demo_site/homer 6.png
Normal file
After Width: | Height: | Size: 6.0 KiB |
BIN
demo_site/homer 7.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
demo_site/homer 8.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
20
demo_site/index.html
Normal file
@ -0,0 +1,20 @@
|
||||
<!doctype html>
|
||||
|
||||
<html><head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
<title>TURBO-CASSETTE DEMO</title>
|
||||
<meta name="description" content="Apple II faster cassette transfer">
|
||||
<meta name="keywords" content="6502 , Apple II, cassette, Jorge Chamorro">
|
||||
<link rel="stylesheet" type="text/css" media="all" charset="utf-8" href="style.css">
|
||||
<script src="demo.js"></script>
|
||||
</head><body><h1>TURBO-CASSETTE Demo</h1><h3 id="o_sample_rate">Sample rate is ¿?</h3><div>
|
||||
<input type="button" id="b_mute" value=" MUTE ">
|
||||
<input type="button" id="b_load_applesoft" value=" ]LOAD ">
|
||||
<input type="button" id="b_load_assembly" value=" *820.E3AR ">
|
||||
<input type="button" id="b_reset" value=" RESET ">
|
||||
<input type="button" id="b_invert" value=" NORMAL/INVERTED ">
|
||||
<input type="button" id="b_reload" value=" reload ">
|
||||
<input type="button" id="b_github" value=" goto github ">
|
||||
<input type="button" id="b_csa2" value=" goto c.s.a2 ">
|
||||
<input type="button" id="b_loop" value=" LOOP 4 EVER "></div>
|
||||
</body></html>
|
49
demo_site/style.css
Normal file
@ -0,0 +1,49 @@
|
||||
body {
|
||||
background-color: #002543;
|
||||
color: #ffffff;
|
||||
margin: 0;
|
||||
zoom: 1.1;
|
||||
}
|
||||
|
||||
.crop {
|
||||
margin: 0;
|
||||
margin-left: 10px;
|
||||
margin-bottom: 10px;
|
||||
width: 280px;
|
||||
height: 192px;
|
||||
overflow: hidden;
|
||||
border: 2px solid white;
|
||||
float: left;
|
||||
}
|
||||
|
||||
img {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
input {
|
||||
margin: 10px;
|
||||
padding: 5px;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: arial,helvetica,sans-serif;
|
||||
font-size: 32px;
|
||||
color: white;
|
||||
font-weight: normal;
|
||||
letter-spacing: 2px;
|
||||
margin: 3px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-family: arial,helvetica,sans-serif;
|
||||
font-size: 14px;
|
||||
color: white;
|
||||
font-weight: normal;
|
||||
letter-spacing: 2px;
|
||||
margin: 3px;
|
||||
}
|
||||
.crop:hover {
|
||||
border: 2px solid #fdc632;
|
||||
}
|
655
src/receive_hgr_demo_site.s
Normal file
@ -0,0 +1,655 @@
|
||||
|
||||
; Apple II TURBO CASSETTE LOADER
|
||||
; 13569 bps @44100 sps
|
||||
; 14769 bps @48000 sps
|
||||
; Jorge Chamorro Bieling, SEPT 2017
|
||||
; jorge@jorgechamorro.com
|
||||
|
||||
; See the thread "Gentlemen, 14+ kbps" @ comp.sys.apple2 :
|
||||
; https://groups.google.com/forum/#!topic/comp.sys.apple2/V_S7-0pv3CA/discussion
|
||||
; Source files: github.com/xk/Turbo-Cassette-for-the-Apple-II
|
||||
; Compile with: apple2.duckdns.org/assembler/
|
||||
; Connect the PC to the Apple II cassette in port, set the volume at 50% or more.
|
||||
; Transfer directly from the assembler page to the Apple II and then 820G
|
||||
; Go to the demo page at: apple2.duckdns.org/turbodemo/
|
||||
; Click on an image to xfer it
|
||||
; On the Apple II the space bar resets the decoder an clears the HGR screen, ESC quits.
|
||||
; Report issues on c.s.a2 or @ the github repo.
|
||||
|
||||
* = $820
|
||||
|
||||
buffer = $2000
|
||||
spkr = $c030
|
||||
cout = $fded
|
||||
hgr = $f3e2
|
||||
bell = $ff3a
|
||||
|
||||
bits = 8
|
||||
sync_min = 9
|
||||
sync_max = 9
|
||||
|
||||
reset jsr bell
|
||||
sta $c010
|
||||
jsr skookum
|
||||
|
||||
entry jsr go
|
||||
lda $c000
|
||||
bmi key
|
||||
bcs reset
|
||||
jmp entry
|
||||
|
||||
key sta $c010
|
||||
and #$7f
|
||||
cmp #27 ;ESC is quit
|
||||
bne reset ;any other key is reset
|
||||
sta $c053
|
||||
sta $c051
|
||||
rts
|
||||
|
||||
go lda #>buffer
|
||||
sta buffer_hi_1
|
||||
sta buffer_hi_2
|
||||
jmp sync
|
||||
|
||||
last_sample
|
||||
.byte 0
|
||||
|
||||
decode ldx #0 ;x= buffer index
|
||||
ldy #bits ;y= bit number
|
||||
sec ;C means last edge was a clock
|
||||
|
||||
sample_lo lda $c060 ;4
|
||||
bmi short_lo ;2..3
|
||||
sl_1 lda $c060 ;4
|
||||
bmi short_lo ;2..3
|
||||
sl_2 lda $c060 ;4
|
||||
bmi short_lo ;2..3
|
||||
sl_3 lda $c060 ;4
|
||||
bmi short_lo ;2..3
|
||||
sl_4 lda $c060 ;4
|
||||
bmi short_lo ;2..3
|
||||
sl_5 lda $c060 ;4
|
||||
bmi short_lo ;2..3
|
||||
sl_6 lda $c060 ;4
|
||||
bmi short_lo ;2..3
|
||||
w_hi_clk lda $c060 ;4
|
||||
bmi clk_rising ;2..3
|
||||
hi_clk_1 lda $c060 ;4
|
||||
bmi clk_rising ;2..3
|
||||
hi_clk_2 lda $c060 ;4
|
||||
bmi clk_rising ;2..3
|
||||
hi_clk_3 lda $c060 ;4
|
||||
bmi clk_rising ;2..3
|
||||
hi_clk_4 lda $c060 ;4
|
||||
bmi clk_rising ;2..3
|
||||
hi_clk_5 lda $c060 ;4
|
||||
bmi clk_rising ;2..3
|
||||
hi_clk_6 lda $c060 ;4
|
||||
bmi clk_rising ;2..3
|
||||
hi_clk_7 lda $c060 ;4
|
||||
bmi clk_rising ;2..3
|
||||
hi_clk_8 lda $c060 ;4
|
||||
bmi clk_rising ;2..3
|
||||
hi_clk_9 lda $c060 ;4
|
||||
bmi clk_rising ;2..3
|
||||
hi_clk_10 lda $c060 ;4
|
||||
bmi clk_rising ;2..3
|
||||
hi_clk_11 lda $c060 ;4
|
||||
bmi clk_rising ;2..3
|
||||
jmp eof_frame
|
||||
|
||||
|
||||
short_lo bcc clk_rising
|
||||
clc
|
||||
jmp sh_1
|
||||
clk_rising clc ;2 rising edge es un 0
|
||||
.byte $3e ;7 rol buffer,x ;7
|
||||
.byte <buffer
|
||||
buffer_hi_1
|
||||
.byte >buffer
|
||||
sec
|
||||
dey
|
||||
bne sh_2
|
||||
inx
|
||||
beq eof_frame
|
||||
ldy #bits
|
||||
jmp sh_3
|
||||
|
||||
|
||||
short_hi bcc clk_falling ;2..3
|
||||
clc ;2
|
||||
jmp sl_1 ;3
|
||||
clk_falling sec ;2 falling edge es un 1
|
||||
.byte $3e ;7 rol buffer,x ;7
|
||||
.byte <buffer
|
||||
buffer_hi_2
|
||||
.byte >buffer
|
||||
sec
|
||||
dey ;2
|
||||
bne sl_2 ;2..3
|
||||
inx
|
||||
beq eof_frame
|
||||
ldy #bits
|
||||
jmp sl_3 ;4
|
||||
|
||||
|
||||
sample_hi lda $c060 ;4
|
||||
bpl short_hi ;2..3
|
||||
sh_1 lda $c060 ;4
|
||||
bpl short_hi ;2..3
|
||||
sh_2 lda $c060 ;4
|
||||
bpl short_hi ;2..3
|
||||
sh_3 lda $c060 ;4
|
||||
bpl short_hi ;2..3
|
||||
sh_4 lda $c060 ;4
|
||||
bpl short_hi ;2..3
|
||||
sh_5 lda $c060 ;4
|
||||
bpl short_hi ;2..3
|
||||
sh_6 lda $c060 ;4
|
||||
bpl short_hi ;2..3
|
||||
w_lo_clk lda $c060 ;4
|
||||
bpl clk_falling ;2..3
|
||||
lo_clk_1 lda $c060 ;4
|
||||
bpl clk_falling ;2..3
|
||||
lo_clk_2 lda $c060 ;4
|
||||
bpl clk_falling ;2..3
|
||||
lo_clk_3 lda $c060 ;4
|
||||
bpl clk_falling ;2..3
|
||||
lo_clk_4 lda $c060 ;4
|
||||
bpl clk_falling ;2..3
|
||||
lo_clk_5 lda $c060 ;4
|
||||
bpl clk_falling ;2..3
|
||||
lo_clk_6 lda $c060 ;4
|
||||
bpl clk_falling ;2..3
|
||||
lo_clk_7 lda $c060 ;4
|
||||
bpl clk_falling ;2..3
|
||||
lo_clk_8 lda $c060 ;4
|
||||
bpl clk_falling ;2..3
|
||||
lo_clk_9 lda $c060 ;4
|
||||
bpl clk_falling ;2..3
|
||||
lo_clk_10 lda $c060 ;4
|
||||
bpl clk_falling ;2..3
|
||||
lo_clk_11 lda $c060 ;4
|
||||
bpl clk_falling ;2..3
|
||||
jmp eof_frame
|
||||
|
||||
|
||||
eof_frame cpy #0
|
||||
bne quit_err
|
||||
cpx #0
|
||||
bne quit_err
|
||||
ok ldx buffer_hi_1
|
||||
inx
|
||||
cpx #$40
|
||||
beq quit_ok
|
||||
stx buffer_hi_1 ;self-modifying code FTW
|
||||
stx buffer_hi_2
|
||||
jmp sync
|
||||
|
||||
quit_err sec
|
||||
rts
|
||||
|
||||
quit_ok clc
|
||||
rts
|
||||
|
||||
|
||||
;ALGORITMO DE SYNC:
|
||||
;1.- buscar un falling edge
|
||||
;2.- contar bucles hasta el próximo flanco
|
||||
;3.- si son más de sync_max o menos de sync_min goto 1
|
||||
;4.- si son entre sync_min y sync_max => ok, y si ocurren 2 seguidos => ok: Al final del segundo empiezan los datos.
|
||||
;5.- si el último pulso da error probablemente la señal esté invertida.
|
||||
;6.- los samples de los pulsos de sync serían LLLLLLLLHHHHHHHLL (8L7H2L)
|
||||
|
||||
|
||||
sync lda spkr
|
||||
ldx #sync_min
|
||||
|
||||
lda $c060
|
||||
sta last_sample
|
||||
wait_edge lda $c000
|
||||
bmi quit_err
|
||||
no_key lda $c060
|
||||
eor last_sample
|
||||
bpl wait_edge
|
||||
lda last_sample
|
||||
bpl sync ;buscamos falling edge
|
||||
|
||||
sync_1_1 dex
|
||||
bmi sync_2 ;min length ok
|
||||
lda $c060
|
||||
bpl sync_1_1
|
||||
bmi sync ;too short
|
||||
|
||||
sync_2 ldx #sync_max
|
||||
sync_2_1 dex
|
||||
bmi sync ;too long
|
||||
lda $c060
|
||||
bpl sync_2_1
|
||||
bmi sync_3
|
||||
|
||||
;1st pulse (LO) ok
|
||||
|
||||
sync_3 ldx #sync_min
|
||||
sync_3_1 dex
|
||||
bmi sync_4 ;min length ok
|
||||
lda $c060
|
||||
bmi sync_3_1
|
||||
bpl sync ;too short
|
||||
|
||||
sync_4 ldx #sync_max
|
||||
sync_4_1 dex
|
||||
bmi sync ;too long
|
||||
lda $c060
|
||||
bmi sync_4_1
|
||||
jmp decode ;2nd pulse (HI) ok
|
||||
|
||||
skookum jsr hgr
|
||||
sta $c052
|
||||
lda #1
|
||||
sta $3a9a
|
||||
sta $263a
|
||||
sta $2dba
|
||||
sta $24c1
|
||||
sta $3719
|
||||
sta $20c1
|
||||
sta $2442
|
||||
sta $3737
|
||||
sta $3d3d
|
||||
sta $223a
|
||||
sta $339b
|
||||
sta $3f9b
|
||||
sta $28bb
|
||||
sta $3b9b
|
||||
sta $3b37
|
||||
sta $3a36
|
||||
sta $29ba
|
||||
sta $3e9a
|
||||
sta $3042
|
||||
sta $3e36
|
||||
sta $379b
|
||||
sta $2cbb
|
||||
lda #2
|
||||
sta $20bd
|
||||
sta $33b7
|
||||
lda #3
|
||||
sta $23b7
|
||||
sta $3ab7
|
||||
sta $303f
|
||||
sta $3a38
|
||||
sta $2842
|
||||
sta $203f
|
||||
sta $271a
|
||||
sta $3e38
|
||||
sta $22bb
|
||||
sta $36b7
|
||||
sta $285e
|
||||
sta $30bb
|
||||
sta $29bc
|
||||
sta $24bd
|
||||
sta $2c42
|
||||
sta $2c3f
|
||||
sta $283f
|
||||
sta $2b1a
|
||||
sta $3638
|
||||
sta $2a3a
|
||||
sta $3b35
|
||||
sta $3335
|
||||
sta $26b6
|
||||
sta $22b8
|
||||
sta $26b8
|
||||
sta $2dbc
|
||||
sta $34bb
|
||||
sta $2e3a
|
||||
sta $31bc
|
||||
sta $243f
|
||||
sta $3398
|
||||
sta $2f35
|
||||
sta $3f37
|
||||
sta $22b6
|
||||
sta $3735
|
||||
sta $231a
|
||||
lda #4
|
||||
sta $3b38
|
||||
lda #6
|
||||
sta $2d3c
|
||||
sta $293f
|
||||
sta $3b97
|
||||
sta $2798
|
||||
sta $3f97
|
||||
sta $293c
|
||||
lda #7
|
||||
sta $28bd
|
||||
sta $2f1a
|
||||
sta $2f98
|
||||
sta $2ab6
|
||||
sta $2eb7
|
||||
sta $213f
|
||||
sta $2b39
|
||||
sta $2fb7
|
||||
sta $3238
|
||||
sta $21bd
|
||||
sta $2e38
|
||||
sta $2ab7
|
||||
sta $38bb
|
||||
sta $2ab8
|
||||
sta $3f19
|
||||
sta $2eb6
|
||||
sta $2b98
|
||||
sta $2f38
|
||||
sta $2bb7
|
||||
sta $3b98
|
||||
sta $39bc
|
||||
sta $3798
|
||||
sta $2cbd
|
||||
sta $32b7
|
||||
sta $2b35
|
||||
sta $245e
|
||||
sta $343f
|
||||
sta $27b7
|
||||
sta $2eb8
|
||||
sta $35bc
|
||||
sta $331a
|
||||
sta $3cbb
|
||||
sta $323a
|
||||
sta $3e3b
|
||||
sta $3b19
|
||||
lda #8
|
||||
sta $2cbc
|
||||
lda #12
|
||||
sta $34bc
|
||||
sta $3f1a
|
||||
sta $30bc
|
||||
lda #14
|
||||
sta $3c3f
|
||||
sta $2a38
|
||||
sta $3cbc
|
||||
sta $3ab6
|
||||
sta $38bc
|
||||
sta $223c
|
||||
sta $36b8
|
||||
sta $253c
|
||||
sta $213c
|
||||
sta $2799
|
||||
sta $3b1a
|
||||
sta $313c
|
||||
sta $34bd
|
||||
sta $2040
|
||||
sta $263c
|
||||
sta $36b6
|
||||
sta $371a
|
||||
sta $30bd
|
||||
sta $253b
|
||||
lda #15
|
||||
sta $2739
|
||||
sta $3dbc
|
||||
sta $3d3e
|
||||
sta $3a3b
|
||||
sta $3eb7
|
||||
sta $32b8
|
||||
sta $205e
|
||||
sta $383f
|
||||
sta $253f
|
||||
sta $3f98
|
||||
sta $3338
|
||||
sta $213b
|
||||
sta $2399
|
||||
sta $32b6
|
||||
sta $363a
|
||||
lda #24
|
||||
sta $37b6
|
||||
sta $2299
|
||||
sta $239a
|
||||
sta $279a
|
||||
lda #28
|
||||
sta $263b
|
||||
sta $2a3b
|
||||
sta $28bf
|
||||
sta $383e
|
||||
sta $39bb
|
||||
sta $343e
|
||||
sta $2d3b
|
||||
sta $3dbb
|
||||
sta $2f99
|
||||
sta $2fb6
|
||||
sta $2336
|
||||
sta $3eb6
|
||||
sta $24bf
|
||||
sta $3cbd
|
||||
sta $2dbd
|
||||
sta $323b
|
||||
sta $35bb
|
||||
sta $2e3b
|
||||
sta $3bb6
|
||||
sta $2699
|
||||
sta $223b
|
||||
sta $2840
|
||||
lda #30
|
||||
sta $293b
|
||||
sta $38bd
|
||||
sta $2bb6
|
||||
sta $2b99
|
||||
sta $2398
|
||||
sta $3fb6
|
||||
sta $2440
|
||||
sta $20bf
|
||||
sta $3738
|
||||
sta $3ab8
|
||||
sta $353c
|
||||
sta $363b
|
||||
lda #31
|
||||
sta $2339
|
||||
sta $393e
|
||||
sta $3a3a
|
||||
sta $25bd
|
||||
sta $2337
|
||||
lda #48
|
||||
sta $3eb5
|
||||
lda #56
|
||||
sta $3639
|
||||
sta $353b
|
||||
sta $20be
|
||||
sta $3799
|
||||
sta $3c3e
|
||||
sta $2e99
|
||||
sta $3040
|
||||
sta $33b6
|
||||
sta $253d
|
||||
sta $3ab9
|
||||
sta $393b
|
||||
sta $3a39
|
||||
lda #57
|
||||
sta $30bf
|
||||
sta $2cbf
|
||||
lda #60
|
||||
sta $213d
|
||||
sta $3399
|
||||
sta $2c40
|
||||
sta $313b
|
||||
sta $3eb8
|
||||
sta $3eb9
|
||||
sta $2a99
|
||||
lda #62
|
||||
sta $29bd
|
||||
sta $2335
|
||||
lda #63
|
||||
sta $2735
|
||||
sta $313e
|
||||
sta $353e
|
||||
lda #64
|
||||
sta $3cbe
|
||||
sta $21b9
|
||||
sta $3334
|
||||
sta $2f34
|
||||
sta $3734
|
||||
sta $3041
|
||||
sta $2c41
|
||||
sta $3f34
|
||||
sta $38be
|
||||
sta $213e
|
||||
sta $28bc
|
||||
sta $38ba
|
||||
sta $34ba
|
||||
sta $28ba
|
||||
sta $2b19
|
||||
sta $26b5
|
||||
sta $3b34
|
||||
sta $25b9
|
||||
sta $2ab5
|
||||
sta $253e
|
||||
sta $3637
|
||||
sta $24bc
|
||||
lda #65
|
||||
sta $3337
|
||||
sta $2042
|
||||
lda #67
|
||||
sta $25bc
|
||||
sta $25ba
|
||||
lda #68
|
||||
sta $3a37
|
||||
lda #70
|
||||
sta $22b7
|
||||
sta $3e37
|
||||
lda #71
|
||||
sta $26b7
|
||||
lda #78
|
||||
sta $31bb
|
||||
sta $2c3e
|
||||
lda #79
|
||||
sta $2dbb
|
||||
sta $23b6
|
||||
lda #92
|
||||
sta $3239
|
||||
lda #94
|
||||
sta $303e
|
||||
sta $2e39
|
||||
lda #95
|
||||
sta $27b6
|
||||
lda #96
|
||||
sta $2cbe
|
||||
sta $31b9
|
||||
sta $3235
|
||||
sta $29b9
|
||||
sta $3e35
|
||||
sta $2b97
|
||||
sta $2719
|
||||
sta $2841
|
||||
sta $2f9a
|
||||
sta $30be
|
||||
sta $293e
|
||||
sta $39b9
|
||||
sta $3b36
|
||||
sta $393d
|
||||
sta $20c0
|
||||
sta $24c0
|
||||
sta $2cba
|
||||
sta $28c0
|
||||
sta $2441
|
||||
sta $2319
|
||||
sta $30ba
|
||||
sta $243e
|
||||
sta $35b9
|
||||
sta $2db9
|
||||
sta $285d
|
||||
sta $3f9a
|
||||
sta $353d
|
||||
sta $22b5
|
||||
sta $205d
|
||||
sta $34be
|
||||
lda #97
|
||||
sta $2f37
|
||||
sta $2b38
|
||||
sta $3db9
|
||||
lda #99
|
||||
sta $21bc
|
||||
lda #103
|
||||
sta $29bb
|
||||
sta $2239
|
||||
sta $3f36
|
||||
sta $25bb
|
||||
lda #108
|
||||
sta $283e
|
||||
lda #111
|
||||
sta $2a39
|
||||
sta $2639
|
||||
lda #112
|
||||
sta $2738
|
||||
sta $203e
|
||||
sta $36b9
|
||||
sta $2ab9
|
||||
sta $3db8
|
||||
sta $3718
|
||||
sta $28be
|
||||
sta $3f99
|
||||
sta $24be
|
||||
sta $2d3d
|
||||
sta $3a99
|
||||
sta $26b9
|
||||
sta $3635
|
||||
sta $3a35
|
||||
sta $2041
|
||||
sta $3e99
|
||||
sta $3e39
|
||||
sta $3336
|
||||
sta $26ba
|
||||
sta $3840
|
||||
sta $339a
|
||||
sta $3c40
|
||||
sta $245d
|
||||
sta $22b9
|
||||
sta $2d3e
|
||||
sta $379a
|
||||
sta $32b9
|
||||
sta $2eb9
|
||||
sta $3b9a
|
||||
sta $3699
|
||||
sta $313d
|
||||
sta $3736
|
||||
lda #113
|
||||
sta $3d3b
|
||||
lda #115
|
||||
sta $38bf
|
||||
sta $21bb
|
||||
lda #119
|
||||
sta $3cbf
|
||||
lda #120
|
||||
sta $2238
|
||||
sta $3b18
|
||||
sta $2f36
|
||||
sta $2338
|
||||
sta $2b36
|
||||
sta $293d
|
||||
sta $3b99
|
||||
sta $3440
|
||||
sta $3299
|
||||
sta $2f97
|
||||
sta $2736
|
||||
lda #121
|
||||
sta $2b37
|
||||
lda #123
|
||||
sta $3d3c
|
||||
sta $34bf
|
||||
lda #124
|
||||
sta $22ba
|
||||
sta $3f18
|
||||
sta $393a
|
||||
sta $3397
|
||||
lda #126
|
||||
sta $393c
|
||||
sta $2638
|
||||
sta $3d3a
|
||||
sta $3e3a
|
||||
sta $3797
|
||||
lda #127
|
||||
sta $2737
|
||||
sta $3f35
|
||||
sta $21ba
|
||||
sta $23b5
|
||||
sta $27b5
|
||||
rts
|
||||
|
||||
.byte 0
|
||||
.byte 0
|
||||
.byte 0
|
||||
|
||||
.end
|