Gas station without pumps

2013 December 1

Bitscope differential probe

Filed under: Data acquisition,Digital-to-analog conversion — gasstationwithoutpumps @ 01:01
Tags: , ,

In First blogging swag, I mentioned getting a pre-production prototype of the Bitscope DP01 Dual Channel Active Differential Probe:

The probe PC board is about 6.2cm long and 2cm wide (8cm long with the connectors on the ends).

The probe PC board is about 6.2cm long and 2cm wide—8cm long with the connectors on the ends. (More pictures in First blogging swag)

Because the first one they sent me got lost in the mail, I didn’t get this device until the Fall quarter had started and I had a lot of grading to do every weekend (plus trying to rewrite the bioengineering and bioinformatics curricula, but that’s a subject for a different blog post).  This weekend I finally have a long weekend without grading (I’ll pay for that next weekend, with a double or triple load), so I’m going to indulge myself and play with my new toy.

The BitScope folks have not released a full spec sheet for the device yet, but they have a blog post with the essentials (and now the official DP01 web page):

DP01 | Active Differential Probe Specifications

Feature Specification
Attenuation/Gain Ratios 2:1 & 1:5 (prescale on)
Input Bandwidth DC to 10MHz (-3dB, prescale off)
DC to 3MHz (-3dB, prescale on)
Common Mode Rejection 100Hz: >1,000 : 1
1MHz: > 400 : 1
Input Resistance 20MΩ (differential)
10MΩ (common)
Input Capacitance 2.5pF (differential)
5pF (common)
Maximum Working Voltage 12.5Vp-p (differental)
±13.8Vpeak (common)
Power Requirement 5V & 3.3V (provided by BitScope)

The bandwidth for the probe is probably larger than the bandwidth for the BS10U Pocket Analyzer itself, and low-voltage measurements will be limited by the noise floor of the pocket analyzer. Let’s start by looking at the pocket analyzer with shorted inputs, to see what the noise floor is:

Here is the waveform for the shorted inputs at the highest gain the BitScope provides (10mV/division) at a fairly high sampling rate (5µs/division).  The peak-to-peak noise is about 14mV, and the digitization noise (about 2mV/step) is clearly visible.

Here is the waveform for the shorted inputs at the highest gain the BitScope provides (10mV/division) at a fairly high sampling rate (5µs/division). The peak-to-peak noise is about 14mV, and the digitization noise (about 2mV/step) is clearly visible. (Click to embiggen.)

For those who have taken my classes and know how I rail against the insanity of black backgrounds and unlabeled axes for plots, I apologize, but BitScope still provides only this 1950s style display, even with the development version of the software (DSO 2.7 DG17G). I wish they would produce publication-quality displays (in svg or pdf formats, with no black background), but I suspect that they have only electrical engineers on their development team, with no graphic designers or human-computer interface experts. It would do them a world of good to read Tufte’s books or some other basic introduction to displaying information.


Click to embiggen. Here is the “spectrum” display of the waveform in the previous image (BS10U Pocket Analyzer with shorted inputs). The vertical scale is 10dB/division, and the horizontal scale is 0.6MHz per division (what an awkward unit!). It would be really nice if there were an option to get a log scale on frequency, as is done on Bode plots.
The big spike marked with the vertical orange line is at 2.5 MHz, and is pretty consistently present.  The horizonal orange line is at 25dB, and the vertical axis is 10dB/division.

The noise seems to be low-pass filtered at about 2 or 2.5MHz (it’s a little hard to tell, since there is no way with the Bitscope sample to take a really long sample and smooth out the random fluctuations), dropping about 120dB per decade above the cutoff. That would be 6th-order filter, which seems a little high order for an anti-aliasing filter. More likely, they are using a lower-order elliptic filter, Chebyshev filter, or other design with a sharp transition between the passband and the stopband. That might also explain the peaking at 2.5MHz, though the peak seems too sharp to be a filter artifact. Using just the amplifier input noise to probe the filter does not give me much information about the filter once it starts attenuating, so I don’t know what the stop band looks like.

