Some small progress on the 68K single board computer: I have a 68008 working in “free run” mode on a breadboard. Free run isn’t really a processor mode, it’s just what happens when you connect all the CPU data lines to ground, hardwire the control signals to default states, and connect a clock oscillator. The 68K acts like there’s a device present that spans the entire address space and is filled entirely with zeroes, so it initializes the program counter to 0 and starts executing a long series of instruction 0×0000, which happens to be the 68K opcode for ORI.B #0,D0. As the PC advances through the address space, the CPU address bus counts up from zero. By connecting an LED or a logic probe to one of the higher address lines, you can see it blink as proof that the processor is alive.
OK, maybe it’s not very exciting, but it’s a fun little experiment you can do with just a naked 68K CPU and a clock oscillator. No RAM or ROM or other hardware is needed. I recently discovered a similar free run demo for Brian Benchoff’s 68K-based single-board computer for Hackaday, although that project appears to have stalled out afterwards. It seems that blinking an LED in free run mode is a rite of passage for 68K projects.
Along the way to this demo, I discovered that reset handling for the 68K is annoyingly complicated. You might think there’s just a /RESET input to the CPU, and you could force /RESET low to reset the processor, but that’s not how it works. The 68K has a /RESET and a /HALT, and to reset the processor you need to drive both of them low. But these pins are actually bidirectional I/Os, and sometimes the CPU itself will drive one of them low! For example /HALT will be driven low after a double bus fault. So the external reset circuitry can’t actively drive these signals high without causing damage, it can only actively drive them low or let them be passively pulled high by a pull-up resistor.
This makes it impossible to design a simple reset circuit where /RESET and /HALT are both driven low when a single button is pushed. The single “master reset” signal would have to be connected to both /RESET and /HALT, effectively tying those signals together. If the CPU later drove /HALT low due to a fault, that would cause it to see /RESET low too, and so the CPU would reset itself. What a mess. After thinking in circles for a while, I concluded the only solution is to use an open collector buffer like 74LS07, or discrete transistors, so each signal can be independently pulled low in response to a single master reset signal, then allowed to float high. I don’t have any of those parts handy, so my breadboard circuit has two separate push buttons, and both must be pushed at the same time to force a CPU reset.Read 4 comments and join the conversation
Hackers of a certain age love the 68000 family of CPUs, and I’ve begun sketching out designs for a 68K-based single board computer. Take a vintage off-the-shelf CPU, add ROM and RAM and an SD card and some type of I/O, and Bob’s your uncle! I plan to start with bare metal programming to test out the hardware and peripherals, then try to get text mode Linux running. I/O will probably be exclusively through a serial port, but I hope to also include a USB controller to see what I can make happen through Linux. For inspiration and direction, I’m drawing heavily from Simon Ferber’s (Kiwi) and Luis Alves’ 68K-based homebrew designs. Here we go!
I have an old MC68008P8 CPU gathering dust in a drawer that would be perfect. The P8 version is rated for 8 MHz, and the 68008 is essentially a 68000 with an 8-bit data bus instead of the standard 16-bit bus. That means its memory throughput is only half the 68000′s, and since it has no cache and most instructions require a memory access, its performance is only slightly better than half that of a 68000 at the same clock speed. But what it lacks in speed, it makes up in simplicity. The 68000 requires twice as many data lines to be routed, and either twice as many RAM and ROM chips, or physically larger chips with 16-bit interfaces.
Luis Alves’ machine used a regular 68000 at 20 MHz, and got decent performance running ucLinux. An 8 MHz 68008 will only have about 20-25% of the performance of that system, which might be a problem. Maybe I should look into the availability of suitable 16-bit ROM and RAM chips before making a final decision.
ROM and RAM
Speaking of ROM and RAM, there’s not much to say here beyond the question of bus width. Pretty much any Flash ROM and SRAM should be more than fast enough to keep up with this CPU. Something like a few MB of ROM and 4-16 MB of RAM should be OK. Thinking ahead to Linux, if I can store the kernel and other programs in ROM and execute the code from there, I can reduce the amount of RAM I’ll need. As a size reference, the kernel for my Raspberry Pi is just over 3 MB, so that’s not unreasonable to put in a ROM. There’s something called XIP (execute in place) that’s supposed to make this possible, but I have no idea how difficult it might be to get working.
It’s probably safer to assume a bootloader will copy the kernel into RAM and it will execute from there, but in that case I might as well write a slightly smarter bootloader that copies the kernel from SD card to RAM instead. Perhaps ROM only needs to be large enough for a minimal bootloader – a bootloader loader – say 512 KB or less.
I’ve been assuming the RAM will be SRAM, because it’s easy to work with and it’s what I’ve used for all my past projects. I know DRAM isn’t that complicated, but every time I read about RAS and CAS and DRAM refresh, my eyes glaze over and I just pay $2 more to buy SRAM. That’s fine for smaller RAM sizes, but if I end up going as high as 8 or 16 MB, it could become a space and cost problem. Large capacity SRAMs are rare, and fitting 8 or 16 smaller SRAM chips on the board would be painful.
The serial connection could be a simple UART, but something like one of FTDI’s common USB-to-serial converters probably makes more sense. Or a USB-to-serial/parallel converter like the FTDI 245, which has a USB interface to the PC and appears as a virtual serial port, but presents a parallel interface to the 68K CPU. That should be a little easier to work with, and faster when transferring large amounts of data. The ’245 also has a decent-size buffer and hardware flow control, which an old-school UART might lack.
CPLD or FPGA
Something’s got to decode memory addresses to determine which RAM or ROM or other chip to enable for a particular memory access. If that were the only requirement, address decoding could be hard-wired using a few 7400-series logic chips. But by doing the decoding in a large CPLD or small FPGA instead, other glue logic functions could be consolidated as well. These include things like reset handling, simple timers, interrupts, GPIOs for buttons and LEDs, and SPI/I2C conversion for peripherals.
A CPLD is strongly preferred over an FPGA, because the CPLD’s configuration is held in its internal non-volatile memory. An FPGA’s configuration is RAM-based, so it would require something else to configure it every time the board boots up. And if the FPGA functioned as the CPU’s address decoder, the CPU would be non-functional during this time, and couldn’t do the boot-time FPGA configuration. Some other device like an on-board microcontroller would have to do the job, adding to the system complexity. CPLD’s are much simpler in this respect, but are limited in the amount of logic they can implement. My combined address decoder / reset handler / timer / interrupt controller / GPIO / SPI / I2C monster may be too complex to fit in a CPLD.
While external storage isn’t required, especially for experimental bare metal programs stored in ROM, some kind of external storage for Linux is a practical necessity. Fortunately the hardware interface to SD memory cards is very simple, and I’ve done it before as part of my Floppy Emu project. All that’s needed is a few pins to connect an SPI interface, and the rest happens in software. The 68K CPU doesn’t have an SPI interface, of course, but the CPLD/FPGA can easily implement a byte-wide parallel to SPI interface.
Ethernet isn’t really required either, but what fun is a Linux installation without a network connection? The Microchip ENC28J60 is a popular and well-supported chip for creating a wired ethernet connection. It uses an SPI interface for talking to the CPU, and there’s Arduino example code available for it, which I could probably decipher. There’s also driver support in newer versions of the Linux kernel. For ease of use, Sparkfun and other suppliers sell a small module based on the ENC28J60 that also includes the required caps, resistors, and inductors, as well as the ethernet jack.
The Maxim MAX3421E is a USB Host controller chip with an SPI interface. It’s the basis of several Arduino USB Host shields, and I could use the associated Arduino libraries for examples of how to get it working. It looks like Linux kernel support was just recently added, in kernel 3.16. I’m not sure I could actually get this working, but it would be cool if I could directly hook up a USB keyboard or thumb drive or other peripheral.
It might seem that using SPI-based solutions for external storage, ethernet, and USB would be a performance bottleneck, since SPI data is transferred one bit at a time in serial fashion. If you check the math, however, the 20 MHz SPI speeds of these devices is still enough to keep up with an 8 MHz 68008. A 20 MHz SPI connection can theoretically transfer 20 million bits/second, or 2.5 million bytes/second. An 8 MHz 68008 needs 4 clock cycles for a single byte-wide memory transfer, giving it a theoretical max of 2 million bytes/second – less than the SPI limit. But it’s actually even worse than that, when you consider the two memory transfers (8 clock cycles) needed to load the 16-bit CPU instruction that performs the SPI transfer. So even an unrolled loop writing a constant value to SPI could do no better than one byte sent per 12 clock cycles, or 667Kbps. In practice, the overhead of serializing and unserializing data for SPI will never be a bottleneck on this system.
With a mix of old and new hardware in the system, 5V to 3.3V level conversion will need to be performed somewhere. The fewer places, the better. The 68008 is a 5V part, and the ROM and RAM can probably be found in either 5V or 3.3V varieties. The CPLD or FPGA will run at 3.3V, but may have 5V tolerant inputs depending on the specific part used. The ethernet and serial chips are 3.3V with 5V tolerant inputs, and I think the USB chip is too. SD cards are 3.3V devices and not 5V tolerant, so conversion will be needed there. If all the 3.3V devices are connected to the CPLD instead of directly to the CPU, and the CPLD is 5V tolerant, then it can serve as the system level converter instead of requiring dedicated level conversion chips. Unfortunately I think few CPLDs are 5V tolerant, and even fewer FPGAs, and the ones that are tend to be old and obsolete.
How does the Flash ROM get programmed? Once the system is working, I think a bootloader can copy itself from ROM to RAM, then run from RAM while it updates the ROM contents. But for initial board setup, the ROM will need to be initialized with a external programmer hardware.
How does the CPLD get configured? I don’t think there’s any way the CPU can do this, so the board will need a JTAG header and a Xilinx/Altera programming cable to update the CPLD configuration.
A few pushbuttons would be useful: at least one for reset, and one to trigger an interrupt. Maybe a run/stop slide switch too – though I’m not sure how I’d use it. Some status LEDs or a 7 segment LED display would be helpful for debugging initial hardware setup, but probably useless after that.
It’s probably a good idea to include some expansion headers, for things I didn’t consider originally. If the header provides access to the entire data bus, some lower bits of the address bus, the CPU read/write control signals, and a few unused CPLD pins, that should be enough to support some extra external hardware.Read 15 comments and join the conversation
The other day I wrote about designing a new homebrew CPU, and getting Linux running on it. After looking deeper into the idea, it’s just not realistic to port Linux to a CPU that I built myself, even a low-end version like ucLinux. At a minimum the CPU would need 16-bit registers (or is it 32-bit?) and hardware support for supervisor and user modes. To get usable performance (typical Linux command line programs running at interactive speeds) it would probably also need a larger number of registers, things like hardware multiply and divide instructions, and at least a small amount of cache. None of that’s impossible, but it would add lots of additional chips and interconnects, and it’s probably out of range of what I can expect to build from a handful of discrete logic chips. My BMOW1 CPU was nowhere near that capable, yet was definitely pushing the upper limits of what I have the time and desire to build by hand.
I could design my CPU in VHDL or a hardware description language, and program it into an FPGA, similar to what I did with my Tiny CPU. That holds much less interest for me, though. There are already lots of FPGA-based CPU soft cores, including ones from the FPGA vendors themselves, and it’s a path that just doesn’t excite me very much.
What about a simpler OS? ELKS is a minimal Linux-derivative originally designed for 8086 computers and should have very modest requirements. It looks nearly abandoned, though, and would probably be difficult to find information and support to help get it going. There’s also Minix, which should run on very low-end systems. It seems better supported than ELKS, but there’s still not much info available about it, and the latest Minix 3.0 appears aimed towards higher-end CPUs. FreeRTOS looks very lightweight and could probably run on a very simple CPU. But from what I can tell it’s not really an operating system at all, it’s just a thread scheduling library. There are no included applications nor even a command shell.
When it comes down to it, I just don’t want to spend the time and energy it would take to create a CPU capable of running any of these. Maybe someday, but not now.
That still leaves me with a couple of related projects that would be interesting to pursue. The first is constructing a single board computer using an old commercially-available CPU, and getting Linux running on that. A great example is this homebrew 68000 system built on a breadboard and running ucLinux. That could be a fun project – complicated, but not overwhelming. I even have a couple of DIP 68000 CPUs in a box somewhere that I could use. Perhaps this could even further the goals of my long-dormant Plus Too project. Or maybe try using a simple ARM CPU, or even an ARM-based microcontroller with some extra external memory. This would be an interesting hardware exercise as well as a deep dive into Linux internals and Linux porting.
The second path is extending an existing C compiler (likely gcc or llvm) to support a homebrew CPU, either one of my existing CPU designs or a new one. The BMOW1 CPU is maybe almost capable enough to handle simple C programs. A few additional registers and instructions, and I think it would be there. It would be predominantly a software project related to how compilers work. This interests me too, though less so. I see the creation of a cross-compiler more as a means to supporting a CPU project, rather than as a fun project in itself.
So many ideas, so little time!Read 2 comments and join the conversation
The revision 4 Floppy Emu cases are here, and they look great! Clear and black acrylic in different layouts, birch plywood, and chocolate-colored hardboard. I’m having too much fun putting these together. The purpose of revision 4 was to test a few layout tweaks and a sampling of different materials, so I could decide which one to get manufactured in larger quantities. The layout changes are probably the most important, but first let’s talk about materials.
First is a birch plywood. It’s actually just a thin birch veneer over some kind of filler layer, but it still looks very nice. You can see the veneer layers when you look at the board edge-on, and the edges are quite dark in color compared to the face of the board. This gives the case a high-contrast look. The engraved logo and text came out well, although they probably could have been a bit darker. The areas of the the board near the holes and corners are baked a darker shade of brown from the heat of the laser. The white case screws look decent with the light birch, though it’s not the best match. Overall the plywood case came out well, but I can’t say it’s my favorite.
Second up is hardboard, which is just a higher-density version of the ubiquitous MDF fiberboard. You might think fiberboard is icky, but this case came out great and is easily my favorite. The faces are a dark chocolate brown color, while the edges are near black, and the combination looks nice together. The black case screws accent it nicely too. The engraved logo and text are clearly visible, yet still understated. The quality of the engraving is also extremely sharp and crisp. There’s no darkening of the board near holes and corners, like occurred with the plywood. The one big drawback of hardboard is that it requires more than twice as much laser time to cut than the other materials do, which increases its cost. If I sold a hardboard case, it would have to be for $4 or so more than a case made from acrylic or plywood.
Black acrylic came out well too, and as expected it’s very similar to the previous cases I did in clear acrylic. I’m not in love with it, though. It’s very glossy, and it shows every fingerprint and smudge. The engraving is pretty good, but it’s like matte gray set against shiny black, and is difficult to see from some angles. Maybe it’s good… I can’t decide.
The new clear acrylic case is almost identical to the old one, except I’ve increased the sizes of the finger joints from 4 mm (as shown on the black case above) to 18 mm. This gives the edges a much less busy look, and helps the pieces fit together more easily. Clear acrylic shows fingerprints too, though not as much as black. And everybody likes clear, right?
I don’t have photos of the layout changes, but they’ll help save manufacturing dollars and assembly headaches. Believe it or not, going from 4 mm to 18 mm finger joints cuts almost $1 off the cost of the case. Fewer direction changes for the laser as it’s cutting means it can finish the job quicker. I also eliminated the two extra pieces I’d been using to accommodate boards with a built-in floppy connector, and instead there’s now a punch-out section on two of the boards that can be removed if necessary, opening a space for the connector. I tested the punch-outs in acrylic and they worked well – didn’t break loose accidentally, but could be broken off using only finger pressure when needed. I didn’t think to include punch-outs in the two wooden cases, but hopefully they’ll work equally well there.
I also made several tiny size adjustments to help make the “swords” for the LEDs and buttons fit just right. And I didn’t quite get it perfect, but now I think I have the dimensions I need to nail it next time. The buttons have tiny nubs on them to help prevent them from slipping back through the top plate while you’re assembling the case. This worked pretty well, but wasn’t 100% reliable. I suspect it will still be necessary to use the tape trick during assembly that I described last time. Hopefully people won’t mind that too much.
Armed with all this information, I think I’m about ready to do a larger manufacturing run of at least a few dozen cases. Given what I saw from these, I’ll probably make the majority of them clear acrylic, and maybe make a few hardboard ones I’ll sell for a couple dollars more as “premium cases” or similar. Thanks to everyone who wrote in with their preferences and requests. Check back in about 10 days and I hope to have a stock of new cases ready to go!Read 1 comment and join the conversation
Wouldn’t it be cool to create a homebrew CPU architecture, then port Linux to it? I realize that single sentence probably implies a couple years’ worth of work, but that’s OK. A real, full-fledged OS running on a totally custom piece of hardware would be awesome! I’ve already designed and built homebrew CPUs several times before, though only one had anything that could charitably be called an “operating system”, and none of them were anywhere capable enough to run something as complex as Linux. What kind of minimum specs would a homebrew processor need to be capable of running a bare-bones text mode Linux? Core speed? Number and size of internal registers? Supervisor/user mode? MMU? How much RAM? What else?
There’s so much I don’t know, I don’t even know what I don’t know. That’s what makes it exciting. I’m perfectly comfortable as a Linux /user/, with a variety of random Unix-world experience going back 20 years to Sun Sparcstations. But I know next to nothing about how Linux (or other Unix flavors) are put together underneath – what exactly is the bootloader, the kernel, what is init, and all these other fun terms I hear tossed around. How do you go about porting Linux to a new board, a new CPU architecture?
Based on 2 minutes of exhaustive research, I’m looking at ucLinux as a starting point, rather than any regular desktop Linux. ucLinux is aimed at very low-end CPUs with no MMU, and “low end” will doubtless describe whatever I end up building. The related ucSimm module is a 16 MHz Dragonball CPU with 2MB of ROM and 8MB of RAM, so that already gives me an idea of where I need to aim for CPU specs. If I can get away with less, great. Bill Buzbee’s homemade Magic-1 runs Minix on a 4MHz custom 16-bit CPU with 4MB RAM.
To be candid, I’m a lot less excited about designing a 4th homemade CPU architecture than I am about porting an operating system to it. So as a starting point (and maybe a finishing point), it might make more sense to try porting Linux to an existing but obscure CPU or development board. That would get me familiar with the details and requirements of the porting process, which would help inform what features would be most valuable when I design my own CPU/board.
Assuming I do go forward with a homebrew CPU (or maybe try to augment the BMOW1 CPU), I’m still unclear where to even begin with porting Linux to it. The Linux kernel is available as source code, so presumably one of the first steps would be to modify and compile this code for the new CPU. That implies using a cross-compiler that runs on an x86 PC but outputs NewCPU code. So how do I make such a cross-compiler?
A few years back, I took a brief look at adding support for a new CPU architecture to gcc, but quickly gave up. It looked complicated and confusing, and I really had no idea what I was doing. Unfortunately, that’s probably where I need to start, since I’ll probably need a cross-compiling gcc to compile the kernel sources. Alternatively I could compile gcc from its own source code, using a different compiler, but then where would I get that other compiler? I had some limited success porting the Small C compiler to BMOW a few years ago, so perhaps I could start there, but that compiler was so limited and simple that it’s probably useless. Given that, it seems a reasonable place to start would be deeper investigation into what’s required for extending gcc to support a new and novel type of CPU. Whee!Read 7 comments and join the conversation
An official laser-cut case for Floppy Emu has finally arrived! It took a lot of prototyping and fiddling with tiny parts, but I hope you’ll agree the result was worth it. The case is only 6mm larger than the board itself, accommodates boards with the extension floppy connector or the built-in connector, and features light pipes to channel the LED’s to the outside of the case. The whole thing is cut from a single sheet of 3mm acrylic, and assembles like a 3D jigsaw puzzle.
I hope to offer these cases for sale soon, but I need help determining how many to make and in what colors. If you might be interested in a case, drop me an email or leave a comment below, and mention your color preference. Cases will probably be $19, and the color will be either clear or black.
I was surprised how challenging it was to make a “simple box” case. My first plan was to design a 3D printed case, but I quickly abandoned that idea once I realized how expensive it would be. 3D printing is an impressive technology, but home 3D printers don’t really have the necessary reliability or speed for consistent manufacturing, and the material cost is significant. Online 3D printing services like Shapeways are another option, but they’re even more expensive. I also doubted I had the necessary 3D modeling skills to design a workable 3D case, so the idea never got very far.
The best alternative seemed to be a laser cut case, constructed of multiple flat pieces assembled into a box shape. Adafruit’s laser-cut enclosure design tutorial was a big help, as was the web-based design tool MakerCase. Before I knew it, I’d designed a basic six-sided box of the proper dimensions, with finger joints at the edges to hold it together. But would it work? Designing a case using finger joints this way requires compensating for the kerf – the thickness of the laser cut. Assume a zero sized kerf, and the box won’t hold together. A 5mm wide tab will end up closer to 4.8mm wide after cutting, while a 5mm wide slot will end up closer to 5.2mm, and the tabs will sit loose in the slots. To compensate, the tabs in the design file should be slightly wider than the desired finished size, and the slots slightly narrower, but not too much. Overestimate the kerf, and the finished tabs will end up wider than the slots, preventing the parts from fitting together at all.
Next I added holes for case screws, the SD card slot, and the extension cable. Easy enough. But what about the buttons? Floppy Emu has four pushbuttons that are needed to operate it, so I couldn’t just seal them up inside the case. I could have cut a big finger-sized hole in the case lid above each button, so you could reach in and press it, but that seemed ugly and awkward. I could also have left the area above the buttons entirely uncovered, but that seemed even less appealing. If I were designing a product that was *always* in a case, I could have switched to a different type of push button with a long plunger that extended outside the case. But I’m not, and that would be goofy for everyone using a Floppy Emu without a case.
I finally concluded the only decent solution was to use some kind of stick to poke through a small hole in the top cover, and press the push button inside the case. This proved to be tricky to get right. If the stick were just a straight shaft, it would fall out if the case were turned upside down. And there was no positive force holding the bottom end of the stick onto the push button. It might wobble around or even slide off the button entirely, causing the whole stick to fall down inside the case. My solution was to add a crossbar to the stick to prevent it from falling out, turning the stick into a sword, and hoping that a tight fit between the sword and the hole would prevent it from sliding around. The light tubes used the same sword design, but modified in size to fit on top of an LED instead of a button. Voila! A finished design.
I sent the design file off to Ponoko for manufacturing, and about a week later I received the laser cut parts in the mail. With eager anticipation I separated the parts, fit them together, and bzzzzt! I had overestimated the kerf, and the parts didn’t fit together at all. Total failure. I went back to the design file, reduced the kerf estimate by half and made a few other mods, and sent revision 2 off to Ponoko. Another week passed. Finally I got the new parts, and it worked! Sort of.
The rev 2 case fit together, and the Floppy Emu board fit inside of it, so that much was looking good. But the swords had big-time slippage problems. They were too loose, and were constantly wobbling around or slipping down inside the case. For revision 3, I made the swords a bit thicker relative to the holes, so they’d fit more tightly and have less room to wobble. I also added “feet” to the swords, to help keep them centered on the buttons and LEDs.
Another week went by, and when the rev 3 case parts arrived, everything looked pretty good. The button swords still wobbled a bit, but not far enough to cause problems or fall off the button. The LED swords were more problematic, and sometimes wobbled off the LED’s centers, but generally stayed close enough to continue working as light pipes. Before offering these cases for sale I’ll probably do a rev 4 design to tighten everything up a little more, but rev 3 is definitely useable. Hooray!
Rev 3 also includes two alternate versions of the base and left side pieces: one for boards with a built-in floppy connector, and one for boards using the extension connector. That makes eight total side pieces, of which you’ll use six.
The only aspect of the design I’m not thrilled with is handling of the swords during assembly. How do you get those little buggers in there and aligned correctly, before you put the top on the case? You can’t just balance the swords on the buttons and then lower the top plate onto them – the swords won’t balance by themselves. One option is to assemble everything upside down: put the top plate upside-down on the table, then place the swords into the holes in the top plate, and finally lower the inverted Floppy Emu board onto the whole assembly. That works, but it’s pretty awkward.
The best solution I’ve found is to do assembly right-side up, and use tape to temporarily hold the swords in the top plate. You assemble the bottom and side pieces normally, and place the Floppy Emu board inside. Then you loosely cover all the top plate holes with tape, and push the swords up from underneath until their top surfaces touch the tape. Now you’ll be holding a top plate with all the swords dangling down under it. Finally, you lower this whole package onto the rest of the assembly, add the case screws, and then remove the tape. It’s not the most elegant system, but it works.
I originally planned to design the case in black, to give the final product a sleek iPhone-style appearance. But when I did a prototype in clear acrylic, my wife loved it and predicted it would be much more popular than black. One big advantage of a clear case is that it won’t need light pipes at all, since you can see the LEDs inside. The material is also a bit cheaper. But the etching on a clear case is difficult to see from some angles, and the final result with its exposed internals looks more like a science fair project than a professional product. What do you think? Which would you prefer?
Read 11 comments and join the conversation