Category Archives: software

Debugging with the Saleae Logic

I just got a Saleae Logic analyzer and it’s immediately been useful. The software is pretty sparse but it’s easy to use.

Below is a screen shot of the traffic between an FT220X USB interface IC and an AVR. Here we can see a glitch at the end of the third clock period. The third clock is the bus turn around phase. The bug here is that I’m tristating the AVR’s data lines at the very end of the clock period.

glitch

The fix was simple:

glitchfix

The Saleae device is better than I expected given some of the reviews I’ve read. It doesn’t do much so there isn’t anything to learn. Software installation was easy and didn’t hog a ton of space on the PC. It does have some quirks. I get an error dialog every time I plug the device into the computer, but everything works fine. When it’s capturing it doesn’t update the memory usage counter as it goes along. By default the program uses an Aero theme which has the application window border areas translucent. Since the time line text, options menu and other things have white text, this means you can’t see them if the application window is sitting on top of a white surface. Fortunately you can turn off the Aero theme. You’ll need to float the app window over a dark surface to find the options menu to do that if you don’t know where it is at first… You can reorder the channels but you have to do so through a right click menu for each one, and you can only move them up or down one at a time which is annoying. It would be nice if you could simply drag them around. The T1 and T2 cursors can get stuck outside the graph on the right side and are unaccessable if you click in the wrong area. To get the back you have to zoom into the graph and reselect the T1 and T2 labels on the right side of the app window.

Minor annoyances. Once you position and label your channels, you can save the profile and then recall it later. That’s handy and works well.

Overall I’m fairly impressed with it. I was able to immediately hunt down problems the moment I had it out of the box and setup. It paid for itself the first day I used it. I have some i2c devices to work with after I finish ironing out this FT1248 interface. It will be interesting to see how useful the protocol analysis tools are with this thing.

A new project is born

I’ve been busy this past week on a new project centered around a Max V CPLD. Schematic isn’t final yet. Just about every time I think I have it nailed down, I find out that I could have used a cheaper part, a smaller part or a certain part ends up not meeting the requirements for one reason or another. Selecting an LDO turned out to be a chore. The one in the schematic below is being swapped out for another. Do I use two, or get one with dual output? Fixed, or adjustable output? Does the dropout line up with my input power requirements, etc? Is the one I selected a common device that’s likely to be available when it’s time to go into production, or is it something that just happened to be in stock, never to be seen again after it runs out? A part that’s unavailable means you have to wait for it to become available again, could be weeks, months, or never. Or it could mean you pay a high price to someone who has it. Or make a change to the PCB design to fit another part, that adds an extra month to the project.

The ATtiny40 I picked looked pretty good. Small, cheap, just enough IO pins to get the job done. Downsides are no on chip debugging support, slave only i2c, not supported by a lot of programmers. I was aware of the first two, they don’t bother me too much. Not working with a wide variety of programmers is a bummer. I’m swapping that out with an ATtiny48 which supports DebugWIRE, has proper i2c support and is on the supported devices list for the AVR Dragon. It costs 30 cents more, but I compensated for it by down costing another area of the circuit so I’m still within my parts budget. I’ll put those extra pins to good use, also, the pin layout is pretty nice.

I’d like to use a smaller, cheaper, lower power oscillator. There probably is one out there, but I haven’t found it. I’m using a 50MHz part because that’s what I need for some of my projects and there is no PLL on the Altera CPLDs. I wonder why they didn’t put one on there, it would be a nice thing to have. Would that significantly add to the cost of the device? Do PLL blocks take up a lot of space on the die? That would be an interesting question to ask an IC designer.

rtschematic

I’ll be ordering most of the parts this evening. By the time I get them in the mail I should have most of the PCB laid out. When that’s done I’ll print out the top layer to check that I got the pads laid out correctly for the parts that weren’t in the library (which was most of them). After that I’ll have some prototype boards made.

copperrt

The incident with the microwave

I found a beat up microwave in the trash the other day. Looks like the neighborhood kids had fun smashing it up. I took the opportunity to rip the display module from it.

In the FPGA projects I’m working on, it would be useful to have a simple hex display and some buttons for input, so I built one. It takes bytes in from a serial connection and displays them on a 4 segment LED module. Below is a picture of the assembled device.

serialhexAnd here is the schematic:

serhexled

Here is the device in action:

And here is the source code:

// This program reads bytes from an RS232 port and displays them in
// hex on a 4 segment LED module. It relies on the UART library that is
// included with the mikroC compiler. This program targets a PIC16f917.
// Source released as Public Domain
// 2013 Brian Miller

// segment commons
const segz = 0b01111111;
const segw = 0b10111111;
const segy = 0b11011111;
const segx = 0b11101111;

// segment pieces
const pa = 0b10000000;
const pb = 0b00000010;
const pc = 0b01000000;
const pd = 0b00000001;
const pe = 0b00000100;
const pf = 0b00100000;
const pg = 0b00001000;

// glyph definitons
const d0 = pa + pb + pc + pe + pf + pg ;
const d1 = pc + pf ;
const d2 = pa + pc + pd+ pe + pg ;
const d3 = pa + pc + pd + pf + pg ;
const d4 = pb + pc + pd + pf ;
const d5 = pa + pb + pd + pf + pg ;
const d6 = pa + pb + pd + pe + pf + pg ;
const d7 = pa + pb + pc + pf ;
const d8 = pa + pb + pc + pd + pe + pf + pg ;
const d9 = pa + pb + pc + pd + pf ;
const da = pa + pb + pc + +pd + pe + pf ;
const db = pb + pd + pe + pf + pg ;
const ddc = pa + pb + pe + pg ;
const dd = pc + pd + pe + pf + pg ;
const de = pa + pb + pd + pe + pg ;
const df = pa + pb + pd + pe ;

// returns the glyph code for the specified nybble in the word
unsigned char retchar ( unsigned int a, unsigned int pos){
         unsigned int tst ;
         switch (pos){
                case 0 :
                     tst = ( a << 12 ) >> 12 ;
                     break;
                case 1:
                     tst = ( a << 8 ) >> 12 ;
                     break;
                case 2:
                     tst = ( a << 4 ) >> 12 ;
                     break;
                case 3:
                     tst = a >> 12 ;
                     break;
         }
         switch ( tst){
                case 0 : return d0 ;
                case 1 : return d1 ;
                case 2 : return d2 ;
                case 3 : return d3;
                case 4 : return d4 ;
                case 5 : return d5 ;
                case 6 : return d6 ;
                case 7 : return d7 ;
                case 8 : return d8 ;
                case 9 : return d9 ;
                case 10 : return da ;
                case 11 : return db ;
                case 12 : return ddc ;
                case 13 : return dd ;
                case 14 : return de ;
                case 15 : return df ;
         }
}

void main() {
     // serial input
     unsigned int inDat;
     
     // individual display digits
     unsigned char s0, s1, s2, s3;
     
     // kp limits button sampling, i selects the digit to be refreshed
     unsigned char i;
     unsigned char kp;
     
     ANSEL = 0 ; // AN pins as digital
     CMCON0 = 0 ; // turn off comparators

     // Segment port
     TRISA = 0 ;
     // Commons port
     TRISB = 0 ;
     // Button inputs
     TRISD = 0xFF;
     
     // lib doc suggests waiting 100ms to allow serial port to settle
     UART1_Init(19200); // 19200 baud
     Delay_ms(100);
     
     // set all digits to 0 on startup
     s0 = d0;
     s1 = d0;
     s2 = d0;
     s3 = d0;
     
     inDat=0;
     i = 0 ;
     kp = 0;

     for (;;){
         // shift in a byte if there is one waiting
         if (UART1_Data_Ready()){
            inDat = inDat << 8 ;
            inDat = inDat + UART1_Read();
            s0 = retchar (inDat, 0);
            s1 = retchar (inDat, 1);
            s2 = retchar (inDat, 2);
            s3 = retchar (inDat, 3);
         }
         // if one or more buttons is pressed and sample limiter is 0
         // then write the button state to the serial port
         if ( kp++ == 0 && PORTD != 0 ) {
            UART1_Write(PORTD);
         }
         // we only update one segment per iteration so that each segment
         // stays lit an equal ammount of time.
         switch (i++){
                case 0:
                     PORTB = 0xFF;
                     PORTA = s0 ;
                     PORTB = segx;
                     break;
                case 1:
                     PORTB = 0xFF;
                     PORTA = s1 ;
                     PORTB = segy;
                     break;
                case 2:
                     PORTB = 0xFF;
                     PORTA = s2;
                     PORTB = segw;
                     break;
                case 3:
                     i=0;
                     PORTB = 0xFF;
                     PORTA = s3 ;
                     PORTB = segz;
                     break;
         }
     }
}

Syntax highlighting with custom Emacs generic mode

lichen_emacs_mode
I was expecting it to be difficult to get syntax highlighting setup. A quick look on google reveals a truck load of pages on how to do it when searching for “emacs generic mode”.  I’d like the labels to have a different color so they stand out from constants and variables, but this is good enough as it is.

The image to the left is a screen shot of Emacs showing off the highlighting.

The assembler is coming along pretty nicely. Still not sure how I ultimately want to handle looping constructs. I briefly thought about adding a third stack for local variables. I will end up doing that, but it won’t be part of the CPU design.

I’m now up to around 80 instructions. Most of the increase was due to adding in support for signed numbers. I added in some instructions for bit shifting, rotating and directly reading and writing individual bits.

Here’s the highlighting chunk in my emacs init file:

(require 'generic-x)

(define-generic-mode
    'lichen-mode
  '("//")
  '( "add" "sub" "div" "mul" "sadd" "ssub" "sdiv" "smul" 
     "and" "or" "xor" "not" "bsl" "bsr" "sbsl" "sbsr" 
     "bsnl" "bsnr" "sbsnl" "sbsnr" "rotl" "rotr"
     "nop" "inc" "dec" "drop" "dropa" "swap" "roll" 
     "a2d" "d2a" "dup" "push" "pushb" "spushb" "pusha"
     "store" "storei" "storeb" "fetch" "fetchb" "sfetchb"
     "incm" "incmb" "decm" "decmb" "bfetch" "bfetchb"
     "equal" "less" "great" "equalm" "lessm" "greatm" "equalmb"
     "lessmb" "greatmb" "equali" "lessi" "greati" "sless"
     "sgreat" "slessm" "sgreatm" "slessmb" "slessi" "sgreati" 
     "call" "callt" "calli" "callit" "jmp" "jmpt" "jmpi" "jmpit"
     "ret" "halt" "reset" )
  '(
    ("*" . 'font-lock-builtin-face)
    ("**" . 'font-lock-builtin-face)
    ("(" . 'font-lock-warning-face)
    (")" . 'font-lock-warning-face)
    (">" . 'font-lock-builtin-face)
    (">>" . 'font-lock-builtin-face)
    ("++" . 'font-lock-builtin-face)
    ("const" . 'font-lock-variable-name-face)
    ("file" . 'font-lock-variable-name-face)
    ("include" . 'font-lock-variable-name-face)
    ("db" . 'font-lock-variable-name-face)
    ("dw" . 'font-lock-variable-name-face)
    ("ddw" . 'font-lock-variable-name-face)
    ("dsn" . 'font-lock-variable-name-face)
    ("ds" . 'font-lock-variable-name-face)
    (":" . 'font-lock-builtin-face))
  '("\\.lasm$")
  nil
  "lichen assembler mode"
)