Unfortunately, “The spectrum magnitude display is unreferenced; all measurements are relative to the prevailing V/Div value on each channel” (, so I don’t know what 25dB means here in terms of the actual noise density. A 350mV peak-to-peak sine wave is 60dB  at 100mV/division, and 80dB at 10mV/division, so 25dB at 10mV/division would be about 600µV peak-to-peak or 220µV rms for a sine wave.  I’m too lazy to try to figure out the rms V/√Hz noise density.

Adding the differential probe in front of the Pocket Analyzer does not change the spectrum shape noticeably.

Waveform (using sharp, raw data display) at 5µs/division and 2mV/division of shorted inputs to the DP01 differential probe at high gain (supposedly a gain of 5).

Waveform (using sharp, raw data display) at 5µs/division and 2mV/division of shorted inputs to the DP01 differential probe at high gain (supposedly a gain of 5). (click to embiggen)

The spectrum (again using the sharp, raw data display) looks essentially the same as without the DP01 probe.  The limitations of the Pocket Analyzer mask any limitations of the DP01 probe.

The spectrum (using the sharp, raw data display) looks essentially the same as without the DP01 probe. Note how sharp the 2.5MHz peak is in this view. The limitations of the Pocket Analyzer mask any limitations of the DP01 probe. (click to embiggen)

In the high-gain mode, the probe has a gain of 5 and the input-referenced noise is around 6mV peak-to-peak, instead of 14mV peak-to-peak without the probe. In the low-gain mode (gain of 0.5), the input-referenced noise is about 26mV peak-to-peak (4 different quantization levels). There is noise added by the probe in the high-gain mode, but it is still better than the Pocket Analyzer without the probe (about 7dB better signal-to-noise ratio, though a gain of 5 should produce a 14dB gain.

I looked at the output of my Elenco Model FG-500 function generator with about a 292kHz waveform (80mV peak-to-peak with about a 4.1v DC offset): one channel set to high gain with AC coupling, the other set to low gain with DC coupling and mean-subtraction in software.

With high gain and ACcoupling, the 292kHz ~80mV signal is easily seen, but with DC coupling the gain has to be turned down to get enough range, and then the low resolution of the BitScope's ADC is a problem.

With high gain and AC coupling (yellow), the 292kHz ~80mV signal is easily seen, but with DC coupling (green) the gain has to be turned down to get enough range, and then the low resolution of the BitScope’s ADC is a problem. (click to embiggen)

The glitches in the “sine wave” output of the FG-500 function generator are actually much bigger than they appear here. With my 60MHz Kikusui COS 5060 analog oscilloscope, I can see a downward spike from the top of the sine wave of about the same magnitude as the sine wave in about 30nsec—much faster than the BitScope Pocket Analyzer can capture.

Spectrum at 20 mv/division shows the harmonic distortion and a clear 20dB larger noise floor for the low-gain signal than the high-gain, AC-coupled signal.

Spectrum at 20 mv/division shows the harmonic distortion and a clear 20dB larger noise floor for the low-gain signal than the high-gain, AC-coupled signal. (click to embiggen)

So far, I’ve just been looking at the probe as an amplifier, without taking advantage of the differential inputs.

I did a simple test with the Freedom KL25Z board (which has a 12-bit DAC), outputting 17 values (0, 0x200, 0x400, … 0x2000), where the full range of the DAC  is 0, 0x10, …, 0xfff0.  I used a series resistor and capacitor as a load, and measured the voltage across each.  Since both the Freedom board and the BitScope are being powered from the same USB supply (my laptop), having  differential inputs really reduces the risk of possibly shorting a signal to ground, and allows me to measure the voltage across the capacitor and the current into it simultaneously.


I connected a 470pF capacitor and a 1802Ω resistor in series as a load for the KL25Z 12-bit DAC, and measured the voltage across each. Channel 1 in yellow is the voltage across the resistor.
Channel 2 in green is across the capacitor. As expected the current through the resistor is the derivative of the voltage across the capacitor, but why the small spikes as well? (click to embiggen)


(click to embiggen) With the capacitor removed, the current drops to 0, and the voltage shows bad behavior for the DAC when it switches from 0xe00 to 0x1000 and from 0x1e00 to 0x2000.
I checked, and there are similar problems at all the multiples of 0x1000, even coming from just one count lower.

The KL25 specs call for a settling time of <1µs for single steps and <30µs rail-to-rail. I’m seeing a faster slew than that for large changes (about –3V/1µs slew rate), but the glitch at the multiples of 0x1000 is almost a microsecond long, so is pushing against the code-to-code spec.

Incidentally, it looks like I can output values to the KL25 DAC at about 828kHz with the mbed libraries (using write_u16(), not their ridiculously slow floating-point output routine).  Given the 1µs settling time, there isn’t much point to trying to push it faster than that.

Overall, the DP01 seems like a useful tool, compensating for many of the weaknesses of the BitScope Pocket Analyzer. The AC coupling, the differential inputs, and the increased gain are all useful features.  There are some flaws, though:

  • Changing between differential and AC-coupled input by changing the orientation of the connectors is annoying, and it is very easy to connect things up wrong.
  • Having to use shorting plugs to change the gain is also annoying—especially since the labels on the pre-preduction release I have suggest a different arrangement of the shorting plugs than the one that actually works. See the picture at the beginning of this post—the plugs have to be horizontal, with channel 2 on top, but the label suggests that they are vertical, with channel 1 on the outside.  Of course, the label also suggests that the gain is ×2 and ×20, rather than ×0.5 and ×5—I hope that they fix that confusion in the final release.
  • Having to remember to change the gain setting on the software every time the gain is changed is also annoying.  A more integrated  system would communicate the gain settings of the probes to the software automatically (difficult to do through the Pocket Analyzer, though, since it has no communication with the probe other than power and measuring the analog output).

Overall, I’m moderately pleased with the BitScope hardware, but I still find their software poorly designed and poorly implemented.  Plots have unlabeled axes, cursors can’t be nudged with arrow keys, and numbers can’t be typed in—everything has to be done by microscopic movements of a mouse, which is doubly difficult on a laptop trackpad.  I had several array-out-of-bounds crashes today, and the few cryptic labels that are on the plots are often wrong (changing the time base does not update the frequency computation for “FP”, for example).

I’m considering using the DP01 preamplifier before the analog-to-digital converters on the Freedom KL25Z board. I may not get all the flexibility of the BitScope that way, but the 16-bit ADC may compensate for a lot of problems. I should be able to get down to a resolution of 10µv that way, which may be enough to do an EKG recording without an additional amplifier.  Unfortunately, I won’t be able to view traces easily, as I’ve not yet gotten my son to rewrite the Arduino Data Logger to talk with the KL25Z board—he’s been spending all his programming time on his light gloves project, and when I can get his attention, it is usually to insist that he work on his college application essays.

2013 January 30

Teaching engineering thinking

Yesterday I wrote

Maybe I should recommend some generic problem-solving books, like Polya’s How to Solve It, since it seems that the class has not been taught many problem-solving skills. I keep feeling that I’m teaching stuff that they should have had much earlier, but clearly haven’t, as if every teacher they’ve ever had has pushed off teaching the important stuff in order to cram in more factoids. There are times when I’m tempted to kick the can down the road myself, but these are all seniors, and it seems almost criminal to let them graduate as engineers without ever having been taught to think like engineers. I’m going to end up working them pretty hard, trying to get them up to speed in circuits, writing design reports, and how-to-think-like-an-engineer in just 7 more weeks.

I’ve been trying to pin down just what I mean by “how to think like an engineer”—something I’ll need to have at least some handle on before I can teach students how to do it.  I have a few vague ideas of what it means, but not anything crisp and clear enough to serve as a design guideline for planning my teaching.  Here are a few random thoughts:

  • Engineers pay attention to details.  It isn’t enough to have the right general idea—the execution has to be right also.
  • Engineering is about solving new problems, not memorizing solutions to old ones. It is better to have a few general principles that can be used over and over in different contexts than an encyclopedia full of formulas and protocols for every known situation.  If the problem has already been solved, it isn’t really an engineering problem.
  • Design is often about a tradeoff between conflicting goals, or between goals and constraints that limit what can be done.
  • Sanity checks are essential.  Every schematic, every wiring connection, every computation should be subjected to quick checks for consistency.  Some of the checks are easy: Does every 2-terminal component on the schematic have two connections to it? Is every pin on the chip accounted for—either wired up or labeled as not connected? Do the units for the computation match (ΩF=seconds, not Hz)? Does replacing the ammeter with a short-circuit change the expected behavior of the circuit?  …
  • Design is not a process of randomly trying things until something happens to work, but of carefully planning how things should behave.
    Don’t get me wrong—I’m not denying the role that chance and luck can play in engineering. There are occasional serendipitous events, where something works despite mistaken thinking, but that is rare. My first patent, the plucked-string algorithm that Alex Strong and I developed, resulted from just such a serendipity—Alex had been attempting to implement something and had mistakenly added an averaging of two adjacent samples. My main contribution was to figure out why that mistake produced much more interesting results than what he had originally set out to do.  But even with that initial serendipity, we spent a couple of years doing careful design—coming up with different software and hardware implementations for the plucked-string algorithm (which we called the Digitar algorithm, but is now more commonly called the Karplus-Strong algorithm).  I even took a  VLSI design course so that we could implement the algorithm as a custom chip—a course that shaped my career for the next 15 years.
  • Debugging is a process of thinking carefully about why the circuit, program, device, system, … is not doing what you want, and what modifications to it should change it in the desired manner. It is even less random than design—one has to build useful mental models of the failing system that explain the cause of the failure, then determine modifications that would fix that mental model, before trying fixes in the real world.
  • There are no right models, just useful models and useless ones.  (Even that’s wrong: there are more useful and less useful models, where the usefulness depends on what questions you need to ask of the model.)
  • Quick estimates from rules of thumb and extreme cases are handy.  A capacitor is an open circuit at DC and a short circuit at ∞ Hz, so low-frequency and high-frequency behavior of RC circuits is easy to estimate without much computation.
  • Empiricism rules: the answer to the question “Is this right?” is almost always “Try it and see!”

How can you tell if someone thinks like an engineer (or will learn to think like one)?

Some people point to kids who like to take things apart to see how they work, and say that they are budding engineers.  While taking things apart to see how they work is sometimes done by engineers, it isn’t the normal mode (they even call it “reverse engineering”, because it is backwards from what engineers usually do).  Scientists take things apart to see how they work—engineers put things together to make them work.

I posted about science vs. engineering 2½ years ago. In looking over that post, I see that even then I was thinking about the differences in training:

There is a distinct difference in the training one should give a student who is planning to be a scientist and one who is planning to be an engineer.  Sure, the basics are the same at the beginning (basic science, math, lab technique, computer programming, statistics, and so forth), but the engineer has to be taught how to design and debug, while the scientist has to be taught how to question dogma and discover new ideas.  These are not the same skills at all and both need substantial practice before people are competent at them.

For scientists, the tradition has been to devote the undergraduate years to acquiring basic knowledge, but not to practice being a scientist at all.  As a result it takes 5–7 years of grad school (and often several years of post doctoral training) to turn science undergrads into scientists. For engineers, the tradition has been to do 2–3 years of basic training, followed by 2–3 years of project work of gradually increasing complexity, culminating in either a B.S. or an M.S. degree.

The shorter training time for engineers means that it must be much more focused—you can’t hope that the students will pick up skills they need gradually as a by-product of years of doing something else (the way that scientists are trained). Instead, the specific design skills and group management skills need to be explicitly taught and practiced while the students are still undergrads.  This has a lot of consequences for curriculum design, as almost all junior and senior courses have to include design practice, and there needs to be at least one big project (preferably one too big for a single engineer to handle).  Explaining these curricular needs to faculty trained as scientists can be difficult—they want to leave all that to the grad curriculum or one-on-one training of postdocs.

I’m afraid that the bioengineering students in my circuits class have all been trained like scientists, with a huge number of courses in basic scientific knowledge, but almost no training in debugging or design practice. Hmm, that’s not quite fair.  Several of them have worked pretty intensively on debugging wet-lab protocols, though mostly in senior thesis projects, not in regular courses.

I can’t teach everything about “thinking like an engineer” in one course, even if I could articulate exacly what I meant by it.  I will try to give them problems that are puzzles, rather than rote application of formulas, and that emphasize design goals rather than analysis of what is already designed.  Since the traditional circuits course is almost all analysis with very little design, this makes the crafting of this course into an engineering design challenge: I need to create something new, not just copy exercises and lesson plans from elsewhere.

Unfortunately, I’m still wrestling with the precise design goals of the course and the constraints imposed by the time available and the prior training of the students. I had taken “thinking like an engineer” for granted earlier, for example, and not thought of it as a pedagogical goal for the course.  Now I need to rethink how I present material and how I get students to wrestle with it so that their lifelong habits of thought are shifted.  I was thinking I would be adding a couple of new tools (from circuit design) to their toolbox of mental models, rather than having them build a whole new toolbox.

Having to debug a course design is a lot like other engineering design challenges, except that I need to debug the course while it is running—I can’t turn it off, restructure it, and turn it back on again.  The problem I have right now is that my mental model of the material and how the students would interact with it is not quite right (I get too many surprises), and I’m trying to decide if it is a good enough model to continue with, or whether I need to find a substantially different mental model in order to debug the course.

Perhaps my new view of needing to teach “thinking like an engineer” is wrong—maybe the problems I’m seeing are not that fundamental, but are just unfamiliarity with the material, and that a little more practice to get comfortable with it is all they need.  The pedagogical interventions I’d need to do are quite different in these two views of the problem, and I’m not sure how to tell which mental model is more useful.

Does anyone who got this far in my post-midnight rambling have any suggestions for me?

2012 October 12

UCSC likes research influence

Last week’s press release from UCSC touts one of their favorite statistics: research influence.  [UCSC still in top three for research influence in world university rankings]

The idea is simple—count citations and do some mysterious (and apparently undocumented) correction for fields and perhaps other things.  The press release claims that the research influence number is citations/paper, but I think it might be normalized in some other way—I can’t tell from the documentation. The website that reports the results has some of the worst documentation of methodology I’ve seen.  For that matter, a lot of the assumptions of the statistics are really dubious (like that high doctorate-to-bachelor’s ratios improve teaching).

So despite the really questionable data and interpretation of the Times Higher Education ranking, UCSC loves that we have a lot of citations.  I guess I’m doing my part (Google Scholar lists me as having 6243 citations, 2584 since 2007), but my citations peaked in 2005 and have been dropping off a bit since then.  I’ve mainly been publishing as a collaborator lately, and most of those papers have pretty small audiences.  I think that I may be rather low in the rankings for our department, since a lot of the highly cited genome papers have Jim Kent and David Haussler as authors.  They’ve also built tools that are used by 100s of times as many people as my tools are.

The way to get huge citation numbers is to produce a tool that everyone uses, and ask them all to cite the same paper.  No one will actually read the paper, but you’ll get huge citation numbers.  My most cited paper (over 1000 citations) is almost certainly not being read that much. This may seem unfair, getting citations for a paper that no one reads, but if the tool is really used by a lot of people, it is having a huge research influence, so the measure is not really being corrupted.

On the other hand, my most influential work (a plucked-string synthesis algorithm) has only about 300 citations, but is mentioned on over 34,000 web pages (according to Google) and is incorporated into many computer programs and synthesizers, so citation counts don’t tell the full story of influence.

Still, it’s nice to see our campus get some good news, since so much of what we get is bad news about the budget.

2011 October 8

Making WAV files from C programs

Filed under: Digital music — gasstationwithoutpumps @ 21:03
Tags: ,

I’m going to try embedding some short pieces of code in this post, and later work out a better way of distributing larger blocks of code.

The code I want to share today consists of a small C file and the associated header for creating WAV files for producing sounds on a laptop or desktop computer. This is not a full-featured WAV file module: the format has a lot of options and I didn’t want the complexity of dealing with all of them. I just wanted to output monophonic sound with a reasonable sampling rate.

/* make_wav.h
 * Fri Jun 18 17:06:02 PDT 2010 Kevin Karplus

#ifndef MAKE_WAV_H
#define MAKE_WAV_H

void write_wav(char * filename, unsigned long num_samples, short int * data, int s_rate);
	/* open a file named filename, write signed 16-bit values as a
		monoaural WAV file at the specified sampling rate
		and close the file



/* make_wav.c
 * Creates a WAV file from an array of ints.
 * Output is monophonic, signed 16-bit samples
 * copyright
 * Fri Jun 18 16:36:23 PDT 2010 Kevin Karplus
 * Creative Commons license Attribution-NonCommercial

#include <stdio.h>
#include <assert.h>

#include "make_wav.h"

void write_little_endian(unsigned int word, int num_bytes, FILE *wav_file)
    unsigned buf;
    {   buf = word & 0xff;
    	fwrite(&buf, 1,1, wav_file);
	word >>= 8;

/* information about the WAV file format from

void write_wav(char * filename, unsigned long num_samples, short int * data, int s_rate)
    FILE* wav_file;
    unsigned int sample_rate;
    unsigned int num_channels;
    unsigned int bytes_per_sample;
    unsigned int byte_rate;
    unsigned long i;	/* counter for samples */

    num_channels = 1;	/* monoaural */
    bytes_per_sample = 2;

    if (s_rate<=0) sample_rate = 44100;
    else sample_rate = (unsigned int) s_rate;

    byte_rate = sample_rate*num_channels*bytes_per_sample;

    wav_file = fopen(filename, "w");
    assert(wav_file);	/* make sure it opened */

    /* write RIFF header */
    fwrite("RIFF", 1, 4, wav_file);
    write_little_endian(36 + bytes_per_sample* num_samples*num_channels, 4, wav_file);
    fwrite("WAVE", 1, 4, wav_file);

    /* write fmt  subchunk */
    fwrite("fmt ", 1, 4, wav_file);
    write_little_endian(16, 4, wav_file);	/* SubChunk1Size is 16 */
    write_little_endian(1, 2, wav_file);	/* PCM is format 1 */
    write_little_endian(num_channels, 2, wav_file);
    write_little_endian(sample_rate, 4, wav_file);
    write_little_endian(byte_rate, 4, wav_file);
    write_little_endian(num_channels*bytes_per_sample, 2, wav_file);  /* block align */
    write_little_endian(8*bytes_per_sample, 2, wav_file);  /* bits/sample */

    /* write data subchunk */
    fwrite("data", 1, 4, wav_file);
    write_little_endian(bytes_per_sample* num_samples*num_channels, 4, wav_file);
    for (i=0; i< num_samples; i++)
    { 	write_little_endian((unsigned int)(data[i]),bytes_per_sample, wav_file);


Note that the above code is not a full program, just a tiny library routine that can be used to generate WAV files. Here is a test program to generate sine waves (inefficiently) to see if the program works. Once you have the basic idea, you can write arbitrary programs to generate WAV files and play them back with QuickTime Player, RealPlayer, Audacity, or any of several other sound-playing programs.  This is really old-school computer music, from the days when computers were so slow that quality sounds could not be generated in real time.  It provides a good way to get started in learning the algorithms, though, as you don’t need to worry about efficiency or all the details needed to compute samples and provide them to a DAC at exactly the right rate.

/* test_make_wav.c
 * Fri Jun 18 17:13:19 PDT 2010 Kevin Karplus
 * Test program for the write_wav function in make_wav.c

#include <math.h>
#include "make_wav.h"

#define S_RATE	(44100)
#define BUF_SIZE (S_RATE*2)	/* 2 second buffer */

int buffer[BUF_SIZE];

int main(int argc, char ** argv)
    int i;
    float t;
    float amplitude = 32000;
    float freq_Hz = 440;
    float phase=0;

    float freq_radians_per_sample = freq_Hz*2*M_PI/S_RATE;

    /* fill buffer with a sine wave */
    for (i=0; i<BUF_SIZE; i++)
        phase += freq_radians_per_sample;
	buffer[i] = (int)(amplitude * sin(phase));

    write_wav("test.wav", BUF_SIZE, buffer, S_RATE);

    return 0;

2011 June 15

Hold the presses! Can’t distribute software!

Filed under: Digital music,Software — gasstationwithoutpumps @ 03:15

This post was going to be a release of a .c file and a .h file for making WAV files from C programs. Unfortunately, the blog site provides no convenient way for distributing software files. The file extensions they allow are limited to jpg, jpeg, png, gif, pdf, doc, ppt, odt, pptx, docx, pps, ppsx, xls, xlsx for “security reasons”. Allowing docx and prohibiting plain text files clear has nothing to do with security, but trying to support the Microsoft monopoly. I may need to seriously rethink whether I want to run this blog on, as I’ll be wanting to include file types that they do not support (program source code, perhaps schematics or PC board layouts).

Maybe it is time to abandon and find a friendlier blogging site that allows reasonable other file formats.

UPDATE: 8 October 2011 does have a perfectly fine way to show code snippets, explained on Posting Source Code.  I don’t think that documentation existed when I first posted this message—at least I couldn’t find it then.  The method is actually fairly simple: just put [sourcecode language=”python”] and [/sourcecode] around the code (with any of 28 different formatting sytles, including “cpp” for c++ and “text” for generic formatting).  So I can do snippets fairly easily, though multi-file programs may be a pain to distribute.  Downloading the snippets to the clipboard is easy, but downloading to files is not supported.  Still, that is probably good enough for this blog.

Next Page »

%d bloggers like this: