o add gnususb as reference bootloader
o refactor boot loader cpde o
This commit is contained in:
200
tools/gnusb/firmware/main.c
Normal file
200
tools/gnusb/firmware/main.c
Normal file
@@ -0,0 +1,200 @@
|
||||
// ==============================================================================
|
||||
// main.c
|
||||
// firmware for a device based on the gnusb - OPEN SOURCE USB SENSOR BOX
|
||||
//
|
||||
// License:
|
||||
// The project is built with AVR USB driver by Objective Development, which is
|
||||
// published under an own licence based on the GNU General Public License (GPL).
|
||||
// gnusb is also distributed under this enhanced licence. See Documentation.
|
||||
//
|
||||
// target-cpu: ATMega16 @ 12MHz
|
||||
// created 2007-01-28 Michael Egger me@anyma.ch
|
||||
//
|
||||
// ==============================================================================
|
||||
|
||||
#include "gnusb.h" // the gnusb library: setup and utility functions
|
||||
|
||||
// ==============================================================================
|
||||
// Constants
|
||||
// ------------------------------------------------------------------------------
|
||||
#define ADC_PAUSE 10 // number of passes before we sample the next AD channel
|
||||
#define LED_KEEP_ALIVE 100 // number of passes before usb status led turns off
|
||||
#define USB_REPLY_PORTB 8 // Values of portb gets stored into 9th byte of usb_reply (counting from 0)
|
||||
#define USB_REPLY_PORTC 9
|
||||
|
||||
|
||||
// ==============================================================================
|
||||
// Globals
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
static u08 ad_mux; // current ad input channel
|
||||
static u16 ad_values[8]; // sampled ad input values
|
||||
static u08 ad_smoothing; // smoothing level of ad samples (0 - 15)
|
||||
static u08 ad_samplepause; // counts up to ADC_PAUSE between samples
|
||||
|
||||
|
||||
static u08 usb_reply[12]; // 8 bytes AD Values (8 most significant bits)
|
||||
// 1 byte PORTB
|
||||
// 1 byte PORTC
|
||||
// 2 bytes least significant bits of AD values
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// - usbFunctionSetup
|
||||
// ------------------------------------------------------------------------------
|
||||
// this function gets called when the usb driver receives a non standard request
|
||||
// that is: our own requests defined in ../common/gnusb_cmds.h
|
||||
// here's where the magic happens...
|
||||
|
||||
uchar usbFunctionSetup(uchar data[8])
|
||||
{
|
||||
|
||||
switch (data[1]) {
|
||||
// ---------------------------- get all values
|
||||
case GNUSB_CMD_POLL:
|
||||
|
||||
usbMsgPtr = usb_reply;
|
||||
return sizeof(usb_reply);
|
||||
break;
|
||||
|
||||
// ---------------------------- set smoothing
|
||||
case GNUSB_CMD_SET_SMOOTHING:
|
||||
|
||||
if (data[2] > 15) ad_smoothing = 15;
|
||||
else ad_smoothing = data[2];
|
||||
break;
|
||||
// ---------------------------- output one byte on PORTB
|
||||
case GNUSB_CMD_SET_PORTB:
|
||||
|
||||
DDRB = 0xff; // set PORTB to output
|
||||
PORTB = data[2]; // output values
|
||||
usb_reply[USB_REPLY_PORTB] = data[2]; // mirror data in next poll
|
||||
break;
|
||||
|
||||
// ---------------------------- output one byte on PORTC
|
||||
case GNUSB_CMD_SET_PORTC:
|
||||
|
||||
DDRC = 0xff; // set PORTC to output
|
||||
PORTC = data[2]; // output values
|
||||
usb_reply[USB_REPLY_PORTC] = data[2]; // mirror data in next poll
|
||||
break;
|
||||
|
||||
// ---------------------------- set PORTB to input
|
||||
case GNUSB_CMD_INPUT_PORTB:
|
||||
|
||||
DDRB = 0x00;
|
||||
break;
|
||||
// ---------------------------- set PORTC to input
|
||||
case GNUSB_CMD_INPUT_PORTC:
|
||||
|
||||
DDRC = 0x00;
|
||||
break;
|
||||
|
||||
|
||||
// ---------------------------- Start Bootloader for reprogramming the gnusb
|
||||
case GNUSB_CMD_START_BOOTLOADER:
|
||||
|
||||
startBootloader();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// - Check ADC and update ad_values
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
void checkAnlogPorts (void) {
|
||||
unsigned int temp,replymask,replyshift,replybyte;
|
||||
|
||||
if (ad_samplepause != 0xff) {
|
||||
if (ad_samplepause < ADC_PAUSE) {
|
||||
ad_samplepause++; // advance pause counter
|
||||
} else {
|
||||
ad_StartConversion(); // start a new conversion
|
||||
ad_samplepause = 0xff; // indicate we're waiting for a result now
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if ( ad_ConversionComplete() ) { // see if AD-Conversion is complete
|
||||
|
||||
temp = ad_Read10bit(); // read ADC (10 bits);
|
||||
|
||||
// basic low pass filter
|
||||
ad_values[ad_mux] = (ad_values[ad_mux] * ad_smoothing + temp) / (ad_smoothing + 1);
|
||||
|
||||
usb_reply[ad_mux] = ad_values[ad_mux] >> 2; // copy 8 most significant bits to usb reply
|
||||
|
||||
// if you don't need 10bit precision you can leave out the following stuff
|
||||
replybyte = 10 + (ad_mux / 4); // are we writing to byte 10 or 11?
|
||||
replyshift = ((ad_mux % 4) * 2); // how much to shift the bits
|
||||
replymask = (3 << replyshift); // create bitmask
|
||||
// write bits to the right place
|
||||
usb_reply[replybyte] =
|
||||
(usb_reply[replybyte] & ~replymask) | (replymask & (ad_values[ad_mux] << replyshift));
|
||||
|
||||
ad_mux = (ad_mux + 1) % 8; // advance multiplexer index
|
||||
ad_SetChannel(ad_mux); // set mutliplexer channel
|
||||
ad_samplepause = 0; // start counting up to ADC_PAUSE in order to let the input settle a bit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// - Check PORT B and PORT C
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
void checkDigitalPorts(void) {
|
||||
// copy state of pins to usb reply, only if the port is configured as an input
|
||||
if (DDRB == 0x00) usb_reply[USB_REPLY_PORTB] = PINB;
|
||||
if (DDRC == 0x00) usb_reply[USB_REPLY_PORTC] = PINC;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ==============================================================================
|
||||
// - main
|
||||
// ------------------------------------------------------------------------------
|
||||
int main(void)
|
||||
{
|
||||
// ------------------------- Initialize Hardware
|
||||
|
||||
// PORTA: AD Converter
|
||||
DDRA = 0x00; // set all pins to input
|
||||
PORTA = 0x00; // make sure pull-up resistors are turned off
|
||||
|
||||
// PORTB: Default Input
|
||||
DDRB = 0x00; // set all pins to input
|
||||
PORTB = 0xff; // make sure pull-up resistors are turned ON
|
||||
|
||||
// PORTC: Default output
|
||||
DDRC = 0xff; // set all pins to output
|
||||
PORTC = 0xff; // turn off all leds
|
||||
|
||||
// PORTD: gnusbCore stuff: USB, status leds, jumper
|
||||
initCoreHardware();
|
||||
ledOn(STATUS_LED_GREEN);
|
||||
|
||||
// ------------------------- Main Loop
|
||||
while(1) {
|
||||
wdt_reset(); // reset Watchdog timer - otherwise Watchdog will reset gnusb
|
||||
sleepIfIdle(); // go to low power mode if host computer is sleeping
|
||||
usbPoll(); // see if there's something going on on the usb bus
|
||||
|
||||
checkAnlogPorts(); // see if we've finished an analog-digital conversion
|
||||
checkDigitalPorts(); // have a look at PORTB and PORTC
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user