Public
Edited
Dec 24, 2023
Insert cell
Insert cell
wdWrapper({
config: {
skin:'default',marks:true,fit2pane: 1,wrapSvgInImg: 0,
},
head: { tick: 0, text:
['tspan',{style:'font-size:28px'}, 'Example of Plugins Usage',
['tspan',{dy:32, x:0, style:'font-size:16px'},
'Core Plugins: parseTrig & parseAsync [source: wavedrom.plugins.js]', ],
['tspan',{dy:24, x:0, style:'font-size:16px'},
'Custom Plugins: customParse(\'example\', {...}) [source: example.custom.wavedrom.plugin.js]', ],
]
},
signal: [
{name: 'clkp', wave: 'p..........'}, // Lane 0
{},
wd_.parseTrig({
name: "sinB", phase: 0,
wave: [ 'sin', { f: 1 , repeat : 3, amp: 1 } ]
}), // Lane 2
{},
wd_.parseTrig({
name: "sinC", phase: 0,
wave: [ 'sin', { f: 0.5 , repeat : 3, amp: 1 } ]
}), // Lane 4
{},
{name: 'pll_en', wave: '0.1.........0...'}, // Lane 6
{},
{name: 'pll_out', wave: 'x..<.>'},
// Lane 8 needs 3 overlays - low freq sin, better freq sin, x
{},
{name: 'pll_lock', wave: '0......1.....0..'}, // Lane 10
{},
{name: 'data-digital', wave: 'h.l...h.l.'}, // Lane 12
{},
wd_.parseTrig({
name: "PSK-analog", phase: 0,
wave: [ 'sin', { f: 1 , repeat : 2, amp: 1 } ]
}),
// Lane 14 needs 3 overlays
{},
wd_.customParse('example', {
key: 'Dummy \'signal\' object, doesnt matter what is here for the example'
}),
{},
wd_.parseAsync({name: 'async-test', wave: [ 'async',
{ seq: '0z1z1', cTimes: [0.2,2.1,3,5,7.3,8.2], rTime: 0.2, fTime: 0.2, sharpz: false }
]}),
{},
wd_.parseTrig({
phase: -3.5,
wave: [ 'sin', { f: 0.75 , repeat : 2, amp: 1 } ],
overlayOnLane: 8 // pll not locked
}),
wd_.parseTrig({
phase: -6.175,
wave: [ 'sin', { f: 1.25 , repeat : 9, amp: 1 } ],
overlayOnLane: 8 // pll locked
}),
{phase: -13.375, wave: 'x..', overlayOnLane: 8}, // pll not enabled
wd_.parseTrig({
phase: -2,
wave: [ 'sin', { f: 1 , repeat : 4, phi: 180 } ],
overlayOnLane: 14 // data = h
}),
wd_.parseTrig({
phase: -6,
wave: [ 'sin', { f: 1 , repeat : 2, phi: 0 } ],
overlayOnLane: 14 // data = l
}),
wd_.parseTrig({
phase: -8,
wave: [ 'sin', { f: 1 , repeat : 2, phi: 180 } ],
overlayOnLane: 14 // data = h
}),
]
}
, 0)
Insert cell
wdWrapper = (() => {
wavedrom.waveSkin = window.WaveSkin ;
return (obj,i) => {
const actSVG = wavedrom.onml.stringify(wavedrom.renderAny(i, obj, wavedrom.waveSkin));
const parser = new DOMParser();
const actSVGForImg = parser.parseFromString(actSVG,'image/svg+xml').firstChild;
let ser = new XMLSerializer();
let imgt = document.createElement('img');
const svgAsImgString = encodeURIComponent(ser.serializeToString(actSVGForImg));
imgt.src = `data:image/svg+xml;utf8,${svgAsImgString}` ;
imgt.style = 'width:100%;height:100%;' ;
return imgt ;
}
})();
Insert cell
wd = (() => {
wavedrom.waveSkin = window.WaveSkin ;
return (obj,i) => html`${wavedrom.onml.stringify(wavedrom.renderAny(i, obj, wavedrom.waveSkin))}`
})();
Insert cell
wd_.customParse('example',{})
Insert cell
temp = {
// START contents of example.custom.wavedrom.plugin.js
const examplePlugin = {

name: 'example',
exec: function(sig) {
sig['wave'] = [];
sig['wave'].push( 'tl',
{
coords: [0,0.5],
text: ('This is an example of a custom plugin output! Eg. field of Plugin class : nativePWAttrList : ' + wd_.nativePWAttrList.join(':')),
tlStyle: 'text-anchor:start'
} );
return sig ;
}

};

wd_.register(examplePlugin);
// END contents of example.custom.wavedrom.plugin.js
return wd_ ;
}
Insert cell
wd_ = {
// START contents of the file wavedrom.plugins.js
class WaveDromPlugins {

static sinTable ;
static cosTable ;
static nativePWAttrList ;
static plugins ;

constructor() {
this.sinTable = [...Array(Math.ceil(2*Math.PI*1000)).keys()].map( x => Math.sin(x/1000) );
this.cosTable = [...Array(Math.ceil(2*Math.PI*1000)).keys()].map( x => Math.cos(x/1000) );
this.nativePWAttrList = ['d','pwStyle','pwClass'] ;
this.plugins = {};
}

parseTrig (sig) {

let tphase = sig.phase || 0 ;
let tspec = JSON.parse(JSON.stringify(sig.wave)) ; // wave to mod
sig.wave = [] ;
let dspec = tspec[1] ;
let nodspec = (typeof dspec === 'undefined') ;
let dspecamp = (nodspec || (typeof dspec.amp === 'undefined')) ? 1 : dspec.amp ;
let dspecf = (nodspec || (typeof dspec.f === 'undefined') || (dspec.f == 0)) ? 1 : dspec.f ;
let dspecphi = (nodspec || (typeof dspec.phi === 'undefined')) ? 0 : dspec.phi ;
let drepeat = (nodspec || (typeof dspec.repeat === 'undefined')) ? 1 : dspec.repeat ;
let pathArr = [] ;
for (let rn = 0; rn < drepeat; rn++) {
for (let i = 0; i < (1/dspecf); i += 0.001) {
let tblIdx = parseInt((2000 * Math.PI * i * dspecf) + (dspecphi * 1000 * Math.PI * dspecf / 180))
% parseInt(2000 * Math.PI) ;
let scaledVal = (tspec[0] === "sin") ? this.sinTable[tblIdx] :
(tspec[0] === "cos") ? this.cosTable[tblIdx] : 0 ;
// scaledVal is between -1 and +1, but pw coords pre-scaling should be between 0 and 1
// first shift the value to be between -0.5 and 0.5 and then apply the amplitude factor
scaledVal /= 2.00 ;
scaledVal *= dspecamp ;
// shift to center around y = 0.5
scaledVal += 0.5 ;
if ((rn == 0) && (i == 0)) {
pathArr.push('M');
}
pathArr.push((rn / dspecf) + i - tphase);
pathArr.push(scaledVal);
}
}
let pwObj = { 'd' : pathArr };
Object.keys(dspec).forEach( (pwAttr) => {
if (this.nativePWAttrList.includes(pwAttr)) {
pwObj[pwAttr] = dspec[pwAttr];
}
} );
sig.wave = [ 'pw', pwObj ] ;
return sig ;
} // end parseTrig

parseAsync (sig) {

let tspec = JSON.parse(JSON.stringify(sig.wave)) ; // wave to mod
sig.wave = [] ;
if (tspec[0] !== 'async') {
return [];
}
let dspec = tspec[1] ;
let nodspec = (typeof dspec === 'undefined') ;
let dspecSeq = (nodspec || (typeof dspec.seq === 'undefined')) ? '0' : dspec.seq ;
let dspecCTimes = (nodspec || (typeof dspec.cTimes === 'undefined')) ? [0] : dspec.cTimes ;
let dspecRT = (nodspec || (typeof dspec.rTime === 'undefined')) ? 0 : dspec.rTime ;
let dspecFT = (nodspec || (typeof dspec.fTime === 'undefined')) ? 0 : dspec.fTime ;
let dspecSharpZ = (nodspec || (typeof dspec.sharpz === 'undefined')) ? false : dspec.sharpz ;
let pathArr = [] ;
let seqIdx = 0 ;
pathArr.push('M');
let xpos = dspecCTimes[seqIdx];
let ypos = (dspecSeq[seqIdx] === '0') ? 0 : (dspecSeq[seqIdx] === '1') ? 1 :
(dspecSeq[seqIdx] === 'z') ? 0.5 : 0 ;
pathArr.push(xpos);
pathArr.push(ypos);
let prevSig = dspecSeq[seqIdx] ;
for (seqIdx = 1; seqIdx < dspecSeq.length; seqIdx++) {
let nxtSig = dspecSeq[seqIdx];
let nxtCTime = dspecCTimes[seqIdx];
// draw line up to the ctime as x pos, y pos will be from prevSig
pathArr.push('L', nxtCTime, ypos); // 'L' not strictly necessary, but for readability
// nxtXPos will depend on rise or fall time
let nxtXPos = nxtCTime + dspecRT; // assume rise time
let cpX = nxtCTime + (0.4 * dspecRT) ;
ypos = (nxtSig === '0') ? 0 : (nxtSig === '1') ? 1 : (nxtSig === 'z') ? 0.5 : 0;
if (prevSig == '1') { // we need to change to fall time
nxtXPos = nxtCTime + dspecFT;
cpX = nxtCTime + (0.4 * dspecFT) ;
}
if ((nxtSig !== 'z') || (dspecSharpZ === true)) {
pathArr.push('L', nxtXPos, ypos);
} else { // Not a straight transition, but We will need a slow rise or fall
pathArr.push('Q', cpX, ypos, nxtXPos, ypos);
}
prevSig = nxtSig ;
}
// Handle the last dspecCTimes
pathArr.push('H',dspecCTimes[seqIdx]);
let pwObj = { 'd' : pathArr };
Object.keys(dspec).forEach( (pwAttr) => {
if (this.nativePWAttrList.includes(pwAttr)) {
pwObj[pwAttr] = dspec[pwAttr];
}
} );
sig.wave = [ 'pw', pwObj ] ;
return sig ;
} // end parseAsync


register (plugin) {
const {name, exec} = plugin ;
this.plugins[name] = exec ;
}

customParse (parseFunc, sig) {
const func = this.plugins[parseFunc];
return func(sig);
}

}
let wd_ ;
try {
wd_ = new WaveDromPlugins();
}
catch(err) { console.log("Unable to load WaveDromPlugins... " + err); }
// END contents of wavedrom.plugins.js
return wd_ ;
}
Insert cell
wavedrom = (await require(await FileAttachment("wavedrom.unpkg.min.js").url()));
Insert cell
(await require(await FileAttachment("default.js").url())).catch ( () => {} );
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more