Monthly Archives: April 2013

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;
         }
     }
}