mirror of
https://github.com/esp8266/Arduino.git
synced 2025-06-16 11:21:18 +03:00
Removing avrlib (since it's not used), and switching to non-locking versions of RXTX for the Mac (separate PPC and Intel versions). Also, removed the __MACOSX file from tools-intel.zip.
This commit is contained in:
@ -168,7 +168,6 @@
|
|||||||
/* End PBXApplicationTarget section */
|
/* End PBXApplicationTarget section */
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
330B21540968180400345666 /* librxtxSerial.jnilib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 330B21530968180400345666 /* librxtxSerial.jnilib */; };
|
|
||||||
332D4DB609CF147F00BF81F6 /* Sizer.java in Sources */ = {isa = PBXBuildFile; fileRef = 332D4DB509CF147F00BF81F6 /* Sizer.java */; };
|
332D4DB609CF147F00BF81F6 /* Sizer.java in Sources */ = {isa = PBXBuildFile; fileRef = 332D4DB509CF147F00BF81F6 /* Sizer.java */; };
|
||||||
336EA55B09FF87F60052D765 /* examples in CopyFiles */ = {isa = PBXBuildFile; fileRef = 336EA4DB09FF87E30052D765 /* examples */; };
|
336EA55B09FF87F60052D765 /* examples in CopyFiles */ = {isa = PBXBuildFile; fileRef = 336EA4DB09FF87E30052D765 /* examples */; };
|
||||||
338C478A0AA204BE008F2C0D /* FTDIUSBSerialDriver_v2_1_6.dmg in CopyFiles */ = {isa = PBXBuildFile; fileRef = 338C47870AA204B0008F2C0D /* FTDIUSBSerialDriver_v2_1_6.dmg */; };
|
338C478A0AA204BE008F2C0D /* FTDIUSBSerialDriver_v2_1_6.dmg in CopyFiles */ = {isa = PBXBuildFile; fileRef = 338C47870AA204B0008F2C0D /* FTDIUSBSerialDriver_v2_1_6.dmg */; };
|
||||||
@ -411,16 +410,13 @@
|
|||||||
339514FA097AEB8000193C89 /* license.txt in CopyFiles */,
|
339514FA097AEB8000193C89 /* license.txt in CopyFiles */,
|
||||||
339514FB097AEB8000193C89 /* readme.txt in CopyFiles */,
|
339514FB097AEB8000193C89 /* readme.txt in CopyFiles */,
|
||||||
33FF07050965BEE60016AC38 /* macosx_setup.command in CopyFiles */,
|
33FF07050965BEE60016AC38 /* macosx_setup.command in CopyFiles */,
|
||||||
330B21540968180400345666 /* librxtxSerial.jnilib in CopyFiles */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
330B21530968180400345666 /* librxtxSerial.jnilib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.bundle"; path = librxtxSerial.jnilib; sourceTree = "<group>"; };
|
|
||||||
332D4DB509CF147F00BF81F6 /* Sizer.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; path = Sizer.java; sourceTree = "<group>"; };
|
332D4DB509CF147F00BF81F6 /* Sizer.java */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.java; path = Sizer.java; sourceTree = "<group>"; };
|
||||||
333269E1099BB1FC007D3AE2 /* tools.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = tools.zip; sourceTree = "<group>"; };
|
|
||||||
336EA4DB09FF87E30052D765 /* examples */ = {isa = PBXFileReference; lastKnownFileType = folder; path = examples; sourceTree = "<group>"; };
|
336EA4DB09FF87E30052D765 /* examples */ = {isa = PBXFileReference; lastKnownFileType = folder; path = examples; sourceTree = "<group>"; };
|
||||||
337CD3F309EFC183002B890C /* fetch.sh */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.sh; path = fetch.sh; sourceTree = "<group>"; };
|
337CD3F309EFC183002B890C /* fetch.sh */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.sh; path = fetch.sh; sourceTree = "<group>"; };
|
||||||
338C47870AA204B0008F2C0D /* FTDIUSBSerialDriver_v2_1_6.dmg */ = {isa = PBXFileReference; lastKnownFileType = file; path = FTDIUSBSerialDriver_v2_1_6.dmg; sourceTree = "<group>"; };
|
338C47870AA204B0008F2C0D /* FTDIUSBSerialDriver_v2_1_6.dmg */ = {isa = PBXFileReference; lastKnownFileType = file; path = FTDIUSBSerialDriver_v2_1_6.dmg; sourceTree = "<group>"; };
|
||||||
@ -987,8 +983,6 @@
|
|||||||
33FFFEAC0965BD110016AC38 /* dist */ = {
|
33FFFEAC0965BD110016AC38 /* dist */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
333269E1099BB1FC007D3AE2 /* tools.zip */,
|
|
||||||
330B21530968180400345666 /* librxtxSerial.jnilib */,
|
|
||||||
33FFFEAE0965BD110016AC38 /* bootloader */,
|
33FFFEAE0965BD110016AC38 /* bootloader */,
|
||||||
33FFFEB20965BD110016AC38 /* drivers */,
|
33FFFEB20965BD110016AC38 /* drivers */,
|
||||||
33FFFEB50965BD110016AC38 /* DS_Store */,
|
33FFFEB50965BD110016AC38 /* DS_Store */,
|
||||||
@ -1078,7 +1072,7 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "unzip -od $BUILT_PRODUCTS_DIR dist/tools-ppc.zip";
|
shellScript = "unzip -od $BUILT_PRODUCTS_DIR dist/tools-ppc.zip\ncp dist/librxtxSerial-ppc.jnilib $BUILT_PRODUCTS_DIR/librxtxSerial.jnilib";
|
||||||
};
|
};
|
||||||
3318B11A0AD6CE9F00FE1A05 /* ShellScript */ = {
|
3318B11A0AD6CE9F00FE1A05 /* ShellScript */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
@ -1091,7 +1085,7 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "unzip -od $BUILT_PRODUCTS_DIR dist/tools-intel.zip";
|
shellScript = "unzip -od $BUILT_PRODUCTS_DIR dist/tools-intel.zip\ncp dist/librxtxSerial-intel.jnilib $BUILT_PRODUCTS_DIR/librxtxSerial.jnilib";
|
||||||
};
|
};
|
||||||
3318B1520AD6D1EB00FE1A05 /* ShellScript */ = {
|
3318B1520AD6D1EB00FE1A05 /* ShellScript */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
BIN
build/macosx/dist/librxtxSerial-intel.jnilib
vendored
Executable file
BIN
build/macosx/dist/librxtxSerial-intel.jnilib
vendored
Executable file
Binary file not shown.
BIN
build/macosx/dist/librxtxSerial-ppc.jnilib
vendored
Executable file
BIN
build/macosx/dist/librxtxSerial-ppc.jnilib
vendored
Executable file
Binary file not shown.
BIN
build/macosx/dist/librxtxSerial.jnilib
vendored
BIN
build/macosx/dist/librxtxSerial.jnilib
vendored
Binary file not shown.
BIN
build/macosx/dist/tools-intel.zip
vendored
BIN
build/macosx/dist/tools-intel.zip
vendored
Binary file not shown.
@ -1,116 +0,0 @@
|
|||||||
/*! \file a2d.c \brief Analog-to-Digital converter function library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'a2d.c'
|
|
||||||
// Title : Analog-to-digital converter functions
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002
|
|
||||||
// Created : 2002-04-08
|
|
||||||
// Revised : 2002-09-30
|
|
||||||
// Version : 1.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/signal.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include "a2d.h"
|
|
||||||
|
|
||||||
// global variables
|
|
||||||
|
|
||||||
//! software flag used to indicate when
|
|
||||||
//! the a2d conversion is complete
|
|
||||||
volatile unsigned char a2dCompleteFlag;
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
//! initialize a2d converter
|
|
||||||
void a2dInit(void)
|
|
||||||
{
|
|
||||||
sbi(ADCSR, ADEN); // enable ADC (turn on ADC power)
|
|
||||||
cbi(ADCSR, ADFR); // default to single sample convert mode
|
|
||||||
a2dSetPrescaler(ADC_PRESCALE); // set default prescaler
|
|
||||||
a2dSetReference(ADC_REFERENCE); // set default reference
|
|
||||||
cbi(ADMUX, ADLAR); // set to right-adjusted result
|
|
||||||
|
|
||||||
sbi(ADCSR, ADIE); // enable ADC interrupts
|
|
||||||
|
|
||||||
a2dCompleteFlag = FALSE; // clear conversion complete flag
|
|
||||||
sei(); // turn on interrupts (if not already on)
|
|
||||||
}
|
|
||||||
|
|
||||||
//! turn off a2d converter
|
|
||||||
void a2dOff(void)
|
|
||||||
{
|
|
||||||
cbi(ADCSR, ADIE); // disable ADC interrupts
|
|
||||||
cbi(ADCSR, ADEN); // disable ADC (turn off ADC power)
|
|
||||||
}
|
|
||||||
|
|
||||||
//! configure A2D converter clock division (prescaling)
|
|
||||||
void a2dSetPrescaler(unsigned char prescale)
|
|
||||||
{
|
|
||||||
outb(ADCSR, ((inb(ADCSR) & ~ADC_PRESCALE_MASK) | prescale));
|
|
||||||
}
|
|
||||||
|
|
||||||
//! configure A2D converter voltage reference
|
|
||||||
void a2dSetReference(unsigned char ref)
|
|
||||||
{
|
|
||||||
outb(ADMUX, ((inb(ADMUX) & ~ADC_REFERENCE_MASK) | (ref<<6)));
|
|
||||||
}
|
|
||||||
|
|
||||||
//! sets the a2d input channel
|
|
||||||
void a2dSetChannel(unsigned char ch)
|
|
||||||
{
|
|
||||||
outb(ADMUX, (inb(ADMUX) & ~ADC_MUX_MASK) | (ch & ADC_MUX_MASK)); // set channel
|
|
||||||
}
|
|
||||||
|
|
||||||
//! start a conversion on the current a2d input channel
|
|
||||||
void a2dStartConvert(void)
|
|
||||||
{
|
|
||||||
sbi(ADCSR, ADIF); // clear hardware "conversion complete" flag
|
|
||||||
sbi(ADCSR, ADSC); // start conversion
|
|
||||||
}
|
|
||||||
|
|
||||||
//! return TRUE if conversion is complete
|
|
||||||
u08 a2dIsComplete(void)
|
|
||||||
{
|
|
||||||
return bit_is_set(ADCSR, ADSC);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Perform a 10-bit conversion
|
|
||||||
// starts conversion, waits until conversion is done, and returns result
|
|
||||||
unsigned short a2dConvert10bit(unsigned char ch)
|
|
||||||
{
|
|
||||||
a2dCompleteFlag = FALSE; // clear conversion complete flag
|
|
||||||
outb(ADMUX, (inb(ADMUX) & ~ADC_MUX_MASK) | (ch & ADC_MUX_MASK)); // set channel
|
|
||||||
sbi(ADCSR, ADIF); // clear hardware "conversion complete" flag
|
|
||||||
sbi(ADCSR, ADSC); // start conversion
|
|
||||||
//while(!a2dCompleteFlag); // wait until conversion complete
|
|
||||||
//while( bit_is_clear(ADCSR, ADIF) ); // wait until conversion complete
|
|
||||||
while( bit_is_set(ADCSR, ADSC) ); // wait until conversion complete
|
|
||||||
|
|
||||||
// CAUTION: MUST READ ADCL BEFORE ADCH!!!
|
|
||||||
return (inb(ADCL) | (inb(ADCH)<<8)); // read ADC (full 10 bits);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Perform a 8-bit conversion.
|
|
||||||
// starts conversion, waits until conversion is done, and returns result
|
|
||||||
unsigned char a2dConvert8bit(unsigned char ch)
|
|
||||||
{
|
|
||||||
// do 10-bit conversion and return highest 8 bits
|
|
||||||
return a2dConvert10bit(ch)>>2; // return ADC MSB byte
|
|
||||||
}
|
|
||||||
|
|
||||||
//! interrupt handler for ADC complete interrupt
|
|
||||||
SIGNAL(SIG_ADC)
|
|
||||||
{
|
|
||||||
// set the a2d conversion flag to indicate "complete"
|
|
||||||
a2dCompleteFlag = TRUE;
|
|
||||||
}
|
|
||||||
|
|
@ -1,141 +0,0 @@
|
|||||||
/*! \file a2d.h \brief Analog-to-Digital converter function library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'a2d.h'
|
|
||||||
// Title : Analog-to-digital converter functions
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002
|
|
||||||
// Created : 4/08/2002
|
|
||||||
// Revised : 4/30/2002
|
|
||||||
// Version : 1.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef A2D_H
|
|
||||||
#define A2D_H
|
|
||||||
|
|
||||||
// defines
|
|
||||||
|
|
||||||
// A2D clock prescaler select
|
|
||||||
// *selects how much the CPU clock frequency is divided
|
|
||||||
// to create the A2D clock frequency
|
|
||||||
// *lower division ratios make conversion go faster
|
|
||||||
// *higher division ratios make conversions more accurate
|
|
||||||
#define ADC_PRESCALE_DIV2 0x00 ///< 0x01,0x00 -> CPU clk/2
|
|
||||||
#define ADC_PRESCALE_DIV4 0x02 ///< 0x02 -> CPU clk/4
|
|
||||||
#define ADC_PRESCALE_DIV8 0x03 ///< 0x03 -> CPU clk/8
|
|
||||||
#define ADC_PRESCALE_DIV16 0x04 ///< 0x04 -> CPU clk/16
|
|
||||||
#define ADC_PRESCALE_DIV32 0x05 ///< 0x05 -> CPU clk/32
|
|
||||||
#define ADC_PRESCALE_DIV64 0x06 ///< 0x06 -> CPU clk/64
|
|
||||||
#define ADC_PRESCALE_DIV128 0x07 ///< 0x07 -> CPU clk/128
|
|
||||||
// default value
|
|
||||||
#define ADC_PRESCALE ADC_PRESCALE_DIV64
|
|
||||||
// do not change the mask value
|
|
||||||
#define ADC_PRESCALE_MASK 0x07
|
|
||||||
|
|
||||||
// A2D voltage reference select
|
|
||||||
// *this determines what is used as the
|
|
||||||
// full-scale voltage point for A2D conversions
|
|
||||||
#define ADC_REFERENCE_AREF 0x00 ///< 0x00 -> AREF pin, internal VREF turned off
|
|
||||||
#define ADC_REFERENCE_AVCC 0x01 ///< 0x01 -> AVCC pin, internal VREF turned off
|
|
||||||
#define ADC_REFERENCE_RSVD 0x02 ///< 0x02 -> Reserved
|
|
||||||
#define ADC_REFERENCE_256V 0x03 ///< 0x03 -> Internal 2.56V VREF
|
|
||||||
// default value
|
|
||||||
#define ADC_REFERENCE ADC_REFERENCE_AVCC
|
|
||||||
// do not change the mask value
|
|
||||||
#define ADC_REFERENCE_MASK 0xC0
|
|
||||||
|
|
||||||
// bit mask for A2D channel multiplexer
|
|
||||||
#define ADC_MUX_MASK 0x1F
|
|
||||||
|
|
||||||
// channel defines (for reference and use in code)
|
|
||||||
// these channels supported by all AVRs with A2D
|
|
||||||
#define ADC_CH_ADC0 0x00
|
|
||||||
#define ADC_CH_ADC1 0x01
|
|
||||||
#define ADC_CH_ADC2 0x02
|
|
||||||
#define ADC_CH_ADC3 0x03
|
|
||||||
#define ADC_CH_ADC4 0x04
|
|
||||||
#define ADC_CH_ADC5 0x05
|
|
||||||
#define ADC_CH_ADC6 0x06
|
|
||||||
#define ADC_CH_ADC7 0x07
|
|
||||||
#define ADC_CH_122V 0x1E ///< 1.22V voltage reference
|
|
||||||
#define ADC_CH_AGND 0x1F ///< AGND
|
|
||||||
// these channels supported only in ATmega128
|
|
||||||
// differential with gain
|
|
||||||
#define ADC_CH_0_0_DIFF10X 0x08
|
|
||||||
#define ADC_CH_1_0_DIFF10X 0x09
|
|
||||||
#define ADC_CH_0_0_DIFF200X 0x0A
|
|
||||||
#define ADC_CH_1_0_DIFF200X 0x0B
|
|
||||||
#define ADC_CH_2_2_DIFF10X 0x0C
|
|
||||||
#define ADC_CH_3_2_DIFF10X 0x0D
|
|
||||||
#define ADC_CH_2_2_DIFF200X 0x0E
|
|
||||||
#define ADC_CH_3_2_DIFF200X 0x0F
|
|
||||||
// differential
|
|
||||||
#define ADC_CH_0_1_DIFF1X 0x10
|
|
||||||
#define ADC_CH_1_1_DIFF1X 0x11
|
|
||||||
#define ADC_CH_2_1_DIFF1X 0x12
|
|
||||||
#define ADC_CH_3_1_DIFF1X 0x13
|
|
||||||
#define ADC_CH_4_1_DIFF1X 0x14
|
|
||||||
#define ADC_CH_5_1_DIFF1X 0x15
|
|
||||||
#define ADC_CH_6_1_DIFF1X 0x16
|
|
||||||
#define ADC_CH_7_1_DIFF1X 0x17
|
|
||||||
|
|
||||||
#define ADC_CH_0_2_DIFF1X 0x18
|
|
||||||
#define ADC_CH_1_2_DIFF1X 0x19
|
|
||||||
#define ADC_CH_2_2_DIFF1X 0x1A
|
|
||||||
#define ADC_CH_3_2_DIFF1X 0x1B
|
|
||||||
#define ADC_CH_4_2_DIFF1X 0x1C
|
|
||||||
#define ADC_CH_5_2_DIFF1X 0x1D
|
|
||||||
|
|
||||||
// compatibility for new Mega processors
|
|
||||||
// ADCSR hack apparently no longer necessary in new AVR-GCC
|
|
||||||
#ifdef ADCSRA
|
|
||||||
#ifndef ADCSR
|
|
||||||
#define ADCSR ADCSRA
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#ifdef ADATE
|
|
||||||
#define ADFR ADATE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// function prototypes
|
|
||||||
|
|
||||||
//! Initializes the A/D converter
|
|
||||||
// (turns ADC on and prepares it for use)
|
|
||||||
void a2dInit(void);
|
|
||||||
|
|
||||||
//! Turn off A/D converter
|
|
||||||
void a2dOff(void);
|
|
||||||
|
|
||||||
//! sets the division ratio of the A/D converter clock
|
|
||||||
// this function is automatically called from a2dInit()
|
|
||||||
// with a default value
|
|
||||||
void a2dSetPrescaler(unsigned char prescale);
|
|
||||||
|
|
||||||
//! configures which voltage reference the A/D converter uses
|
|
||||||
// this function is automatically called from a2dInit()
|
|
||||||
// with a default value
|
|
||||||
void a2dSetReference(unsigned char ref);
|
|
||||||
|
|
||||||
//! sets the a2d input channel
|
|
||||||
void a2dSetChannel(unsigned char ch);
|
|
||||||
|
|
||||||
//! start a conversion on the current a2d input channel
|
|
||||||
void a2dStartConvert(void);
|
|
||||||
|
|
||||||
//! return TRUE if conversion is complete
|
|
||||||
u08 a2dIsComplete(void);
|
|
||||||
|
|
||||||
//! starts a conversion on A/D channel# ch,
|
|
||||||
// returns the 10-bit value of the conversion when it is finished
|
|
||||||
unsigned short a2dConvert10bit(unsigned char ch);
|
|
||||||
|
|
||||||
//! starts a conversion on A/D channel# ch,
|
|
||||||
// returns the 8-bit value of the conversion when it is finished
|
|
||||||
unsigned char a2dConvert8bit(unsigned char ch);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,93 +0,0 @@
|
|||||||
/*! \file ads7828.c \brief TI ADS7828 12-bit 8ch A/D Converter Driver Library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'ads7828.c'
|
|
||||||
// Title : TI ADS7828 12-bit 8ch A/D Converter Driver Library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2004
|
|
||||||
// Created : 2004.02.10
|
|
||||||
// Revised : 2004.02.19
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/signal.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include "i2c.h"
|
|
||||||
#include "ads7828.h"
|
|
||||||
|
|
||||||
// global variables
|
|
||||||
u08 Ads7282RefMode;
|
|
||||||
|
|
||||||
// Functions
|
|
||||||
u08 ads7828Init(u08 i2cAddr)
|
|
||||||
{
|
|
||||||
u08 channel = 0x80;
|
|
||||||
|
|
||||||
// setup default A/D voltage reference
|
|
||||||
ads7828SetReference(0);
|
|
||||||
|
|
||||||
// issue a convserion to test chip presence
|
|
||||||
// return TRUE if chip detected
|
|
||||||
// return FALSE if chip does not respond
|
|
||||||
return (i2cMasterSendNI(i2cAddr, 1, &channel) == I2C_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
u16 ads7828Convert(u08 i2cAddr, u08 channel)
|
|
||||||
{
|
|
||||||
// re-order channel bits for
|
|
||||||
// logical single-ended channel selection
|
|
||||||
// channel bit0 -> C2
|
|
||||||
// channel bit1 -> C0
|
|
||||||
// channel bit2 -> C1
|
|
||||||
channel = (((channel>>1) | (channel&0x01)<<2)<<4) | ADS7828_CMD_SD;
|
|
||||||
// do conversion
|
|
||||||
return ads7828ConvertRaw(i2cAddr, channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
u16 ads7828ConvertDiff(u08 i2cAddr, u08 channel)
|
|
||||||
{
|
|
||||||
// clear single-ended channel bit
|
|
||||||
channel = (channel&0x07)<<4;
|
|
||||||
// do conversion
|
|
||||||
return ads7828ConvertRaw(i2cAddr, channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
u16 ads7828ConvertRaw(u08 i2cAddr, u08 channel)
|
|
||||||
{
|
|
||||||
u08 buffer[2];
|
|
||||||
// combine raw channel and reference bits
|
|
||||||
channel &= 0xF0;
|
|
||||||
channel |= Ads7282RefMode;
|
|
||||||
// start conversion on requested channel
|
|
||||||
i2cMasterSendNI(i2cAddr, 1, &channel);
|
|
||||||
// retrieve conversion result
|
|
||||||
i2cMasterReceiveNI(i2cAddr, 2, buffer);
|
|
||||||
// pack bytes and return result
|
|
||||||
return ((buffer[0]<<8) | buffer[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ads7828SetReference(u08 ref)
|
|
||||||
{
|
|
||||||
if(ref)
|
|
||||||
{
|
|
||||||
// use internal reference
|
|
||||||
Ads7282RefMode = ADS7828_CMD_PDMODE2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// use external reference
|
|
||||||
Ads7282RefMode = ADS7828_CMD_PDMODE0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
/*! \file ads7828.h \brief TI ADS7828 12-bit 8ch A/D Converter Driver Library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'ads7828.h'
|
|
||||||
// Title : TI ADS7828 12-bit 8ch A/D Converter Driver Library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2004
|
|
||||||
// Created : 2004.02.10
|
|
||||||
// Revised : 2004.02.19
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef ADS7828_H
|
|
||||||
#define ADS7828_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
// constants/macros/typdefs
|
|
||||||
#define ADS7828_I2C_ADDR 0x90 //< Base I2C address of ADS7828 devices
|
|
||||||
|
|
||||||
// command register bit defines
|
|
||||||
#define ADS7828_CMD_PD0 0x04 //< ADS7828 Power-down bit 0
|
|
||||||
#define ADS7828_CMD_PD1 0x08 //< ADS7828 Power-down bit 1
|
|
||||||
#define ADS7828_CMD_C0 0x10 //< ADS7828 Channel Select bit 0
|
|
||||||
#define ADS7828_CMD_C1 0x20 //< ADS7828 Channel Select bit 1
|
|
||||||
#define ADS7828_CMD_C2 0x40 //< ADS7828 Channel Select bit 2
|
|
||||||
#define ADS7828_CMD_SD 0x80 //< ADS7828 Single-ended/Differential Select bit
|
|
||||||
|
|
||||||
// single-ended channel order defines
|
|
||||||
#define ADS7828_CMD_CH0 0x00 //< ADS7828 Convert Channel 0
|
|
||||||
#define ADS7828_CMD_CH1 0x04 //< ADS7828 Convert Channel 1
|
|
||||||
#define ADS7828_CMD_CH2 0x01 //< ADS7828 Convert Channel 2
|
|
||||||
#define ADS7828_CMD_CH3 0x05 //< ADS7828 Convert Channel 3
|
|
||||||
#define ADS7828_CMD_CH4 0x02 //< ADS7828 Convert Channel 4
|
|
||||||
#define ADS7828_CMD_CH5 0x06 //< ADS7828 Convert Channel 5
|
|
||||||
#define ADS7828_CMD_CH6 0x03 //< ADS7828 Convert Channel 6
|
|
||||||
#define ADS7828_CMD_CH7 0x07 //< ADS7828 Convert Channel 7
|
|
||||||
|
|
||||||
// power-down mode defines
|
|
||||||
#define ADS7828_CMD_PDMODE0 0x00 //< ADS7828 Power-down Mode 0
|
|
||||||
#define ADS7828_CMD_PDMODE1 0x04 //< ADS7828 Power-down Mode 1
|
|
||||||
#define ADS7828_CMD_PDMODE2 0x08 //< ADS7828 Power-down Mode 2
|
|
||||||
#define ADS7828_CMD_PDMODE3 0x0C //< ADS7828 Power-down Mode 3
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
//! Initialize the ADS7828 chip
|
|
||||||
// returns:
|
|
||||||
// TRUE if successful
|
|
||||||
// FALSE if unsuccessful (chip not present)
|
|
||||||
u08 ads7828Init(u08 i2cAddr);
|
|
||||||
|
|
||||||
//! Set the voltage reference to use for A/D conversion
|
|
||||||
// ref = 0 => External reference voltage on Ref pin
|
|
||||||
// ref = 1 => Internal 2.5V reference voltage (Ref pin left open)
|
|
||||||
void ads7828SetReference(u08 ref);
|
|
||||||
|
|
||||||
//! Begin single-ended conversion on given logical channel#, and return result
|
|
||||||
u16 ads7828Convert(u08 i2cAddr, u08 channel);
|
|
||||||
|
|
||||||
//! Begin differential conversion on given channel pair, and return result
|
|
||||||
u16 ads7828ConvertDiff(u08 i2cAddr, u08 channel);
|
|
||||||
|
|
||||||
//! Begin conversion on given raw channel#, and return result
|
|
||||||
u16 ads7828ConvertRaw(u08 i2cAddr, u08 channel);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,606 +0,0 @@
|
|||||||
/*! \file ata.c \brief IDE-ATA hard disk interface driver. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'ata.c'
|
|
||||||
// Title : IDE-ATA interface driver for hard disks
|
|
||||||
// Author : Pascal Stang
|
|
||||||
// Date : 11/22/2000
|
|
||||||
// Revised : 4/19/2003
|
|
||||||
// Version : 0.3
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
#include <avr/signal.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
// #include <stdio.h>
|
|
||||||
#endif
|
|
||||||
#include "global.h"
|
|
||||||
#include "timer.h"
|
|
||||||
#include "rprintf.h"
|
|
||||||
|
|
||||||
#include "ata.h"
|
|
||||||
|
|
||||||
//#define DEBUG_ATA 1
|
|
||||||
|
|
||||||
// global variables
|
|
||||||
|
|
||||||
// drive information
|
|
||||||
typeDriveInfo ataDriveInfo;
|
|
||||||
|
|
||||||
|
|
||||||
void ataInit(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ataDriveInit(void)
|
|
||||||
{
|
|
||||||
u08 i;
|
|
||||||
unsigned char* buffer = (unsigned char*) SECTOR_BUFFER_ADDR;
|
|
||||||
|
|
||||||
// read drive identity
|
|
||||||
rprintfProgStrM("\r\nScanning IDE interface...\r\n");
|
|
||||||
// Wait for drive to be ready
|
|
||||||
ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
|
|
||||||
// issue identify command
|
|
||||||
ataWriteByte(ATA_REG_CMDSTATUS1, 0xEC);
|
|
||||||
// wait for drive to request data transfer
|
|
||||||
ataStatusWait(ATA_SR_DRQ, ATA_SR_DRQ);
|
|
||||||
timerPause(200);
|
|
||||||
// read in the data
|
|
||||||
ataReadDataBuffer(buffer, 512);
|
|
||||||
|
|
||||||
// set local drive info parameters
|
|
||||||
ataDriveInfo.cylinders = *( ((unsigned int*) buffer) + ATA_IDENT_CYLINDERS );
|
|
||||||
ataDriveInfo.heads = *( ((unsigned int*) buffer) + ATA_IDENT_HEADS );
|
|
||||||
ataDriveInfo.sectors = *( ((unsigned int*) buffer) + ATA_IDENT_SECTORS );
|
|
||||||
ataDriveInfo.LBAsupport = *( ((unsigned int*) buffer) + ATA_IDENT_FIELDVALID );
|
|
||||||
ataDriveInfo.sizeinsectors = *( (unsigned long*) (buffer + ATA_IDENT_LBASECTORS*2) );
|
|
||||||
// copy model string
|
|
||||||
for(i=0; i<40; i+=2)
|
|
||||||
{
|
|
||||||
// correct for byte order
|
|
||||||
ataDriveInfo.model[i ] = buffer[(ATA_IDENT_MODEL*2) + i + 1];
|
|
||||||
ataDriveInfo.model[i+1] = buffer[(ATA_IDENT_MODEL*2) + i ];
|
|
||||||
}
|
|
||||||
// terminate string
|
|
||||||
ataDriveInfo.model[40] = 0;
|
|
||||||
|
|
||||||
// process and print info
|
|
||||||
if(ataDriveInfo.LBAsupport)
|
|
||||||
{
|
|
||||||
// LBA support
|
|
||||||
rprintf("Drive 0: %dMB ", ataDriveInfo.sizeinsectors/(1000000/512) );
|
|
||||||
rprintf("LBA mode -- MODEL: ");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// CHS, no LBA support
|
|
||||||
// calculate drive size
|
|
||||||
ataDriveInfo.sizeinsectors = (unsigned long) ataDriveInfo.cylinders*
|
|
||||||
ataDriveInfo.heads*ataDriveInfo.sectors;
|
|
||||||
rprintf("Drive 0: %dMB ", ataDriveInfo.sizeinsectors/(1000000/512) );
|
|
||||||
rprintf("CHS mode C=%d H=%d S=%d -- MODEL: ", ataDriveInfo.cylinders, ataDriveInfo.heads, ataDriveInfo.sectors );
|
|
||||||
}
|
|
||||||
// print model information
|
|
||||||
rprintfStr(ataDriveInfo.model); rprintfCRLF();
|
|
||||||
|
|
||||||
// initialize local disk parameters
|
|
||||||
//ataDriveInfo.cylinders = ATA_DISKPARM_CLYS;
|
|
||||||
//ataDriveInfo.heads = ATA_DISKPARM_HEADS;
|
|
||||||
//ataDriveInfo.sectors = ATA_DISKPARM_SECTORS;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ataDiskErr(void)
|
|
||||||
{
|
|
||||||
unsigned char b;
|
|
||||||
|
|
||||||
b = ataReadByte(ATA_REG_ERROR);
|
|
||||||
rprintfProgStrM("ATA Error: ");
|
|
||||||
rprintfu08(b);
|
|
||||||
rprintfCRLF();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ataSetDrivePowerMode(u08 DriveNo, u08 mode, u08 timeout)
|
|
||||||
{
|
|
||||||
// select drive
|
|
||||||
ataDriveSelect(DriveNo);
|
|
||||||
// Wait for drive to be ready
|
|
||||||
ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
|
|
||||||
|
|
||||||
// set mode
|
|
||||||
switch(mode)
|
|
||||||
{
|
|
||||||
case ATA_DISKMODE_SPINDOWN: ataWriteByte(ATA_REG_CMDSTATUS1, ATA_CMD_SPINDOWN); break;
|
|
||||||
case ATA_DISKMODE_SPINUP: ataWriteByte(ATA_REG_CMDSTATUS1, ATA_CMD_SPINUP); break;
|
|
||||||
case ATA_DISKMODE_SETTIMEOUT:
|
|
||||||
ataWriteByte(ATA_REG_SECCOUNT, timeout);
|
|
||||||
ataWriteByte(ATA_REG_CMDSTATUS1, ATA_CMD_IDLE_5SU);
|
|
||||||
break;
|
|
||||||
case ATA_DISKMODE_SLEEP: ataWriteByte(ATA_REG_CMDSTATUS1, ATA_CMD_SLEEP); break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ataPrintSector( u08 *Buffer)
|
|
||||||
{
|
|
||||||
u08 i;
|
|
||||||
u16 j;
|
|
||||||
u08 *buf;
|
|
||||||
u08 s;
|
|
||||||
|
|
||||||
buf = Buffer;
|
|
||||||
|
|
||||||
// print the low order address indicies
|
|
||||||
rprintfProgStrM(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF\r\n");
|
|
||||||
rprintfProgStrM(" ----------------------------------------------- ---- ASCII -----\r\n");
|
|
||||||
|
|
||||||
// print the data
|
|
||||||
for(j=0; j<0x20; j++)
|
|
||||||
{
|
|
||||||
// print the high order address index for this line
|
|
||||||
rprintfu16(j<<4);
|
|
||||||
rprintfProgStrM(" ");
|
|
||||||
|
|
||||||
// print the hex data
|
|
||||||
for(i=0; i<0x10; i++)
|
|
||||||
{
|
|
||||||
rprintfu08(buf[(j<<4)+i]);
|
|
||||||
rprintfProgStrM(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
// leave some space
|
|
||||||
rprintfProgStrM(" ");
|
|
||||||
|
|
||||||
// print the ascii data
|
|
||||||
for(i=0; i<0x10; i++)
|
|
||||||
{
|
|
||||||
s = buf[(j<<4)+i];
|
|
||||||
// make sure character is printable
|
|
||||||
if(s >= 0x20)
|
|
||||||
{
|
|
||||||
rprintfChar(s);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rprintfChar(0x20);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
rprintfCRLF();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ataReadDataBuffer(u08 *Buffer, u16 numBytes)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
//sbi(MCUCR, SRW); // enable RAM waitstate
|
|
||||||
|
|
||||||
// read data from drive
|
|
||||||
for (i=0; i<(numBytes/16); i++)
|
|
||||||
{
|
|
||||||
// optimize by reading 16 bytes in-line before looping
|
|
||||||
*Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
|
|
||||||
*Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
|
|
||||||
*Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
|
|
||||||
*Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
|
|
||||||
*Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
|
|
||||||
*Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
|
|
||||||
*Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
|
|
||||||
*Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
|
|
||||||
*Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
|
|
||||||
*Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
|
|
||||||
*Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
|
|
||||||
*Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
|
|
||||||
*Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
|
|
||||||
*Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
|
|
||||||
*Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL);
|
|
||||||
*Buffer++ = *((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH);
|
|
||||||
}
|
|
||||||
//cbi(MCUCR, SRW); // disable RAM waitstate
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ataWriteDataBuffer(u08 *Buffer, u16 numBytes)
|
|
||||||
{
|
|
||||||
register unsigned char temp;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
//sbi(MCUCR, SRW); // enable RAM waitstate
|
|
||||||
|
|
||||||
// write data to drive
|
|
||||||
for (i=0; i<(numBytes/16); i++)
|
|
||||||
{
|
|
||||||
// optimize by writing 16 bytes in-line before looping
|
|
||||||
// keep byte order correct by using temp register
|
|
||||||
temp = *Buffer++;
|
|
||||||
*((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
|
|
||||||
*((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
|
|
||||||
temp = *Buffer++;
|
|
||||||
*((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
|
|
||||||
*((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
|
|
||||||
temp = *Buffer++;
|
|
||||||
*((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
|
|
||||||
*((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
|
|
||||||
temp = *Buffer++;
|
|
||||||
*((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
|
|
||||||
*((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
|
|
||||||
temp = *Buffer++;
|
|
||||||
*((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
|
|
||||||
*((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
|
|
||||||
temp = *Buffer++;
|
|
||||||
*((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
|
|
||||||
*((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
|
|
||||||
temp = *Buffer++;
|
|
||||||
*((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
|
|
||||||
*((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
|
|
||||||
temp = *Buffer++;
|
|
||||||
*((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAH) = *Buffer++;
|
|
||||||
*((volatile unsigned char*) ATA_REG_BASE + ATA_REG_DATAL) = temp;
|
|
||||||
}
|
|
||||||
//cbi(MCUCR, SRW); // disable RAM waitstate
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 ataStatusWait(u08 mask, u08 waitStatus)
|
|
||||||
{
|
|
||||||
register u08 status;
|
|
||||||
|
|
||||||
delay(100);
|
|
||||||
|
|
||||||
// wait for desired status
|
|
||||||
while( ((status = ataReadByte(ATA_REG_CMDSTATUS1)) & mask) == waitStatus );
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unsigned char ataReadSectorsCHS( unsigned char Drive,
|
|
||||||
unsigned char Head,
|
|
||||||
unsigned int Track,
|
|
||||||
unsigned char Sector,
|
|
||||||
unsigned int numsectors,
|
|
||||||
unsigned char *Buffer)
|
|
||||||
{
|
|
||||||
unsigned char temp;
|
|
||||||
|
|
||||||
// Wait for drive to be ready
|
|
||||||
temp = ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
|
|
||||||
|
|
||||||
// Prepare parameters...
|
|
||||||
ataWriteByte(ATA_REG_HDDEVSEL, 0xA0+(Drive ? 0x10:00)+Head); // CHS mode/Drive/Head
|
|
||||||
ataWriteByte(ATA_REG_CYLHI, Track>>8); // MSB of track
|
|
||||||
ataWriteByte(ATA_REG_CYLLO, Track); // LSB of track
|
|
||||||
ataWriteByte(ATA_REG_STARTSEC, Sector); // sector
|
|
||||||
ataWriteByte(ATA_REG_SECCOUNT, numsectors); // # of sectors
|
|
||||||
|
|
||||||
// Issue read sector command...
|
|
||||||
ataWriteByte(ATA_REG_CMDSTATUS1, 0x21);
|
|
||||||
|
|
||||||
// Wait for drive to be ready
|
|
||||||
temp = ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
|
|
||||||
|
|
||||||
if (temp & ATA_SR_ERR)
|
|
||||||
{
|
|
||||||
rprintfProgStrM("RD ERR\r\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for drive to request data transfer
|
|
||||||
ataStatusWait(ATA_SR_DRQ, 0);
|
|
||||||
|
|
||||||
// read data from drive
|
|
||||||
ataReadDataBuffer(Buffer, 512*numsectors);
|
|
||||||
|
|
||||||
// Return the error bit from the status register...
|
|
||||||
temp = ataReadByte(ATA_REG_CMDSTATUS1); // read status register
|
|
||||||
|
|
||||||
return (temp & ATA_SR_ERR) ? 1:0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unsigned char ataWriteSectorsCHS(unsigned char Drive,
|
|
||||||
unsigned char Head,
|
|
||||||
unsigned int Track,
|
|
||||||
unsigned char Sector,
|
|
||||||
unsigned int numsectors,
|
|
||||||
unsigned char *Buffer)
|
|
||||||
{
|
|
||||||
unsigned char temp;
|
|
||||||
|
|
||||||
// Wait for drive to be ready
|
|
||||||
temp = ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
|
|
||||||
|
|
||||||
// Prepare parameters...
|
|
||||||
ataWriteByte(ATA_REG_HDDEVSEL, 0xA0+(Drive ? 0x10:00)+Head); // CHS mode/Drive/Head
|
|
||||||
ataWriteByte(ATA_REG_CYLHI, Track>>8); // MSB of track
|
|
||||||
ataWriteByte(ATA_REG_CYLLO, Track); // LSB of track
|
|
||||||
ataWriteByte(ATA_REG_STARTSEC, Sector); // sector
|
|
||||||
ataWriteByte(ATA_REG_SECCOUNT, numsectors); // # of sectors
|
|
||||||
|
|
||||||
// Issue write sector command
|
|
||||||
ataWriteByte(ATA_REG_CMDSTATUS1, 0x31);
|
|
||||||
|
|
||||||
//delay(100);
|
|
||||||
|
|
||||||
// Wait for drive to request data transfer
|
|
||||||
ataStatusWait(ATA_SR_DRQ, 0);
|
|
||||||
|
|
||||||
// write data to drive
|
|
||||||
ataWriteDataBuffer(Buffer, 512*numsectors);
|
|
||||||
|
|
||||||
// Wait for drive to finish write
|
|
||||||
temp = ataStatusWait(ATA_SR_BSY, ATA_SR_BSY);
|
|
||||||
|
|
||||||
// check for errors
|
|
||||||
if (temp & ATA_SR_ERR)
|
|
||||||
{
|
|
||||||
rprintfProgStrM("WR ERR\r\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the error bit from the status register...
|
|
||||||
return (temp & ATA_SR_ERR) ? 1:0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char ataReadSectorsLBA( unsigned char Drive,
|
|
||||||
unsigned long lba,
|
|
||||||
unsigned int numsectors,
|
|
||||||
unsigned char *Buffer)
|
|
||||||
{
|
|
||||||
unsigned int cyl, head, sect;
|
|
||||||
unsigned char temp;
|
|
||||||
|
|
||||||
#ifdef DEBUG_ATA
|
|
||||||
rprintfProgStrM("ATA LBA read ");
|
|
||||||
rprintfu32(lba); rprintfProgStrM(" ");
|
|
||||||
rprintfu16(numsectors); rprintfProgStrM(" ");
|
|
||||||
rprintfu16((unsigned int)Buffer);
|
|
||||||
rprintfCRLF();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sect = (int) ( lba & 0x000000ffL );
|
|
||||||
lba = lba >> 8;
|
|
||||||
cyl = (int) ( lba & 0x0000ffff );
|
|
||||||
lba = lba >> 16;
|
|
||||||
head = ( (int) ( lba & 0x0fL ) ) | ATA_HEAD_USE_LBA;
|
|
||||||
|
|
||||||
temp = ataReadSectorsCHS( Drive, head, cyl, sect, numsectors, Buffer );
|
|
||||||
|
|
||||||
if(temp)
|
|
||||||
ataDiskErr();
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char ataWriteSectorsLBA( unsigned char Drive,
|
|
||||||
unsigned long lba,
|
|
||||||
unsigned int numsectors,
|
|
||||||
unsigned char *Buffer)
|
|
||||||
{
|
|
||||||
unsigned int cyl, head, sect;
|
|
||||||
unsigned char temp;
|
|
||||||
|
|
||||||
#ifdef DEBUG_ATA
|
|
||||||
rprintfProgStrM("ATA LBA write ");
|
|
||||||
rprintfu32(lba); rprintfProgStrM(" ");
|
|
||||||
rprintfu16(numsectors); rprintfProgStrM(" ");
|
|
||||||
rprintfu16((unsigned int)Buffer);
|
|
||||||
rprintfCRLF();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sect = (int) ( lba & 0x000000ffL );
|
|
||||||
lba = lba >> 8;
|
|
||||||
cyl = (int) ( lba & 0x0000ffff );
|
|
||||||
lba = lba >> 16;
|
|
||||||
head = ( (int) ( lba & 0x0fL ) ) | ATA_HEAD_USE_LBA;
|
|
||||||
|
|
||||||
temp = ataWriteSectorsCHS( Drive, head, cyl, sect, numsectors, Buffer );
|
|
||||||
|
|
||||||
if(temp)
|
|
||||||
ataDiskErr();
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unsigned char ataReadSectors( unsigned char Drive,
|
|
||||||
unsigned long lba,
|
|
||||||
unsigned int numsectors,
|
|
||||||
unsigned char *Buffer)
|
|
||||||
{
|
|
||||||
unsigned int cyl, head, sect;
|
|
||||||
unsigned char temp;
|
|
||||||
|
|
||||||
// check if drive supports native LBA mode
|
|
||||||
if(ataDriveInfo.LBAsupport)
|
|
||||||
{
|
|
||||||
// drive supports using native LBA
|
|
||||||
temp = ataReadSectorsLBA(Drive, lba, numsectors, Buffer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// drive required CHS access
|
|
||||||
#ifdef DEBUG_ATA
|
|
||||||
// do this defore destroying lba
|
|
||||||
rprintfProgStrM("ATA LBA for CHS read: ");
|
|
||||||
rprintfProgStrM("LBA="); rprintfu32(lba); rprintfProgStrM(" ");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// convert LBA to pseudo CHS
|
|
||||||
// remember to offset the sector count by one
|
|
||||||
sect = (u08) (lba % ataDriveInfo.sectors)+1;
|
|
||||||
lba = lba / ataDriveInfo.sectors;
|
|
||||||
head = (u08) (lba % ataDriveInfo.heads);
|
|
||||||
lba = lba / ataDriveInfo.heads;
|
|
||||||
cyl = (u16) lba;
|
|
||||||
|
|
||||||
#ifdef DEBUG_ATA
|
|
||||||
rprintfProgStrM("C:H:S=");
|
|
||||||
rprintfu16(cyl); rprintfProgStrM(":");
|
|
||||||
rprintfu08(head); rprintfProgStrM(":");
|
|
||||||
rprintfu08(sect); rprintfCRLF();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
temp = ataReadSectorsCHS( Drive, head, cyl, sect, numsectors, Buffer );
|
|
||||||
}
|
|
||||||
|
|
||||||
if(temp)
|
|
||||||
ataDiskErr();
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unsigned char ataWriteSectors(unsigned char Drive,
|
|
||||||
unsigned long lba,
|
|
||||||
unsigned int numsectors,
|
|
||||||
unsigned char *Buffer)
|
|
||||||
{
|
|
||||||
unsigned int cyl, head, sect;
|
|
||||||
unsigned char temp;
|
|
||||||
|
|
||||||
// check if drive supports native LBA mode
|
|
||||||
if(ataDriveInfo.LBAsupport)
|
|
||||||
{
|
|
||||||
// drive supports using native LBA
|
|
||||||
temp = ataWriteSectorsLBA(Drive, lba, numsectors, Buffer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// drive required CHS access
|
|
||||||
#ifdef DEBUG_ATA
|
|
||||||
// do this defore destroying lba
|
|
||||||
rprintfProgStrM("ATA LBA for CHS write: ");
|
|
||||||
rprintfProgStrM("LBA="); rprintfu32(lba); rprintfProgStrM(" ");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// convert LBA to pseudo CHS
|
|
||||||
// remember to offset the sector count by one
|
|
||||||
sect = (u08) (lba % ataDriveInfo.sectors)+1;
|
|
||||||
lba = lba / ataDriveInfo.sectors;
|
|
||||||
head = (u08) (lba % ataDriveInfo.heads);
|
|
||||||
lba = lba / ataDriveInfo.heads;
|
|
||||||
cyl = (u16) lba;
|
|
||||||
|
|
||||||
#ifdef DEBUG_ATA
|
|
||||||
rprintfProgStrM("C:H:S=");
|
|
||||||
rprintfu16(cyl); rprintfProgStrM(":");
|
|
||||||
rprintfu08(head); rprintfProgStrM(":");
|
|
||||||
rprintfu08(sect); rprintfCRLF();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
temp = ataWriteSectorsCHS( Drive, head, cyl, sect, numsectors, Buffer );
|
|
||||||
}
|
|
||||||
|
|
||||||
if(temp)
|
|
||||||
ataDiskErr();
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ataDriveSelect(u08 DriveNo)
|
|
||||||
{
|
|
||||||
ataWriteByte(ATA_REG_HDDEVSEL, 0xA0+(DriveNo ? 0x10:00)); // Drive selection
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
// Set drive mode (STANDBY, IDLE)
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
/*#define STANDBY 0
|
|
||||||
#define IDLE 1
|
|
||||||
#define SLEEP 2
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
unsigned char SetMode(unsigned char DriveNo, unsigned char Mode, unsigned char PwrDown)
|
|
||||||
{
|
|
||||||
WriteBYTE(CMD, 6, 0xA0 + (DriveNo ? 0x10:0x00)); // Select drive
|
|
||||||
WriteBYTE(CMD, 2, (PwrDown ? 0x01:0x00)); // Enable automatic power down
|
|
||||||
switch (Mode)
|
|
||||||
{
|
|
||||||
case STANDBY: WriteBYTE(CMD,7, 0xE2); break;
|
|
||||||
case IDLE: WriteBYTE(CMD,7, 0xE3); break;
|
|
||||||
// NOTE: To recover from sleep, either issue a soft or hardware reset !
|
|
||||||
// (But not on all drives, f.ex seagate ST3655A it's not nessecary to reset
|
|
||||||
// but only to go in Idle mode, But on a Conner CFA170A it's nessecary with
|
|
||||||
// a reset)
|
|
||||||
case SLEEP: WriteBYTE(CMD,7, 0xE6); break;
|
|
||||||
}
|
|
||||||
Timer10mSec=10000;
|
|
||||||
while ((ReadBYTE(CMD,7) & 0xC0)!=0x40 && Timer10mSec); // Wait for DRDY & NOT BUSY
|
|
||||||
if (Timer10mSec==0) return 0xFF; // or timeout
|
|
||||||
|
|
||||||
// Return the error register...
|
|
||||||
return ReadBYTE(CMD, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
u08 ataReadByte(u08 reg)
|
|
||||||
{
|
|
||||||
register u08 ret;
|
|
||||||
//sbi(MCUCR, SRW); // enable RAM waitstate
|
|
||||||
ret = *((volatile unsigned char*) ATA_REG_BASE + reg);
|
|
||||||
//cbi(MCUCR, SRW); // disable RAM waitstate
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ataWriteByte(u08 reg, u08 data)
|
|
||||||
{
|
|
||||||
//sbi(MCUCR, SRW); // enable RAM waitstate
|
|
||||||
*((volatile unsigned char*) ATA_REG_BASE + reg) = data;
|
|
||||||
//cbi(MCUCR, SRW); // disable RAM waitstate
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ataShowRegisters(unsigned char DriveNo)
|
|
||||||
{
|
|
||||||
ataWriteByte(ATA_REG_HDDEVSEL, 0xA0 + (DriveNo ? 0x10:0x00)); // Select drive
|
|
||||||
|
|
||||||
rprintfProgStrM("R0: DATALOW = 0x"); rprintfu08(ataReadByte(ATA_REG_DATAL )); rprintfProgStrM(" \r\n");
|
|
||||||
rprintfProgStrM("R1: ERROR = 0x"); rprintfu08(ataReadByte(ATA_REG_ERROR )); rprintfProgStrM(" \r\n");
|
|
||||||
rprintfProgStrM("R2: SECT CNT = 0x"); rprintfu08(ataReadByte(ATA_REG_SECCOUNT)); rprintfProgStrM(" \r\n");
|
|
||||||
rprintfProgStrM("R3: SECT NUM = 0x"); rprintfu08(ataReadByte(ATA_REG_STARTSEC)); rprintfProgStrM(" \r\n");
|
|
||||||
rprintfProgStrM("R4: CYL LOW = 0x"); rprintfu08(ataReadByte(ATA_REG_CYLLO )); rprintfProgStrM(" \r\n");
|
|
||||||
rprintfProgStrM("R5: CYL HIGH = 0x"); rprintfu08(ataReadByte(ATA_REG_CYLHI )); rprintfProgStrM(" \r\n");
|
|
||||||
rprintfProgStrM("R6: HEAD/DEV = 0x"); rprintfu08(ataReadByte(ATA_REG_HDDEVSEL)); rprintfProgStrM(" \r\n");
|
|
||||||
rprintfProgStrM("R7: CMD/STA = 0x"); rprintfu08(ataReadByte(ATA_REG_CMDSTATUS1)); rprintfProgStrM("\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char ataSWReset(void)
|
|
||||||
{
|
|
||||||
ataWriteByte(ATA_REG_HDDEVSEL, 0x06); // SRST and nIEN bits
|
|
||||||
delay(10); // 10uS delay
|
|
||||||
ataWriteByte(ATA_REG_HDDEVSEL, 0x02); // nIEN bits
|
|
||||||
delay(10); // 10 uS delay
|
|
||||||
|
|
||||||
while( (ataReadByte(ATA_REG_CMDSTATUS1) & 0xC0) != 0x40 ); // Wait for DRDY and not BSY
|
|
||||||
|
|
||||||
return ataReadByte(ATA_REG_CMDSTATUS1) + ataReadByte(ATA_REG_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
unsigned char ATA_Idle(unsigned char Drive)
|
|
||||||
{
|
|
||||||
|
|
||||||
WriteBYTE(CMD, 6, 0xA0 + (Drive ? 0x10:0x00)); // Select drive
|
|
||||||
WriteBYTE(CMD,7, 0xE1);
|
|
||||||
|
|
||||||
while ((ReadBYTE(CMD,7) & 0xC0)!=0x40); // Wait for DRDY & NOT BUSY
|
|
||||||
|
|
||||||
// Return the error register...
|
|
||||||
return ReadBYTE(CMD, 1);
|
|
||||||
}
|
|
||||||
*/
|
|
@ -1,182 +0,0 @@
|
|||||||
/*! \file ata.h \brief IDE-ATA hard disk interface driver. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'ata.h'
|
|
||||||
// Title : IDE-ATA interface driver for hard disks
|
|
||||||
// Author : Pascal Stang
|
|
||||||
// Date : 11/22/2000
|
|
||||||
// Revised : 12/29/2000
|
|
||||||
// Version : 0.3
|
|
||||||
// Target MCU : ATmega103 (should work for Atmel AVR Series)
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef ATA_H
|
|
||||||
#define ATA_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include "ataconf.h"
|
|
||||||
|
|
||||||
// constants
|
|
||||||
#define DRIVE0 0
|
|
||||||
|
|
||||||
#define STANDBY 0
|
|
||||||
#define SLEEP 1
|
|
||||||
#define IDLE 2
|
|
||||||
|
|
||||||
// ATA status register bits
|
|
||||||
#define ATA_SR_BSY 0x80
|
|
||||||
#define ATA_SR_DRDY 0x40
|
|
||||||
#define ATA_SR_DF 0x20
|
|
||||||
#define ATA_SR_DSC 0x10
|
|
||||||
#define ATA_SR_DRQ 0x08
|
|
||||||
#define ATA_SR_CORR 0x04
|
|
||||||
#define ATA_SR_IDX 0x02
|
|
||||||
#define ATA_SR_ERR 0x01
|
|
||||||
|
|
||||||
// ATA error register bits
|
|
||||||
#define ATA_ER_UNC 0x40
|
|
||||||
#define ATA_ER_MC 0x20
|
|
||||||
#define ATA_ER_IDNF 0x10
|
|
||||||
#define ATA_ER_MCR 0x08
|
|
||||||
#define ATA_ER_ABRT 0x04
|
|
||||||
#define ATA_ER_TK0NF 0x02
|
|
||||||
#define ATA_ER_AMNF 0x01
|
|
||||||
|
|
||||||
// ATA head register bits
|
|
||||||
#define ATA_HEAD_USE_LBA 0x40
|
|
||||||
/*
|
|
||||||
// ATA registers
|
|
||||||
#define ATA_REG_BASE 0x8000
|
|
||||||
#define ATA_REG_DATAL 0x00
|
|
||||||
#define ATA_REG_ERROR 0x01
|
|
||||||
#define ATA_REG_SECCOUNT 0x02
|
|
||||||
#define ATA_REG_STARTSEC 0x03
|
|
||||||
#define ATA_REG_CYLLO 0x04
|
|
||||||
#define ATA_REG_CYLHI 0x05
|
|
||||||
#define ATA_REG_HDDEVSEL 0x06
|
|
||||||
#define ATA_REG_CMDSTATUS1 0x07
|
|
||||||
#define ATA_REG_CMDSTATUS2 0x08
|
|
||||||
#define ATA_REG_ACTSTATUS 0x09
|
|
||||||
|
|
||||||
#define ATA_REG_DATAH 0x10
|
|
||||||
*/
|
|
||||||
// ATA commands
|
|
||||||
#define ATA_CMD_READ 0x20
|
|
||||||
#define ATA_CMD_READNR 0x21
|
|
||||||
#define ATA_CMD_WRITE 0x30
|
|
||||||
#define ATA_CMD_WRITENR 0x31
|
|
||||||
#define ATA_CMD_IDENTIFY 0xEC
|
|
||||||
#define ATA_CMD_RECALIBRATE 0x10
|
|
||||||
#define ATA_CMD_SPINDOWN 0xE0 // spin down disk immediately
|
|
||||||
#define ATA_CMD_SPINUP 0xE1 // spin up disk immediately
|
|
||||||
#define ATA_CMD_STANDBY_5SU 0xE2 // spin down disk and set auto-power-down timer (sectorcount*5sec)
|
|
||||||
#define ATA_CMD_IDLE_5SU 0xE3 // keep disk spinning and set auto-power-down timer (sectorcount*5sec)
|
|
||||||
#define ATA_CMD_SLEEP 0xE6 // sleep disk (wakeup only on HW or SW reset)
|
|
||||||
#define ATA_CMD_STANDBY_01SU 0xF2 // spin down disk and set auto-power-down timer (sectorcount*0.1sec)
|
|
||||||
#define ATA_CMD_IDLE_01SU 0xF3 // keep disk spinning and set auto-power-down timer (sectorcount*0.1sec)
|
|
||||||
|
|
||||||
|
|
||||||
// ATA CHS disk parameters (examples, now we autodetect)
|
|
||||||
#define ATA_DISKPARM_CLYS 0x03A6 // number of cylinders per platter
|
|
||||||
#define ATA_DISKPARM_HEADS 0x10 // number of heads (usable plater sides)
|
|
||||||
#define ATA_DISKPARM_SECTORS 0x11 // number of sectors per head per cylinder
|
|
||||||
|
|
||||||
// ATA Identity fields
|
|
||||||
// all offsets refer to word offset (2 byte increments)
|
|
||||||
#define ATA_IDENT_DEVICETYPE 0 // specifies ATA/ATAPI, removable/non-removable
|
|
||||||
#define ATA_IDENT_CYLINDERS 1 // number of logical cylinders
|
|
||||||
#define ATA_IDENT_HEADS 3 // number of logical heads
|
|
||||||
#define ATA_IDENT_SECTORS 6 // number of sectors per track
|
|
||||||
#define ATA_IDENT_SERIAL 10 // drive model name (20 characters)
|
|
||||||
#define ATA_IDENT_MODEL 27 // drive model name (40 characters)
|
|
||||||
#define ATA_IDENT_FIELDVALID 53 // indicates field validity of higher words (bit0: words54-58, bit1: words 64-70)
|
|
||||||
#define ATA_IDENT_LBASECTORS 60 // number of sectors in LBA translation mode
|
|
||||||
|
|
||||||
// drive mode defines (for ataSetDrivePowerMode() )
|
|
||||||
#define ATA_DISKMODE_SPINDOWN 0
|
|
||||||
#define ATA_DISKMODE_SPINUP 1
|
|
||||||
#define ATA_DISKMODE_SETTIMEOUT 2
|
|
||||||
#define ATA_DISKMODE_SLEEP 3
|
|
||||||
|
|
||||||
// typedefs
|
|
||||||
// drive info structure
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned int cylinders;
|
|
||||||
unsigned char heads;
|
|
||||||
unsigned char sectors;
|
|
||||||
unsigned long sizeinsectors;
|
|
||||||
unsigned char LBAsupport;
|
|
||||||
char model[41];
|
|
||||||
} typeDriveInfo;
|
|
||||||
|
|
||||||
|
|
||||||
// Prototypes
|
|
||||||
void ataInit(void);
|
|
||||||
void ataDriveInit(void);
|
|
||||||
void ataDriveSelect(u08 DriveNo);
|
|
||||||
void ataSetDrivePowerMode(u08 DriveNo, u08 mode, u08 timeout);
|
|
||||||
u08 ataReadByte(u08 reg);
|
|
||||||
void ataWriteByte(u08 reg, u08 data);
|
|
||||||
void ataShowRegisters(unsigned char DriveNo);
|
|
||||||
u08 ataSWReset(void);
|
|
||||||
void ataDiskErr(void);
|
|
||||||
void ataPrintSector( u08 *Buffer);
|
|
||||||
void ataReadDataBuffer(u08 *Buffer, u16 numBytes);
|
|
||||||
void ataWriteDataBuffer(u08 *Buffer, u16 numBytes);
|
|
||||||
u08 ataStatusWait(u08 mask, u08 waitStatus);
|
|
||||||
|
|
||||||
// read and write routines for CHS based drives
|
|
||||||
unsigned char ataReadSectorsCHS( unsigned char Drive,
|
|
||||||
unsigned char Head,
|
|
||||||
unsigned int Track,
|
|
||||||
unsigned char Sector,
|
|
||||||
unsigned int numsectors,
|
|
||||||
unsigned char *Buffer);
|
|
||||||
|
|
||||||
unsigned char ataWriteSectorsCHS( unsigned char Drive,
|
|
||||||
unsigned char Head,
|
|
||||||
unsigned int Track,
|
|
||||||
unsigned char Sector,
|
|
||||||
unsigned int numsectors,
|
|
||||||
unsigned char *Buffer);
|
|
||||||
|
|
||||||
// read and write routines for LBA based drives
|
|
||||||
unsigned char ataReadSectorsLBA( unsigned char Drive,
|
|
||||||
unsigned long lba,
|
|
||||||
unsigned int numsectors,
|
|
||||||
unsigned char *Buffer);
|
|
||||||
|
|
||||||
unsigned char ataWriteSectorsLBA( unsigned char Drive,
|
|
||||||
unsigned long lba,
|
|
||||||
unsigned int numsectors,
|
|
||||||
unsigned char *Buffer);
|
|
||||||
|
|
||||||
// generic read and write routines using LBA
|
|
||||||
// uses native or translated LBA addressing
|
|
||||||
// given autodetected drive type
|
|
||||||
unsigned char ataReadSectors( unsigned char Drive,
|
|
||||||
unsigned long lba,
|
|
||||||
unsigned int numsectors,
|
|
||||||
unsigned char *Buffer);
|
|
||||||
|
|
||||||
unsigned char ataWriteSectors( unsigned char Drive,
|
|
||||||
unsigned long lba,
|
|
||||||
unsigned int numsectors,
|
|
||||||
unsigned char *Buffer);
|
|
||||||
|
|
||||||
//unsigned char IdentifyDrive(unsigned char DriveNo, unsigned char *Buffer, tdefDriveInfo *DriveInfo);
|
|
||||||
//unsigned char SetMode(unsigned char DriveNo, unsigned char Mode, unsigned char PwrDown);
|
|
||||||
//unsigned char ATA_Idle(unsigned char Drive);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,77 +0,0 @@
|
|||||||
/*! \file avrlibdefs.h \brief AVRlib global defines and macros. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'avrlibdefs.h'
|
|
||||||
// Title : AVRlib global defines and macros include file
|
|
||||||
// Author : Pascal Stang
|
|
||||||
// Created : 7/12/2001
|
|
||||||
// Revised : 9/30/2002
|
|
||||||
// Version : 1.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// Description : This include file is designed to contain items useful to all
|
|
||||||
// code files and projects, regardless of specific implementation.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef AVRLIBDEFS_H
|
|
||||||
#define AVRLIBDEFS_H
|
|
||||||
|
|
||||||
// Code compatibility to new AVR-libc
|
|
||||||
// outb(), inb(), BV(), sbi(), cbi(), sei(), cli()
|
|
||||||
#ifndef outb
|
|
||||||
#define outb(addr, data) addr = (data)
|
|
||||||
#endif
|
|
||||||
#ifndef inb
|
|
||||||
#define inb(addr) (addr)
|
|
||||||
#endif
|
|
||||||
#ifndef BV
|
|
||||||
#define BV(bit) (1<<(bit))
|
|
||||||
#endif
|
|
||||||
#ifndef cbi
|
|
||||||
#define cbi(reg,bit) reg &= ~(BV(bit))
|
|
||||||
#endif
|
|
||||||
#ifndef sbi
|
|
||||||
#define sbi(reg,bit) reg |= (BV(bit))
|
|
||||||
#endif
|
|
||||||
#ifndef cli
|
|
||||||
#define cli() __asm__ __volatile__ ("cli" ::)
|
|
||||||
#endif
|
|
||||||
#ifndef sei
|
|
||||||
#define sei() __asm__ __volatile__ ("sei" ::)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// support for individual port pin naming in the mega128
|
|
||||||
// see port128.h for details
|
|
||||||
#ifdef __AVR_ATmega128__
|
|
||||||
// not currently necessary due to inclusion
|
|
||||||
// of these defines in newest AVR-GCC
|
|
||||||
// do a quick test to see if include is needed
|
|
||||||
#ifndef PD0
|
|
||||||
#include "port128.h"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// use this for packed structures
|
|
||||||
// (this is seldom necessary on an 8-bit architecture like AVR,
|
|
||||||
// but can assist in code portability to AVR)
|
|
||||||
#define GNUC_PACKED __attribute__((packed))
|
|
||||||
|
|
||||||
// port address helpers
|
|
||||||
#define DDR(x) ((x)-1) // address of data direction register of port x
|
|
||||||
#define PIN(x) ((x)-2) // address of input register of port x
|
|
||||||
|
|
||||||
// MIN/MAX/ABS macros
|
|
||||||
#define MIN(a,b) ((a<b)?(a):(b))
|
|
||||||
#define MAX(a,b) ((a>b)?(a):(b))
|
|
||||||
#define ABS(x) ((x>0)?(x):(-x))
|
|
||||||
|
|
||||||
// constants
|
|
||||||
#define PI 3.14159265359
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,84 +0,0 @@
|
|||||||
/*! \file avrlibtypes.h \brief AVRlib global types and typedefines. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'avrlibtypes.h'
|
|
||||||
// Title : AVRlib global types and typedefines include file
|
|
||||||
// Author : Pascal Stang
|
|
||||||
// Created : 7/12/2001
|
|
||||||
// Revised : 9/30/2002
|
|
||||||
// Version : 1.0
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// Description : Type-defines required and used by AVRlib. Most types are also
|
|
||||||
// generally useful.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef AVRLIBTYPES_H
|
|
||||||
#define AVRLIBTYPES_H
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
// true/false defines
|
|
||||||
#define FALSE 0
|
|
||||||
#define TRUE -1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// datatype definitions macros
|
|
||||||
typedef unsigned char u08;
|
|
||||||
typedef signed char s08;
|
|
||||||
typedef unsigned short u16;
|
|
||||||
typedef signed short s16;
|
|
||||||
typedef unsigned long u32;
|
|
||||||
typedef signed long s32;
|
|
||||||
typedef unsigned long long u64;
|
|
||||||
typedef signed long long s64;
|
|
||||||
|
|
||||||
/* use inttypes.h instead
|
|
||||||
// C99 standard integer type definitions
|
|
||||||
typedef unsigned char uint8_t;
|
|
||||||
typedef signed char int8_t;
|
|
||||||
typedef unsigned short uint16_t;
|
|
||||||
typedef signed short int16_t;
|
|
||||||
typedef unsigned long uint32_t;
|
|
||||||
typedef signed long int32_t;
|
|
||||||
typedef unsigned long uint64_t;
|
|
||||||
typedef signed long int64_t;
|
|
||||||
*/
|
|
||||||
// maximum value that can be held
|
|
||||||
// by unsigned data types (8,16,32bits)
|
|
||||||
#define MAX_U08 255
|
|
||||||
#define MAX_U16 65535
|
|
||||||
#define MAX_U32 4294967295
|
|
||||||
|
|
||||||
// maximum values that can be held
|
|
||||||
// by signed data types (8,16,32bits)
|
|
||||||
#define MIN_S08 -128
|
|
||||||
#define MAX_S08 127
|
|
||||||
#define MIN_S16 -32768
|
|
||||||
#define MAX_S16 32767
|
|
||||||
#define MIN_S32 -2147483648
|
|
||||||
#define MAX_S32 2147483647
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
// more type redefinitions
|
|
||||||
typedef unsigned char BOOL;
|
|
||||||
typedef unsigned char BYTE;
|
|
||||||
typedef unsigned int WORD;
|
|
||||||
typedef unsigned long DWORD;
|
|
||||||
|
|
||||||
typedef unsigned char UCHAR;
|
|
||||||
typedef unsigned int UINT;
|
|
||||||
typedef unsigned short USHORT;
|
|
||||||
typedef unsigned long ULONG;
|
|
||||||
|
|
||||||
typedef char CHAR;
|
|
||||||
typedef int INT;
|
|
||||||
typedef long LONG;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,131 +0,0 @@
|
|||||||
/*! \file bitbuf.c \brief Multipurpose bit buffer structure and methods. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'bitbuf.c'
|
|
||||||
// Title : Multipurpose bit buffer structure and methods
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2001-2002
|
|
||||||
// Created : 7/10/2002
|
|
||||||
// Revised : 7/10/2002
|
|
||||||
// Version : 0.5
|
|
||||||
// Target MCU : any
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#include "bitbuf.h"
|
|
||||||
|
|
||||||
// global variables
|
|
||||||
|
|
||||||
//! Initialize the bit buffer
|
|
||||||
// sets the start location and size of the buffer in memory
|
|
||||||
void bitbufInit(BitBuf* bitBuffer, unsigned char *start, unsigned short bytesize)
|
|
||||||
{
|
|
||||||
// set start pointer of the buffer
|
|
||||||
bitBuffer->dataptr = start;
|
|
||||||
bitBuffer->size = bytesize;
|
|
||||||
// initialize indexing and length
|
|
||||||
bitBuffer->dataindex = 0;
|
|
||||||
bitbufFlush(bitBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// access routines
|
|
||||||
|
|
||||||
//! Get a bit from the current position in the buffer
|
|
||||||
// returns the bit at the current position in the buffer
|
|
||||||
// and increments the bit position
|
|
||||||
unsigned char bitbufGet(BitBuf* bitBuffer)
|
|
||||||
{
|
|
||||||
unsigned char byte;
|
|
||||||
unsigned char bit;
|
|
||||||
|
|
||||||
// get current working byte
|
|
||||||
byte = bitBuffer->dataptr[bitBuffer->bytePos];
|
|
||||||
// read data bit
|
|
||||||
bit = (byte & (1<<bitBuffer->bitPos))?(1):(0);
|
|
||||||
|
|
||||||
// increment bit counter
|
|
||||||
if(bitBuffer->bitPos < 7)
|
|
||||||
{
|
|
||||||
bitBuffer->bitPos++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// increment byte counter
|
|
||||||
bitBuffer->bitPos = 0;
|
|
||||||
bitBuffer->bytePos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return bit value
|
|
||||||
return bit;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Get a bit from a given index into the buffer
|
|
||||||
// returns the bit at position [bitIndex] in the buffer
|
|
||||||
unsigned char bitbufGetAtIndex(BitBuf* bitBuffer, unsigned short bitIndex)
|
|
||||||
{
|
|
||||||
// return bit at index in buffer
|
|
||||||
return (bitBuffer->dataptr[bitIndex>>3] & (1<<(bitIndex & 0x07)))?(1):(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Store a bit at the current position in the buffer
|
|
||||||
// stores the bit at the current position in the buffer
|
|
||||||
// and increments the bit position
|
|
||||||
void bitbufStore(BitBuf* bitBuffer, unsigned char bit)
|
|
||||||
{
|
|
||||||
unsigned char byte;
|
|
||||||
// get current working byte
|
|
||||||
byte = bitBuffer->dataptr[bitBuffer->bytePos];
|
|
||||||
// apply data bit
|
|
||||||
if(bit)
|
|
||||||
byte |= (1<<bitBuffer->bitPos);
|
|
||||||
else
|
|
||||||
byte &= ~(1<<bitBuffer->bitPos);
|
|
||||||
// store data
|
|
||||||
bitBuffer->dataptr[bitBuffer->bytePos] = byte;
|
|
||||||
bitBuffer->datalength++;
|
|
||||||
|
|
||||||
// increment bit counter
|
|
||||||
if(bitBuffer->bitPos < 7)
|
|
||||||
{
|
|
||||||
bitBuffer->bitPos++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// increment byte counter
|
|
||||||
bitBuffer->bitPos = 0;
|
|
||||||
bitBuffer->bytePos++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void bitbufReset(BitBuf* bitBuffer)
|
|
||||||
{
|
|
||||||
// reset counters
|
|
||||||
bitBuffer->bytePos = 0;
|
|
||||||
bitBuffer->bitPos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bitbufFlush(BitBuf* bitBuffer)
|
|
||||||
{
|
|
||||||
// flush contents of the buffer
|
|
||||||
bitBuffer->datalength = 0;
|
|
||||||
// reset indexing
|
|
||||||
bitbufReset(bitBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned short bitbufGetDataLength(BitBuf* bitBuffer)
|
|
||||||
{
|
|
||||||
return bitBuffer->datalength;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
unsigned char bitbufIsNotFull(cBuffer* buffer)
|
|
||||||
{
|
|
||||||
// check to see if the buffer has room
|
|
||||||
// return true if there is room
|
|
||||||
return (buffer->datalength < buffer->size);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
|||||||
/*! \file bitbuf.h \brief Multipurpose bit buffer structure and methods. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'bitbuf.c'
|
|
||||||
// Title : Multipurpose bit buffer structure and methods
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2001-2002
|
|
||||||
// Created : 7/10/2002
|
|
||||||
// Revised : 7/10/2002
|
|
||||||
// Version : 0.5
|
|
||||||
// Target MCU : any
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef BITBUF_H
|
|
||||||
#define BITBUF_H
|
|
||||||
|
|
||||||
// structure/typdefs
|
|
||||||
|
|
||||||
// the BitBuffer structure
|
|
||||||
typedef struct struct_BitBuf
|
|
||||||
{
|
|
||||||
unsigned char *dataptr; // the physical memory address where the buffer is stored
|
|
||||||
unsigned short size; // the allocated byte size of the buffer
|
|
||||||
unsigned short bytePos; // current byte position
|
|
||||||
unsigned short bitPos; // current bit position
|
|
||||||
unsigned short datalength; // the length of the data (in bits) currently in the buffer
|
|
||||||
unsigned short dataindex; // the index (in bits) into the buffer where the data starts
|
|
||||||
} BitBuf;
|
|
||||||
|
|
||||||
// function prototypes
|
|
||||||
|
|
||||||
//! initialize a buffer to start at a given address and have given size
|
|
||||||
void bitbufInit(BitBuf* bitBuffer, unsigned char *start, unsigned short bytesize);
|
|
||||||
|
|
||||||
//! get the bit at the current position in the buffer
|
|
||||||
unsigned char bitbufGet(BitBuf* bitBuffer);
|
|
||||||
|
|
||||||
//! get a bit at the specified index in the buffer (kind of like array access)
|
|
||||||
// ** note: this does not remove/delete the bit that was read
|
|
||||||
unsigned char bitbufGetAtIndex(BitBuf* bitBuffer, unsigned short bitIndex);
|
|
||||||
|
|
||||||
//! store a bit at the current position in the buffer
|
|
||||||
void bitbufStore(BitBuf* bitBuffer, unsigned char bit);
|
|
||||||
|
|
||||||
//! return the number of bits in the buffer
|
|
||||||
unsigned short bitbufGetDataLength(BitBuf* bitBuffer);
|
|
||||||
|
|
||||||
// check if the buffer is full/not full (returns non-zero value if not full)
|
|
||||||
//unsigned char bitbufIsNotFull(cBuffer* buffer);
|
|
||||||
|
|
||||||
//! resets the read/write position of the buffer to beginning
|
|
||||||
void bitbufReset(BitBuf* bitBuffer);
|
|
||||||
|
|
||||||
//! flush (clear) the contents of the buffer
|
|
||||||
void bitbufFlush(BitBuf* bitBuffer);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,110 +0,0 @@
|
|||||||
/*! \file buffer.c \brief Multipurpose byte buffer structure and methods. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'buffer.c'
|
|
||||||
// Title : Multipurpose byte buffer structure and methods
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2001-2002
|
|
||||||
// Created : 9/23/2001
|
|
||||||
// Revised : 9/23/2001
|
|
||||||
// Version : 1.0
|
|
||||||
// Target MCU : any
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#include "buffer.h"
|
|
||||||
|
|
||||||
// global variables
|
|
||||||
|
|
||||||
// initialization
|
|
||||||
|
|
||||||
void bufferInit(cBuffer* buffer, unsigned char *start, unsigned short size)
|
|
||||||
{
|
|
||||||
// set start pointer of the buffer
|
|
||||||
buffer->dataptr = start;
|
|
||||||
buffer->size = size;
|
|
||||||
// initialize index and length
|
|
||||||
buffer->dataindex = 0;
|
|
||||||
buffer->datalength = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// access routines
|
|
||||||
unsigned char bufferGetFromFront(cBuffer* buffer)
|
|
||||||
{
|
|
||||||
unsigned char data = 0;
|
|
||||||
|
|
||||||
// check to see if there's data in the buffer
|
|
||||||
if(buffer->datalength)
|
|
||||||
{
|
|
||||||
// get the first character from buffer
|
|
||||||
data = buffer->dataptr[buffer->dataindex];
|
|
||||||
// move index down and decrement length
|
|
||||||
buffer->dataindex++;
|
|
||||||
if(buffer->dataindex >= buffer->size)
|
|
||||||
{
|
|
||||||
buffer->dataindex %= buffer->size;
|
|
||||||
}
|
|
||||||
buffer->datalength--;
|
|
||||||
}
|
|
||||||
// return
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void bufferDumpFromFront(cBuffer* buffer, unsigned short numbytes)
|
|
||||||
{
|
|
||||||
// dump numbytes from the front of the buffer
|
|
||||||
// are we dumping less than the entire buffer?
|
|
||||||
if(numbytes < buffer->datalength)
|
|
||||||
{
|
|
||||||
// move index down by numbytes and decrement length by numbytes
|
|
||||||
buffer->dataindex += numbytes;
|
|
||||||
if(buffer->dataindex >= buffer->size)
|
|
||||||
{
|
|
||||||
buffer->dataindex %= buffer->size;
|
|
||||||
}
|
|
||||||
buffer->datalength -= numbytes;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// flush the whole buffer
|
|
||||||
buffer->datalength = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char bufferGetAtIndex(cBuffer* buffer, unsigned short index)
|
|
||||||
{
|
|
||||||
// return character at index in buffer
|
|
||||||
return buffer->dataptr[(buffer->dataindex+index)%(buffer->size)];
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char bufferAddToEnd(cBuffer* buffer, unsigned char data)
|
|
||||||
{
|
|
||||||
// make sure the buffer has room
|
|
||||||
if(buffer->datalength < buffer->size)
|
|
||||||
{
|
|
||||||
// save data byte at end of buffer
|
|
||||||
buffer->dataptr[(buffer->dataindex + buffer->datalength) % buffer->size] = data;
|
|
||||||
// increment the length
|
|
||||||
buffer->datalength++;
|
|
||||||
// return success
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char bufferIsNotFull(cBuffer* buffer)
|
|
||||||
{
|
|
||||||
// check to see if the buffer has room
|
|
||||||
// return true if there is room
|
|
||||||
return (buffer->datalength < buffer->size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bufferFlush(cBuffer* buffer)
|
|
||||||
{
|
|
||||||
// flush contents of the buffer
|
|
||||||
buffer->datalength = 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
|||||||
/*! \file buffer.h \brief Multipurpose byte buffer structure and methods. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'buffer.h'
|
|
||||||
// Title : Multipurpose byte buffer structure and methods
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2001-2002
|
|
||||||
// Created : 9/23/2001
|
|
||||||
// Revised : 11/16/2002
|
|
||||||
// Version : 1.1
|
|
||||||
// Target MCU : any
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef BUFFER_H
|
|
||||||
#define BUFFER_H
|
|
||||||
|
|
||||||
// structure/typdefs
|
|
||||||
|
|
||||||
// the cBuffer structure
|
|
||||||
typedef struct struct_cBuffer
|
|
||||||
{
|
|
||||||
unsigned char *dataptr; // the physical memory address where the buffer is stored
|
|
||||||
unsigned short size; // the allocated size of the buffer
|
|
||||||
unsigned short datalength; // the length of the data currently in the buffer
|
|
||||||
unsigned short dataindex; // the index into the buffer where the data starts
|
|
||||||
} cBuffer;
|
|
||||||
|
|
||||||
// function prototypes
|
|
||||||
|
|
||||||
//! initialize a buffer to start at a given address and have given size
|
|
||||||
void bufferInit(cBuffer* buffer, unsigned char *start, unsigned short size);
|
|
||||||
|
|
||||||
//! get the first byte from the front of the buffer
|
|
||||||
unsigned char bufferGetFromFront(cBuffer* buffer);
|
|
||||||
|
|
||||||
//! dump (discard) the first numbytes from the front of the buffer
|
|
||||||
void bufferDumpFromFront(cBuffer* buffer, unsigned short numbytes);
|
|
||||||
|
|
||||||
//! get a byte at the specified index in the buffer (kind of like array access)
|
|
||||||
// ** note: this does not remove the byte that was read from the buffer
|
|
||||||
unsigned char bufferGetAtIndex(cBuffer* buffer, unsigned short index);
|
|
||||||
|
|
||||||
//! add a byte to the end of the buffer
|
|
||||||
unsigned char bufferAddToEnd(cBuffer* buffer, unsigned char data);
|
|
||||||
|
|
||||||
//! check if the buffer is full/not full (returns non-zero value if not full)
|
|
||||||
unsigned char bufferIsNotFull(cBuffer* buffer);
|
|
||||||
|
|
||||||
//! flush (clear) the contents of the buffer
|
|
||||||
void bufferFlush(cBuffer* buffer);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,390 +0,0 @@
|
|||||||
1 .file "buffer.c"
|
|
||||||
2 .arch atmega8
|
|
||||||
3 __SREG__ = 0x3f
|
|
||||||
4 __SP_H__ = 0x3e
|
|
||||||
5 __SP_L__ = 0x3d
|
|
||||||
6 __tmp_reg__ = 0
|
|
||||||
7 __zero_reg__ = 1
|
|
||||||
8 .global __do_copy_data
|
|
||||||
9 .global __do_clear_bss
|
|
||||||
12 .text
|
|
||||||
13 .Ltext0:
|
|
||||||
44 .global bufferInit
|
|
||||||
46 bufferInit:
|
|
||||||
1:../avrlib/buffer.c **** /*! \file buffer.c \brief Multipurpose byte buffer structure and methods. */
|
|
||||||
2:../avrlib/buffer.c **** //*****************************************************************************
|
|
||||||
3:../avrlib/buffer.c **** //
|
|
||||||
4:../avrlib/buffer.c **** // File Name : 'buffer.c'
|
|
||||||
5:../avrlib/buffer.c **** // Title : Multipurpose byte buffer structure and methods
|
|
||||||
6:../avrlib/buffer.c **** // Author : Pascal Stang - Copyright (C) 2001-2002
|
|
||||||
7:../avrlib/buffer.c **** // Created : 9/23/2001
|
|
||||||
8:../avrlib/buffer.c **** // Revised : 9/23/2001
|
|
||||||
9:../avrlib/buffer.c **** // Version : 1.0
|
|
||||||
10:../avrlib/buffer.c **** // Target MCU : any
|
|
||||||
11:../avrlib/buffer.c **** // Editor Tabs : 4
|
|
||||||
12:../avrlib/buffer.c **** //
|
|
||||||
13:../avrlib/buffer.c **** // This code is distributed under the GNU Public License
|
|
||||||
14:../avrlib/buffer.c **** // which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
15:../avrlib/buffer.c **** //
|
|
||||||
16:../avrlib/buffer.c **** //*****************************************************************************
|
|
||||||
17:../avrlib/buffer.c ****
|
|
||||||
18:../avrlib/buffer.c **** #include "buffer.h"
|
|
||||||
19:../avrlib/buffer.c ****
|
|
||||||
20:../avrlib/buffer.c **** // global variables
|
|
||||||
21:../avrlib/buffer.c ****
|
|
||||||
22:../avrlib/buffer.c **** // initialization
|
|
||||||
23:../avrlib/buffer.c ****
|
|
||||||
24:../avrlib/buffer.c **** void bufferInit(cBuffer* buffer, unsigned char *start, unsigned short size)
|
|
||||||
25:../avrlib/buffer.c **** {
|
|
||||||
48 .LM1:
|
|
||||||
49 /* prologue: frame size=0 */
|
|
||||||
50 /* prologue end (size=0) */
|
|
||||||
51 0000 FC01 movw r30,r24
|
|
||||||
26:../avrlib/buffer.c **** // set start pointer of the buffer
|
|
||||||
27:../avrlib/buffer.c **** buffer->dataptr = start;
|
|
||||||
53 .LM2:
|
|
||||||
54 0002 6083 st Z,r22
|
|
||||||
55 0004 7183 std Z+1,r23
|
|
||||||
28:../avrlib/buffer.c **** buffer->size = size;
|
|
||||||
57 .LM3:
|
|
||||||
58 0006 4283 std Z+2,r20
|
|
||||||
59 0008 5383 std Z+3,r21
|
|
||||||
29:../avrlib/buffer.c **** // initialize index and length
|
|
||||||
30:../avrlib/buffer.c **** buffer->dataindex = 0;
|
|
||||||
61 .LM4:
|
|
||||||
62 000a 1682 std Z+6,__zero_reg__
|
|
||||||
63 000c 1782 std Z+7,__zero_reg__
|
|
||||||
31:../avrlib/buffer.c **** buffer->datalength = 0;
|
|
||||||
65 .LM5:
|
|
||||||
66 000e 1482 std Z+4,__zero_reg__
|
|
||||||
67 0010 1582 std Z+5,__zero_reg__
|
|
||||||
68 /* epilogue: frame size=0 */
|
|
||||||
69 0012 0895 ret
|
|
||||||
70 /* epilogue end (size=1) */
|
|
||||||
71 /* function bufferInit size 10 (9) */
|
|
||||||
73 .Lscope0:
|
|
||||||
77 .global bufferGetFromFront
|
|
||||||
79 bufferGetFromFront:
|
|
||||||
32:../avrlib/buffer.c **** }
|
|
||||||
33:../avrlib/buffer.c ****
|
|
||||||
34:../avrlib/buffer.c **** // access routines
|
|
||||||
35:../avrlib/buffer.c **** unsigned char bufferGetFromFront(cBuffer* buffer)
|
|
||||||
36:../avrlib/buffer.c **** {
|
|
||||||
81 .LM6:
|
|
||||||
82 /* prologue: frame size=0 */
|
|
||||||
83 0014 CF93 push r28
|
|
||||||
84 0016 DF93 push r29
|
|
||||||
85 /* prologue end (size=2) */
|
|
||||||
86 0018 EC01 movw r28,r24
|
|
||||||
37:../avrlib/buffer.c **** unsigned char data = 0;
|
|
||||||
88 .LM7:
|
|
||||||
89 001a E0E0 ldi r30,lo8(0)
|
|
||||||
38:../avrlib/buffer.c ****
|
|
||||||
39:../avrlib/buffer.c **** // check to see if there's data in the buffer
|
|
||||||
40:../avrlib/buffer.c **** if(buffer->datalength)
|
|
||||||
91 .LM8:
|
|
||||||
92 001c 2C81 ldd r18,Y+4
|
|
||||||
93 001e 3D81 ldd r19,Y+5
|
|
||||||
94 0020 2115 cp r18,__zero_reg__
|
|
||||||
95 0022 3105 cpc r19,__zero_reg__
|
|
||||||
96 0024 B1F0 breq .L3
|
|
||||||
41:../avrlib/buffer.c **** {
|
|
||||||
42:../avrlib/buffer.c **** // get the first character from buffer
|
|
||||||
43:../avrlib/buffer.c **** data = buffer->dataptr[buffer->dataindex];
|
|
||||||
98 .LM9:
|
|
||||||
99 0026 E881 ld r30,Y
|
|
||||||
100 0028 F981 ldd r31,Y+1
|
|
||||||
101 002a 8E81 ldd r24,Y+6
|
|
||||||
102 002c 9F81 ldd r25,Y+7
|
|
||||||
103 002e E80F add r30,r24
|
|
||||||
104 0030 F91F adc r31,r25
|
|
||||||
105 0032 E081 ld r30,Z
|
|
||||||
44:../avrlib/buffer.c **** // move index down and decrement length
|
|
||||||
45:../avrlib/buffer.c **** buffer->dataindex++;
|
|
||||||
107 .LM10:
|
|
||||||
108 0034 0196 adiw r24,1
|
|
||||||
109 0036 8E83 std Y+6,r24
|
|
||||||
110 0038 9F83 std Y+7,r25
|
|
||||||
46:../avrlib/buffer.c **** if(buffer->dataindex >= buffer->size)
|
|
||||||
112 .LM11:
|
|
||||||
113 003a 6A81 ldd r22,Y+2
|
|
||||||
114 003c 7B81 ldd r23,Y+3
|
|
||||||
115 003e 8617 cp r24,r22
|
|
||||||
116 0040 9707 cpc r25,r23
|
|
||||||
117 0042 18F0 brlo .L4
|
|
||||||
47:../avrlib/buffer.c **** {
|
|
||||||
48:../avrlib/buffer.c **** buffer->dataindex %= buffer->size;
|
|
||||||
119 .LM12:
|
|
||||||
120 0044 00D0 rcall __udivmodhi4
|
|
||||||
121 0046 8E83 std Y+6,r24
|
|
||||||
122 0048 9F83 std Y+7,r25
|
|
||||||
123 .L4:
|
|
||||||
49:../avrlib/buffer.c **** }
|
|
||||||
50:../avrlib/buffer.c **** buffer->datalength--;
|
|
||||||
125 .LM13:
|
|
||||||
126 004a 2150 subi r18,lo8(-(-1))
|
|
||||||
127 004c 3040 sbci r19,hi8(-(-1))
|
|
||||||
128 004e 2C83 std Y+4,r18
|
|
||||||
129 0050 3D83 std Y+5,r19
|
|
||||||
130 .L3:
|
|
||||||
51:../avrlib/buffer.c **** }
|
|
||||||
52:../avrlib/buffer.c **** // return
|
|
||||||
53:../avrlib/buffer.c **** return data;
|
|
||||||
54:../avrlib/buffer.c **** }
|
|
||||||
132 .LM14:
|
|
||||||
133 0052 8E2F mov r24,r30
|
|
||||||
134 0054 9927 clr r25
|
|
||||||
135 /* epilogue: frame size=0 */
|
|
||||||
136 0056 DF91 pop r29
|
|
||||||
137 0058 CF91 pop r28
|
|
||||||
138 005a 0895 ret
|
|
||||||
139 /* epilogue end (size=3) */
|
|
||||||
140 /* function bufferGetFromFront size 36 (31) */
|
|
||||||
145 .Lscope1:
|
|
||||||
150 .global bufferDumpFromFront
|
|
||||||
152 bufferDumpFromFront:
|
|
||||||
55:../avrlib/buffer.c ****
|
|
||||||
56:../avrlib/buffer.c **** void bufferDumpFromFront(cBuffer* buffer, unsigned short numbytes)
|
|
||||||
57:../avrlib/buffer.c **** {
|
|
||||||
154 .LM15:
|
|
||||||
155 /* prologue: frame size=0 */
|
|
||||||
156 005c CF93 push r28
|
|
||||||
157 005e DF93 push r29
|
|
||||||
158 /* prologue end (size=2) */
|
|
||||||
159 0060 FC01 movw r30,r24
|
|
||||||
160 0062 EB01 movw r28,r22
|
|
||||||
58:../avrlib/buffer.c **** // dump numbytes from the front of the buffer
|
|
||||||
59:../avrlib/buffer.c **** // are we dumping less than the entire buffer?
|
|
||||||
60:../avrlib/buffer.c **** if(numbytes < buffer->datalength)
|
|
||||||
162 .LM16:
|
|
||||||
163 0064 2481 ldd r18,Z+4
|
|
||||||
164 0066 3581 ldd r19,Z+5
|
|
||||||
165 0068 6217 cp r22,r18
|
|
||||||
166 006a 7307 cpc r23,r19
|
|
||||||
167 006c 98F4 brsh .L6
|
|
||||||
61:../avrlib/buffer.c **** {
|
|
||||||
62:../avrlib/buffer.c **** // move index down by numbytes and decrement length by numbytes
|
|
||||||
63:../avrlib/buffer.c **** buffer->dataindex += numbytes;
|
|
||||||
169 .LM17:
|
|
||||||
170 006e 8681 ldd r24,Z+6
|
|
||||||
171 0070 9781 ldd r25,Z+7
|
|
||||||
172 0072 860F add r24,r22
|
|
||||||
173 0074 971F adc r25,r23
|
|
||||||
174 0076 8683 std Z+6,r24
|
|
||||||
175 0078 9783 std Z+7,r25
|
|
||||||
64:../avrlib/buffer.c **** if(buffer->dataindex >= buffer->size)
|
|
||||||
177 .LM18:
|
|
||||||
178 007a 6281 ldd r22,Z+2
|
|
||||||
179 007c 7381 ldd r23,Z+3
|
|
||||||
180 007e 8617 cp r24,r22
|
|
||||||
181 0080 9707 cpc r25,r23
|
|
||||||
182 0082 18F0 brlo .L7
|
|
||||||
65:../avrlib/buffer.c **** {
|
|
||||||
66:../avrlib/buffer.c **** buffer->dataindex %= buffer->size;
|
|
||||||
184 .LM19:
|
|
||||||
185 0084 00D0 rcall __udivmodhi4
|
|
||||||
186 0086 8683 std Z+6,r24
|
|
||||||
187 0088 9783 std Z+7,r25
|
|
||||||
188 .L7:
|
|
||||||
67:../avrlib/buffer.c **** }
|
|
||||||
68:../avrlib/buffer.c **** buffer->datalength -= numbytes;
|
|
||||||
190 .LM20:
|
|
||||||
191 008a 2C1B sub r18,r28
|
|
||||||
192 008c 3D0B sbc r19,r29
|
|
||||||
193 008e 2483 std Z+4,r18
|
|
||||||
194 0090 3583 std Z+5,r19
|
|
||||||
195 0092 02C0 rjmp .L5
|
|
||||||
196 .L6:
|
|
||||||
69:../avrlib/buffer.c **** }
|
|
||||||
70:../avrlib/buffer.c **** else
|
|
||||||
71:../avrlib/buffer.c **** {
|
|
||||||
72:../avrlib/buffer.c **** // flush the whole buffer
|
|
||||||
73:../avrlib/buffer.c **** buffer->datalength = 0;
|
|
||||||
198 .LM21:
|
|
||||||
199 0094 1482 std Z+4,__zero_reg__
|
|
||||||
200 0096 1582 std Z+5,__zero_reg__
|
|
||||||
201 .L5:
|
|
||||||
202 /* epilogue: frame size=0 */
|
|
||||||
203 0098 DF91 pop r29
|
|
||||||
204 009a CF91 pop r28
|
|
||||||
205 009c 0895 ret
|
|
||||||
206 /* epilogue end (size=3) */
|
|
||||||
207 /* function bufferDumpFromFront size 33 (28) */
|
|
||||||
209 .Lscope2:
|
|
||||||
214 .global bufferGetAtIndex
|
|
||||||
216 bufferGetAtIndex:
|
|
||||||
74:../avrlib/buffer.c **** }
|
|
||||||
75:../avrlib/buffer.c **** }
|
|
||||||
76:../avrlib/buffer.c ****
|
|
||||||
77:../avrlib/buffer.c **** unsigned char bufferGetAtIndex(cBuffer* buffer, unsigned short index)
|
|
||||||
78:../avrlib/buffer.c **** {
|
|
||||||
218 .LM22:
|
|
||||||
219 /* prologue: frame size=0 */
|
|
||||||
220 /* prologue end (size=0) */
|
|
||||||
221 009e FC01 movw r30,r24
|
|
||||||
79:../avrlib/buffer.c **** // return character at index in buffer
|
|
||||||
80:../avrlib/buffer.c **** return buffer->dataptr[(buffer->dataindex+index)%(buffer->size)];
|
|
||||||
223 .LM23:
|
|
||||||
224 00a0 8681 ldd r24,Z+6
|
|
||||||
225 00a2 9781 ldd r25,Z+7
|
|
||||||
226 00a4 2281 ldd r18,Z+2
|
|
||||||
227 00a6 3381 ldd r19,Z+3
|
|
||||||
228 00a8 860F add r24,r22
|
|
||||||
229 00aa 971F adc r25,r23
|
|
||||||
230 00ac B901 movw r22,r18
|
|
||||||
231 00ae 00D0 rcall __udivmodhi4
|
|
||||||
232 00b0 0190 ld __tmp_reg__,Z+
|
|
||||||
233 00b2 F081 ld r31,Z
|
|
||||||
234 00b4 E02D mov r30,__tmp_reg__
|
|
||||||
235 00b6 E80F add r30,r24
|
|
||||||
236 00b8 F91F adc r31,r25
|
|
||||||
237 00ba 8081 ld r24,Z
|
|
||||||
81:../avrlib/buffer.c **** }
|
|
||||||
239 .LM24:
|
|
||||||
240 00bc 9927 clr r25
|
|
||||||
241 /* epilogue: frame size=0 */
|
|
||||||
242 00be 0895 ret
|
|
||||||
243 /* epilogue end (size=1) */
|
|
||||||
244 /* function bufferGetAtIndex size 17 (16) */
|
|
||||||
246 .Lscope3:
|
|
||||||
251 .global bufferAddToEnd
|
|
||||||
253 bufferAddToEnd:
|
|
||||||
82:../avrlib/buffer.c ****
|
|
||||||
83:../avrlib/buffer.c **** unsigned char bufferAddToEnd(cBuffer* buffer, unsigned char data)
|
|
||||||
84:../avrlib/buffer.c **** {
|
|
||||||
255 .LM25:
|
|
||||||
256 /* prologue: frame size=0 */
|
|
||||||
257 00c0 CF93 push r28
|
|
||||||
258 00c2 DF93 push r29
|
|
||||||
259 /* prologue end (size=2) */
|
|
||||||
260 00c4 EC01 movw r28,r24
|
|
||||||
261 00c6 462F mov r20,r22
|
|
||||||
85:../avrlib/buffer.c **** // make sure the buffer has room
|
|
||||||
86:../avrlib/buffer.c **** if(buffer->datalength < buffer->size)
|
|
||||||
263 .LM26:
|
|
||||||
264 00c8 2C81 ldd r18,Y+4
|
|
||||||
265 00ca 3D81 ldd r19,Y+5
|
|
||||||
266 00cc 6A81 ldd r22,Y+2
|
|
||||||
267 00ce 7B81 ldd r23,Y+3
|
|
||||||
268 00d0 2617 cp r18,r22
|
|
||||||
269 00d2 3707 cpc r19,r23
|
|
||||||
270 00d4 90F4 brsh .L11
|
|
||||||
87:../avrlib/buffer.c **** {
|
|
||||||
88:../avrlib/buffer.c **** // save data byte at end of buffer
|
|
||||||
89:../avrlib/buffer.c **** buffer->dataptr[(buffer->dataindex + buffer->datalength) % buffer->size] = data;
|
|
||||||
272 .LM27:
|
|
||||||
273 00d6 8E81 ldd r24,Y+6
|
|
||||||
274 00d8 9F81 ldd r25,Y+7
|
|
||||||
275 00da 820F add r24,r18
|
|
||||||
276 00dc 931F adc r25,r19
|
|
||||||
277 00de 00D0 rcall __udivmodhi4
|
|
||||||
278 00e0 E881 ld r30,Y
|
|
||||||
279 00e2 F981 ldd r31,Y+1
|
|
||||||
280 00e4 E80F add r30,r24
|
|
||||||
281 00e6 F91F adc r31,r25
|
|
||||||
282 00e8 4083 st Z,r20
|
|
||||||
90:../avrlib/buffer.c **** // increment the length
|
|
||||||
91:../avrlib/buffer.c **** buffer->datalength++;
|
|
||||||
284 .LM28:
|
|
||||||
285 00ea 8C81 ldd r24,Y+4
|
|
||||||
286 00ec 9D81 ldd r25,Y+5
|
|
||||||
287 00ee 0196 adiw r24,1
|
|
||||||
288 00f0 8C83 std Y+4,r24
|
|
||||||
289 00f2 9D83 std Y+5,r25
|
|
||||||
92:../avrlib/buffer.c **** // return success
|
|
||||||
93:../avrlib/buffer.c **** return -1;
|
|
||||||
291 .LM29:
|
|
||||||
292 00f4 8FEF ldi r24,lo8(255)
|
|
||||||
293 00f6 90E0 ldi r25,hi8(255)
|
|
||||||
294 00f8 02C0 rjmp .L10
|
|
||||||
295 .L11:
|
|
||||||
94:../avrlib/buffer.c **** }
|
|
||||||
95:../avrlib/buffer.c **** else return 0;
|
|
||||||
297 .LM30:
|
|
||||||
298 00fa 80E0 ldi r24,lo8(0)
|
|
||||||
299 00fc 90E0 ldi r25,hi8(0)
|
|
||||||
300 .L10:
|
|
||||||
301 /* epilogue: frame size=0 */
|
|
||||||
302 00fe DF91 pop r29
|
|
||||||
303 0100 CF91 pop r28
|
|
||||||
304 0102 0895 ret
|
|
||||||
305 /* epilogue end (size=3) */
|
|
||||||
306 /* function bufferAddToEnd size 34 (29) */
|
|
||||||
308 .Lscope4:
|
|
||||||
312 .global bufferIsNotFull
|
|
||||||
314 bufferIsNotFull:
|
|
||||||
96:../avrlib/buffer.c **** }
|
|
||||||
97:../avrlib/buffer.c ****
|
|
||||||
98:../avrlib/buffer.c **** unsigned char bufferIsNotFull(cBuffer* buffer)
|
|
||||||
99:../avrlib/buffer.c **** {
|
|
||||||
316 .LM31:
|
|
||||||
317 /* prologue: frame size=0 */
|
|
||||||
318 /* prologue end (size=0) */
|
|
||||||
319 0104 FC01 movw r30,r24
|
|
||||||
100:../avrlib/buffer.c **** // check to see if the buffer has room
|
|
||||||
101:../avrlib/buffer.c **** // return true if there is room
|
|
||||||
102:../avrlib/buffer.c **** return (buffer->datalength < buffer->size);
|
|
||||||
321 .LM32:
|
|
||||||
322 0106 40E0 ldi r20,lo8(0)
|
|
||||||
323 0108 50E0 ldi r21,hi8(0)
|
|
||||||
324 010a 2481 ldd r18,Z+4
|
|
||||||
325 010c 3581 ldd r19,Z+5
|
|
||||||
326 010e 8281 ldd r24,Z+2
|
|
||||||
327 0110 9381 ldd r25,Z+3
|
|
||||||
328 0112 2817 cp r18,r24
|
|
||||||
329 0114 3907 cpc r19,r25
|
|
||||||
330 0116 10F4 brsh .L14
|
|
||||||
332 .LM33:
|
|
||||||
333 0118 41E0 ldi r20,lo8(1)
|
|
||||||
334 011a 50E0 ldi r21,hi8(1)
|
|
||||||
335 .L14:
|
|
||||||
103:../avrlib/buffer.c **** }
|
|
||||||
337 .LM34:
|
|
||||||
338 011c CA01 movw r24,r20
|
|
||||||
339 /* epilogue: frame size=0 */
|
|
||||||
340 011e 0895 ret
|
|
||||||
341 /* epilogue end (size=1) */
|
|
||||||
342 /* function bufferIsNotFull size 14 (13) */
|
|
||||||
344 .Lscope5:
|
|
||||||
348 .global bufferFlush
|
|
||||||
350 bufferFlush:
|
|
||||||
104:../avrlib/buffer.c ****
|
|
||||||
105:../avrlib/buffer.c **** void bufferFlush(cBuffer* buffer)
|
|
||||||
106:../avrlib/buffer.c **** {
|
|
||||||
352 .LM35:
|
|
||||||
353 /* prologue: frame size=0 */
|
|
||||||
354 /* prologue end (size=0) */
|
|
||||||
107:../avrlib/buffer.c **** // flush contents of the buffer
|
|
||||||
108:../avrlib/buffer.c **** buffer->datalength = 0;
|
|
||||||
356 .LM36:
|
|
||||||
357 0120 FC01 movw r30,r24
|
|
||||||
358 0122 1482 std Z+4,__zero_reg__
|
|
||||||
359 0124 1582 std Z+5,__zero_reg__
|
|
||||||
360 /* epilogue: frame size=0 */
|
|
||||||
361 0126 0895 ret
|
|
||||||
362 /* epilogue end (size=1) */
|
|
||||||
363 /* function bufferFlush size 4 (3) */
|
|
||||||
365 .Lscope6:
|
|
||||||
367 .text
|
|
||||||
369 Letext:
|
|
||||||
370 /* File "../avrlib/buffer.c": code 148 = 0x0094 ( 129), prologues 6, epilogues 13 */
|
|
||||||
DEFINED SYMBOLS
|
|
||||||
*ABS*:00000000 buffer.c
|
|
||||||
*ABS*:0000003f __SREG__
|
|
||||||
*ABS*:0000003e __SP_H__
|
|
||||||
*ABS*:0000003d __SP_L__
|
|
||||||
*ABS*:00000000 __tmp_reg__
|
|
||||||
*ABS*:00000001 __zero_reg__
|
|
||||||
/var/tmp//ccWNR2QI.s:46 .text:00000000 bufferInit
|
|
||||||
/var/tmp//ccWNR2QI.s:79 .text:00000014 bufferGetFromFront
|
|
||||||
/var/tmp//ccWNR2QI.s:152 .text:0000005c bufferDumpFromFront
|
|
||||||
/var/tmp//ccWNR2QI.s:216 .text:0000009e bufferGetAtIndex
|
|
||||||
/var/tmp//ccWNR2QI.s:253 .text:000000c0 bufferAddToEnd
|
|
||||||
/var/tmp//ccWNR2QI.s:314 .text:00000104 bufferIsNotFull
|
|
||||||
/var/tmp//ccWNR2QI.s:350 .text:00000120 bufferFlush
|
|
||||||
/var/tmp//ccWNR2QI.s:369 .text:00000128 Letext
|
|
||||||
|
|
||||||
UNDEFINED SYMBOLS
|
|
||||||
__do_copy_data
|
|
||||||
__do_clear_bss
|
|
||||||
__udivmodhi4
|
|
@ -1,425 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (c) 1996. The Regents of the University of California (Regents).
|
|
||||||
All Rights Reserved.
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software and its
|
|
||||||
documentation for educational, research, and not-for-profit purposes, without
|
|
||||||
fee and without a signed licensing agreement, is hereby granted, provided that
|
|
||||||
the above copyright notice, this paragraph and the following two paragraphs
|
|
||||||
appear in all copies, modifications, and distributions. Contact The Office of
|
|
||||||
Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley,
|
|
||||||
CA 94720-1620, (510) 643-7201, for commercial licensing opportunities.
|
|
||||||
|
|
||||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
|
||||||
University of California, Berkeley.
|
|
||||||
|
|
||||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
|
||||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
|
|
||||||
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
|
|
||||||
REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING
|
|
||||||
DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
|
|
||||||
REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
|
|
||||||
ENHANCEMENTS, OR MODIFICATIONS.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Author: Matt Wright
|
|
||||||
Version 2.2: Calls htonl in the right places 20000620
|
|
||||||
Version 2.3: Gets typed messages right.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* Here are the possible values of the state field: */
|
|
||||||
|
|
||||||
#define EMPTY 0 /* Nothing written to packet yet */
|
|
||||||
#define ONE_MSG_ARGS 1 /* Packet has a single message; gathering arguments */
|
|
||||||
#define NEED_COUNT 2 /* Just opened a bundle; must write message name or
|
|
||||||
open another bundle */
|
|
||||||
#define GET_ARGS 3 /* Getting arguments to a message. If we see a message
|
|
||||||
name or a bundle open/close then the current message
|
|
||||||
will end. */
|
|
||||||
#define DONE 4 /* All open bundles have been closed, so can't write
|
|
||||||
anything else */
|
|
||||||
|
|
||||||
|
|
||||||
#include "OSC-client.h"
|
|
||||||
|
|
||||||
// defines to make this work with the atmel
|
|
||||||
//
|
|
||||||
#include "progmem.h"
|
|
||||||
#include "debug.h"
|
|
||||||
//#define printf debug
|
|
||||||
//
|
|
||||||
|
|
||||||
char *OSC_errorMessage;
|
|
||||||
|
|
||||||
static int OSC_padString(char *dest, char PROGMEM *str);
|
|
||||||
static int OSC_WritePadding(char *dest, int i);
|
|
||||||
static int CheckTypeTag(OSCbuf *buf, char expectedType);
|
|
||||||
|
|
||||||
void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray) {
|
|
||||||
buf->buffer = byteArray;
|
|
||||||
buf->size = size;
|
|
||||||
OSC_resetBuffer(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSC_resetBuffer(OSCbuf *buf) {
|
|
||||||
buf->bufptr = buf->buffer;
|
|
||||||
buf->state = EMPTY;
|
|
||||||
buf->bundleDepth = 0;
|
|
||||||
buf->prevCounts[0] = 0;
|
|
||||||
buf->gettingFirstUntypedArg = 0;
|
|
||||||
buf->typeStringPtr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int OSC_isBufferEmpty(OSCbuf *buf) {
|
|
||||||
return buf->bufptr == buf->buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
int OSC_freeSpaceInBuffer(OSCbuf *buf) {
|
|
||||||
return buf->size - (buf->bufptr - buf->buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
int OSC_isBufferDone(OSCbuf *buf) {
|
|
||||||
return (buf->state == DONE || buf->state == ONE_MSG_ARGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *OSC_getPacket(OSCbuf *buf) {
|
|
||||||
#ifdef ERROR_CHECK_GETPACKET
|
|
||||||
if (buf->state == DONE || buf->state == ONE_MSG_ARGS) {
|
|
||||||
return buf->buffer;
|
|
||||||
} else {
|
|
||||||
OSC_errorMessage = "Packet has unterminated bundles";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return buf->buffer;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int OSC_packetSize(OSCbuf *buf) {
|
|
||||||
#ifdef ERROR_CHECK_PACKETSIZE
|
|
||||||
if (buf->state == DONE || buf->state == ONE_MSG_ARGS) {
|
|
||||||
return (buf->bufptr - buf->buffer);
|
|
||||||
} else {
|
|
||||||
OSC_errorMessage = "Packet has unterminated bundles";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return (buf->bufptr - buf->buffer);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CheckOverflow(buf, bytesNeeded) { \
|
|
||||||
if ((bytesNeeded) > OSC_freeSpaceInBuffer(buf)) { \
|
|
||||||
OSC_errorMessage = "buffer overflow"; \
|
|
||||||
return 1; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
static void PatchMessageSize(OSCbuf *buf) {
|
|
||||||
int4byte size;
|
|
||||||
size = buf->bufptr - ((char *) buf->thisMsgSize) - 4;
|
|
||||||
*(buf->thisMsgSize) = htonl(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt) {
|
|
||||||
if (buf->state == ONE_MSG_ARGS) {
|
|
||||||
OSC_errorMessage = "Can't open a bundle in a one-message packet";
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf->state == DONE) {
|
|
||||||
OSC_errorMessage = "This packet is finished; can't open a new bundle";
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (++(buf->bundleDepth) >= MAX_BUNDLE_NESTING) {
|
|
||||||
OSC_errorMessage = "Bundles nested too deeply; change MAX_BUNDLE_NESTING in OpenSoundControl.h";
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CheckTypeTag(buf, '\0')) return 9;
|
|
||||||
|
|
||||||
if (buf->state == GET_ARGS) {
|
|
||||||
PatchMessageSize(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf->state == EMPTY) {
|
|
||||||
/* Need 16 bytes for "#bundle" and time tag */
|
|
||||||
CheckOverflow(buf, 16);
|
|
||||||
} else {
|
|
||||||
/* This bundle is inside another bundle, so we need to leave
|
|
||||||
a blank size count for the size of this current bundle. */
|
|
||||||
CheckOverflow(buf, 20);
|
|
||||||
*((int4byte *)buf->bufptr) = 0xaaaaaaaa;
|
|
||||||
buf->prevCounts[buf->bundleDepth] = (int4byte *)buf->bufptr;
|
|
||||||
|
|
||||||
buf->bufptr += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf->bufptr += OSC_padString(buf->bufptr, "#bundle");
|
|
||||||
|
|
||||||
|
|
||||||
*((OSCTimeTag *) buf->bufptr) = tt;
|
|
||||||
|
|
||||||
if (htonl(1L) != 1L) {
|
|
||||||
/* Byte swap the 8-byte integer time tag */
|
|
||||||
int4byte *intp = (int4byte *)buf->bufptr;
|
|
||||||
intp[0] = htonl(intp[0]);
|
|
||||||
intp[1] = htonl(intp[1]);
|
|
||||||
|
|
||||||
#ifdef HAS8BYTEINT
|
|
||||||
{ /* tt is a 64-bit int so we have to swap the two 32-bit words.
|
|
||||||
(Otherwise tt is a struct of two 32-bit words, and even though
|
|
||||||
each word was wrong-endian, they were in the right order
|
|
||||||
in the struct.) */
|
|
||||||
int4byte temp = intp[0];
|
|
||||||
intp[0] = intp[1];
|
|
||||||
intp[1] = temp;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
buf->bufptr += sizeof(OSCTimeTag);
|
|
||||||
|
|
||||||
buf->state = NEED_COUNT;
|
|
||||||
|
|
||||||
buf->gettingFirstUntypedArg = 0;
|
|
||||||
buf->typeStringPtr = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int OSC_closeBundle(OSCbuf *buf) {
|
|
||||||
if (buf->bundleDepth == 0) {
|
|
||||||
/* This handles EMPTY, ONE_MSG, ARGS, and DONE */
|
|
||||||
OSC_errorMessage = "Can't close bundle; no bundle is open!";
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CheckTypeTag(buf, '\0')) return 9;
|
|
||||||
|
|
||||||
if (buf->state == GET_ARGS) {
|
|
||||||
PatchMessageSize(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf->bundleDepth == 1) {
|
|
||||||
/* Closing the last bundle: No bundle size to patch */
|
|
||||||
buf->state = DONE;
|
|
||||||
} else {
|
|
||||||
/* Closing a sub-bundle: patch bundle size */
|
|
||||||
int4byte size = buf->bufptr - ((char *) buf->prevCounts[buf->bundleDepth]) - 4;
|
|
||||||
*(buf->prevCounts[buf->bundleDepth]) = htonl(size);
|
|
||||||
buf->state = NEED_COUNT;
|
|
||||||
}
|
|
||||||
|
|
||||||
--buf->bundleDepth;
|
|
||||||
buf->gettingFirstUntypedArg = 0;
|
|
||||||
buf->typeStringPtr = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int OSC_closeAllBundles(OSCbuf *buf) {
|
|
||||||
if (buf->bundleDepth == 0) {
|
|
||||||
/* This handles EMPTY, ONE_MSG, ARGS, and DONE */
|
|
||||||
OSC_errorMessage = "Can't close all bundles; no bundle is open!";
|
|
||||||
return 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CheckTypeTag(buf, '\0')) return 9;
|
|
||||||
|
|
||||||
while (buf->bundleDepth > 0) {
|
|
||||||
OSC_closeBundle(buf);
|
|
||||||
}
|
|
||||||
buf->typeStringPtr = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int OSC_writeAddress(OSCbuf *buf, char PROGMEM *name) {
|
|
||||||
int4byte paddedLength;
|
|
||||||
|
|
||||||
if (buf->state == ONE_MSG_ARGS) {
|
|
||||||
//debug(PSTR("This packet is not a bundle, so you can't write another address"));
|
|
||||||
return 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf->state == DONE) {
|
|
||||||
//debug(PSTR("This packet is finished; can't write another address"));
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CheckTypeTag(buf, '\0')) return 9;
|
|
||||||
|
|
||||||
paddedLength = OSC_effectiveStringLength(name);
|
|
||||||
|
|
||||||
if (buf->state == EMPTY) {
|
|
||||||
/* This will be a one-message packet, so no sizes to worry about */
|
|
||||||
CheckOverflow(buf, paddedLength);
|
|
||||||
buf->state = ONE_MSG_ARGS;
|
|
||||||
} else {
|
|
||||||
/* GET_ARGS or NEED_COUNT */
|
|
||||||
CheckOverflow(buf, 4+paddedLength);
|
|
||||||
if (buf->state == GET_ARGS) {
|
|
||||||
/* Close the old message */
|
|
||||||
PatchMessageSize(buf);
|
|
||||||
}
|
|
||||||
buf->thisMsgSize = (int4byte *)buf->bufptr;
|
|
||||||
*(buf->thisMsgSize) = 0xbbbbbbbb;
|
|
||||||
buf->bufptr += 4;
|
|
||||||
buf->state = GET_ARGS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now write the name */
|
|
||||||
buf->bufptr += OSC_padString(buf->bufptr, name);
|
|
||||||
buf->typeStringPtr = 0;
|
|
||||||
buf->gettingFirstUntypedArg = 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int OSC_writeAddressAndTypes(OSCbuf *buf, char PROGMEM *name, char PROGMEM *types) {
|
|
||||||
int result;
|
|
||||||
int4byte paddedLength;
|
|
||||||
|
|
||||||
if (CheckTypeTag(buf, '\0')) return 9;
|
|
||||||
|
|
||||||
result = OSC_writeAddress(buf, name);
|
|
||||||
|
|
||||||
if (result) return result;
|
|
||||||
|
|
||||||
paddedLength = OSC_effectiveStringLength(types);
|
|
||||||
|
|
||||||
CheckOverflow(buf, paddedLength);
|
|
||||||
|
|
||||||
buf->typeStringPtr = buf->bufptr + 1; /* skip comma */
|
|
||||||
buf->bufptr += OSC_padString(buf->bufptr, types);
|
|
||||||
|
|
||||||
buf->gettingFirstUntypedArg = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int CheckTypeTag(OSCbuf *buf, char expectedType) {
|
|
||||||
if (buf->typeStringPtr) {
|
|
||||||
if (*(buf->typeStringPtr) != expectedType) {
|
|
||||||
if (expectedType == '\0') {
|
|
||||||
OSC_errorMessage =
|
|
||||||
"According to the type tag I expected more arguments.";
|
|
||||||
} else if (*(buf->typeStringPtr) == '\0') {
|
|
||||||
OSC_errorMessage =
|
|
||||||
"According to the type tag I didn't expect any more arguments.";
|
|
||||||
} else {
|
|
||||||
OSC_errorMessage =
|
|
||||||
"According to the type tag I expected an argument of a different type.";
|
|
||||||
// printf("* Expected %c, string now %s\n", expectedType, buf->typeStringPtr);
|
|
||||||
}
|
|
||||||
return 9;
|
|
||||||
}
|
|
||||||
++(buf->typeStringPtr);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int OSC_writeFloatArg(OSCbuf *buf, float arg) {
|
|
||||||
int4byte *intp;
|
|
||||||
|
|
||||||
CheckOverflow(buf, 4);
|
|
||||||
|
|
||||||
if (CheckTypeTag(buf, 'f')) return 9;
|
|
||||||
|
|
||||||
/* Pretend arg is a long int so we can use htonl() */
|
|
||||||
intp = ((int4byte *) &arg);
|
|
||||||
*((int4byte *) buf->bufptr) = htonl(*intp);
|
|
||||||
|
|
||||||
buf->bufptr += 4;
|
|
||||||
|
|
||||||
buf->gettingFirstUntypedArg = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args) {
|
|
||||||
int i;
|
|
||||||
int4byte *intp;
|
|
||||||
|
|
||||||
CheckOverflow(buf, 4 * numFloats);
|
|
||||||
|
|
||||||
/* Pretend args are long ints so we can use htonl() */
|
|
||||||
intp = ((int4byte *) args);
|
|
||||||
|
|
||||||
for (i = 0; i < numFloats; i++) {
|
|
||||||
if (CheckTypeTag(buf, 'f')) return 9;
|
|
||||||
*((int4byte *) buf->bufptr) = htonl(intp[i]);
|
|
||||||
buf->bufptr += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf->gettingFirstUntypedArg = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int OSC_writeIntArg(OSCbuf *buf, int4byte arg) {
|
|
||||||
CheckOverflow(buf, 4);
|
|
||||||
if (CheckTypeTag(buf, 'i')) return 9;
|
|
||||||
|
|
||||||
*((int4byte *) buf->bufptr) = htonl(arg);
|
|
||||||
buf->bufptr += 4;
|
|
||||||
|
|
||||||
buf->gettingFirstUntypedArg = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int OSC_writeStringArg(OSCbuf *buf, char PROGMEM *arg) {
|
|
||||||
int len;
|
|
||||||
|
|
||||||
if (CheckTypeTag(buf, 's')) return 9;
|
|
||||||
|
|
||||||
len = OSC_effectiveStringLength(arg);
|
|
||||||
|
|
||||||
CheckOverflow(buf, len);
|
|
||||||
buf->bufptr += OSC_padString(buf->bufptr, arg);
|
|
||||||
|
|
||||||
buf->gettingFirstUntypedArg = 0;
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#define STRING_ALIGN_PAD 4
|
|
||||||
int OSC_effectiveStringLength(char PROGMEM *string) {
|
|
||||||
int len = strlen_P(string) + 1; /* We need space for the null char. */
|
|
||||||
|
|
||||||
/* Round up len to next multiple of STRING_ALIGN_PAD to account for alignment padding */
|
|
||||||
if ((len % STRING_ALIGN_PAD) != 0) {
|
|
||||||
len += STRING_ALIGN_PAD - (len % STRING_ALIGN_PAD);
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int OSC_padString(char *dest, char PROGMEM *str) {
|
|
||||||
int i;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
for (i = 0; (c = pgm_read_byte(str+i)) != '\0'; i++) {
|
|
||||||
dest[i] = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
return OSC_WritePadding(dest, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int OSC_WritePadding(char *dest, int i) {
|
|
||||||
dest[i] = '\0';
|
|
||||||
i++;
|
|
||||||
|
|
||||||
for (; (i % STRING_ALIGN_PAD) != 0; i++) {
|
|
||||||
dest[i] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
@ -1,192 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (c) 1996,1997. The Regents of the University of California (Regents).
|
|
||||||
All Rights Reserved.
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software and its
|
|
||||||
documentation for educational, research, and not-for-profit purposes, without
|
|
||||||
fee and without a signed licensing agreement, is hereby granted, provided that
|
|
||||||
the above copyright notice, this paragraph and the following two paragraphs
|
|
||||||
appear in all copies, modifications, and distributions. Contact The Office of
|
|
||||||
Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley,
|
|
||||||
CA 94720-1620, (510) 643-7201, for commercial licensing opportunities.
|
|
||||||
|
|
||||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
|
||||||
University of California, Berkeley.
|
|
||||||
|
|
||||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
|
||||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
|
|
||||||
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
|
|
||||||
REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING
|
|
||||||
DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
|
|
||||||
REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
|
|
||||||
ENHANCEMENTS, OR MODIFICATIONS.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
OSC-client.h: library for constructing OpenSoundControl messages.
|
|
||||||
Derived from SynthControl.h
|
|
||||||
Author: Matt Wright
|
|
||||||
Version 0.1: 6/13/97
|
|
||||||
Version 0.2: 7/21/2000: Support for type-tagged messages
|
|
||||||
|
|
||||||
|
|
||||||
General notes:
|
|
||||||
|
|
||||||
This library abstracts away the data format for the OpenSoundControl
|
|
||||||
protocol. Users of this library can construct OpenSoundControl packets
|
|
||||||
with a function call interface instead of knowing how to lay out the bits.
|
|
||||||
|
|
||||||
All issues of memory allocation are deferred to the user of this library.
|
|
||||||
There are two data structures that the user must allocate. The first
|
|
||||||
is the actual buffer that the message will be written into. This buffer
|
|
||||||
can be any size, but if it's too small there's a possibility that it
|
|
||||||
will become overfull. The other data structure is called an OSCbuf,
|
|
||||||
and it holds all the state used by the library as it's constructing
|
|
||||||
a buffer.
|
|
||||||
|
|
||||||
All procedures that have the possibility of an error condition return int,
|
|
||||||
with 0 indicating no error and nonzero indicating an error. The variable
|
|
||||||
OSC_errorMessage will be set to point to a string containing an error
|
|
||||||
message explaining what the problem is.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "OSC-timetag.h"
|
|
||||||
#include "global.h"
|
|
||||||
#include <progmem.h>
|
|
||||||
|
|
||||||
#define ATMEL
|
|
||||||
|
|
||||||
#ifdef ATMEL
|
|
||||||
#define htonl(x) \
|
|
||||||
((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
|
|
||||||
(((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The int4byte type has to be a 4-byte integer. You may have to
|
|
||||||
change this to long or something else on your system. */
|
|
||||||
#ifdef __MWERKS__
|
|
||||||
/* In Metrowerks you can set ints to be 2 or 4 bytes on 68K, but long is
|
|
||||||
always 4 bytes */
|
|
||||||
typedef long int4byte;
|
|
||||||
#else
|
|
||||||
typedef s32 int4byte;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The maximum depth of bundles within bundles within bundles within...
|
|
||||||
This is the size of a static array. If you exceed this limit you'll
|
|
||||||
get an error message. */
|
|
||||||
#define MAX_BUNDLE_NESTING 32
|
|
||||||
|
|
||||||
|
|
||||||
/* Don't ever manipulate the data in the OSCbuf struct directly. (It's
|
|
||||||
declared here in the header file only so your program will be able to
|
|
||||||
declare variables of type OSCbuf and have the right amount of memory
|
|
||||||
be allocated.) */
|
|
||||||
|
|
||||||
typedef struct OSCbuf_struct {
|
|
||||||
char *buffer; /* The buffer to hold the OSC packet */
|
|
||||||
int size; /* Size of the buffer */
|
|
||||||
char *bufptr; /* Current position as we fill the buffer */
|
|
||||||
int state; /* State of partially-constructed message */
|
|
||||||
int4byte *thisMsgSize; /* Pointer to count field before
|
|
||||||
currently-being-written message */
|
|
||||||
int4byte *prevCounts[MAX_BUNDLE_NESTING];
|
|
||||||
/* Pointers to count field before each currently
|
|
||||||
open bundle */
|
|
||||||
int bundleDepth; /* How many sub-sub-bundles are we in now? */
|
|
||||||
char *typeStringPtr; /* This pointer advances through the type
|
|
||||||
tag string as you add arguments. */
|
|
||||||
int gettingFirstUntypedArg; /* nonzero if this message doesn't have
|
|
||||||
a type tag and we're waiting for the 1st arg */
|
|
||||||
} OSCbuf;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Initialize the given OSCbuf. The user of this module must pass in the
|
|
||||||
block of memory that this OSCbuf will use for a buffer, and the number of
|
|
||||||
bytes in that block. (It's the user's job to allocate the memory because
|
|
||||||
you do it differently in different systems.) */
|
|
||||||
void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray);
|
|
||||||
|
|
||||||
|
|
||||||
/* Reset the given OSCbuf. Do this after you send out the contents of
|
|
||||||
the buffer and want to start writing new data into it. */
|
|
||||||
void OSC_resetBuffer(OSCbuf *buf);
|
|
||||||
|
|
||||||
|
|
||||||
/* Is the buffer empty? (I.e., would it be stupid to send the buffer
|
|
||||||
contents to the synth?) */
|
|
||||||
int OSC_isBufferEmpty(OSCbuf *buf);
|
|
||||||
|
|
||||||
|
|
||||||
/* How much space is left in the buffer? */
|
|
||||||
int OSC_freeSpaceInBuffer(OSCbuf *buf);
|
|
||||||
|
|
||||||
/* Does the buffer contain a valid OSC packet? (Returns nonzero if yes.) */
|
|
||||||
int OSC_isBufferDone(OSCbuf *buf);
|
|
||||||
|
|
||||||
/* When you're ready to send out the buffer (i.e., when OSC_isBufferDone()
|
|
||||||
returns true), call these two procedures to get the OSC packet that's been
|
|
||||||
assembled and its size in bytes. (And then call OSC_resetBuffer() if you
|
|
||||||
want to re-use this OSCbuf for the next packet.) */
|
|
||||||
char *OSC_getPacket(OSCbuf *buf);
|
|
||||||
int OSC_packetSize(OSCbuf *buf);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Here's the basic model for building up OSC messages in an OSCbuf:
|
|
||||||
|
|
||||||
- Make sure the OSCbuf has been initialized with OSC_initBuffer().
|
|
||||||
|
|
||||||
- To open a bundle, call OSC_openBundle(). You can then write
|
|
||||||
messages or open new bundles within the bundle you opened.
|
|
||||||
Call OSC_closeBundle() to close the bundle. Note that a packet
|
|
||||||
does not have to have a bundle; it can instead consist of just a
|
|
||||||
single message.
|
|
||||||
|
|
||||||
|
|
||||||
- For each message you want to send:
|
|
||||||
|
|
||||||
- Call OSC_writeAddress() with the name of your message. (In
|
|
||||||
addition to writing your message name into the buffer, this
|
|
||||||
procedure will also leave space for the size count of this message.)
|
|
||||||
|
|
||||||
- Alternately, call OSC_writeAddressAndTypes() with the name of
|
|
||||||
your message and with a type string listing the types of all the
|
|
||||||
arguments you will be putting in this message.
|
|
||||||
|
|
||||||
- Now write each of the arguments into the buffer, by calling one of:
|
|
||||||
OSC_writeFloatArg()
|
|
||||||
OSC_writeFloatArgs()
|
|
||||||
OSC_writeIntArg()
|
|
||||||
OSC_writeStringArg()
|
|
||||||
|
|
||||||
- Now your message is complete; you can send out the buffer or you can
|
|
||||||
add another message to it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt);
|
|
||||||
int OSC_closeBundle(OSCbuf *buf);
|
|
||||||
int OSC_closeAllBundles(OSCbuf *buf);
|
|
||||||
|
|
||||||
int OSC_writeAddress(OSCbuf *buf, char PROGMEM *name);
|
|
||||||
int OSC_writeAddressAndTypes(OSCbuf *buf, char PROGMEM *name, char PROGMEM *types);
|
|
||||||
int OSC_writeFloatArg(OSCbuf *buf, float arg);
|
|
||||||
int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args);
|
|
||||||
int OSC_writeIntArg(OSCbuf *buf, int4byte arg);
|
|
||||||
int OSC_writeStringArg(OSCbuf *buf, char PROGMEM *arg);
|
|
||||||
|
|
||||||
extern char *OSC_errorMessage;
|
|
||||||
|
|
||||||
/* How many bytes will be needed in the OSC format to hold the given
|
|
||||||
string? The length of the string, plus the null char, plus any padding
|
|
||||||
needed for 4-byte alignment. */
|
|
||||||
int OSC_effectiveStringLength(char PROGMEM *string);
|
|
@ -1,175 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (c) 1998. The Regents of the University of California (Regents).
|
|
||||||
All Rights Reserved.
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software and its
|
|
||||||
documentation for educational, research, and not-for-profit purposes, without
|
|
||||||
fee and without a signed licensing agreement, is hereby granted, provided that
|
|
||||||
the above copyright notice, this paragraph and the following two paragraphs
|
|
||||||
appear in all copies, modifications, and distributions. Contact The Office of
|
|
||||||
Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley,
|
|
||||||
CA 94720-1620, (510) 643-7201, for commercial licensing opportunities.
|
|
||||||
|
|
||||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
|
||||||
University of California, Berkeley.
|
|
||||||
|
|
||||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
|
||||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
|
|
||||||
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
|
|
||||||
REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING
|
|
||||||
DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
|
|
||||||
REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
|
|
||||||
ENHANCEMENTS, OR MODIFICATIONS.
|
|
||||||
|
|
||||||
The OpenSound Control WWW page is
|
|
||||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
OSC_timeTag.c: library for manipulating OSC time tags
|
|
||||||
Matt Wright, 5/29/97
|
|
||||||
|
|
||||||
Version 0.2 (9/11/98): cleaned up so no explicit type names in the .c file.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "OSC-timetag.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAS8BYTEINT
|
|
||||||
#define TWO_TO_THE_32_FLOAT 4294967296.0f
|
|
||||||
|
|
||||||
OSCTimeTag OSCTT_Immediately(void) {
|
|
||||||
return (OSCTimeTag) 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
OSCTimeTag OSCTT_BiggestPossibleTimeTag(void) {
|
|
||||||
return (OSCTimeTag) 0xffffffffffffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) {
|
|
||||||
int64 offset = (int64) (secondsOffset * TWO_TO_THE_32_FLOAT);
|
|
||||||
|
|
||||||
/* printf("* OSCTT_PlusSeconds %llx plus %f seconds (i.e., %lld offset) is %llx\n", original,
|
|
||||||
secondsOffset, offset, original + offset); */
|
|
||||||
|
|
||||||
return original + offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
int OSCTT_Compare(OSCTimeTag left, OSCTimeTag right) {
|
|
||||||
#if 0
|
|
||||||
printf("***** OSCTT_Compare(%llx, %llx): %d\n", left, right,
|
|
||||||
(left<right) ? -1 : ((left == right) ? 0 : 1));
|
|
||||||
#endif
|
|
||||||
if (left < right) {
|
|
||||||
return -1;
|
|
||||||
} else if (left == right) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __sgi
|
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
#define SECONDS_FROM_1900_to_1970 2208988800 /* 17 leap years */
|
|
||||||
#define TWO_TO_THE_32_OVER_ONE_MILLION 4295
|
|
||||||
|
|
||||||
|
|
||||||
OSCTimeTag OSCTT_CurrentTime(void) {
|
|
||||||
uint64 result;
|
|
||||||
uint32 usecOffset;
|
|
||||||
struct timeval tv;
|
|
||||||
struct timezone tz;
|
|
||||||
|
|
||||||
BSDgettimeofday(&tv, &tz);
|
|
||||||
|
|
||||||
/* First get the seconds right */
|
|
||||||
result = (unsigned) SECONDS_FROM_1900_to_1970 +
|
|
||||||
(unsigned) tv.tv_sec -
|
|
||||||
(unsigned) 60 * tz.tz_minuteswest +
|
|
||||||
(unsigned) (tz.tz_dsttime ? 3600 : 0);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* No timezone, no DST version ... */
|
|
||||||
result = (unsigned) SECONDS_FROM_1900_to_1970 +
|
|
||||||
(unsigned) tv.tv_sec;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* make seconds the high-order 32 bits */
|
|
||||||
result = result << 32;
|
|
||||||
|
|
||||||
/* Now get the fractional part. */
|
|
||||||
usecOffset = (unsigned) tv.tv_usec * (unsigned) TWO_TO_THE_32_OVER_ONE_MILLION;
|
|
||||||
/* printf("** %ld microsec is offset %x\n", tv.tv_usec, usecOffset); */
|
|
||||||
|
|
||||||
result += usecOffset;
|
|
||||||
|
|
||||||
/* printf("* OSCTT_CurrentTime is %llx\n", result); */
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* __sgi */
|
|
||||||
|
|
||||||
/* Instead of asking your operating system what time it is, it might be
|
|
||||||
clever to find out the current time at the instant your application
|
|
||||||
starts audio processing, and then keep track of the number of samples
|
|
||||||
output to know how much time has passed. */
|
|
||||||
|
|
||||||
/* Loser version for systems that have no ability to tell the current time: */
|
|
||||||
OSCTimeTag OSCTT_CurrentTime(void) {
|
|
||||||
return (OSCTimeTag) 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __sgi */
|
|
||||||
|
|
||||||
|
|
||||||
#else /* Not HAS8BYTEINT */
|
|
||||||
|
|
||||||
OSCTimeTag OSCTT_CurrentTime(void) {
|
|
||||||
OSCTimeTag result;
|
|
||||||
result.seconds = 0;
|
|
||||||
result.fraction = 1;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
OSCTimeTag OSCTT_BiggestPossibleTimeTag(void) {
|
|
||||||
OSCTimeTag result;
|
|
||||||
result.seconds = 0xffffffff;
|
|
||||||
result.fraction = 0xffffffff;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
OSCTimeTag OSCTT_Immediately(void) {
|
|
||||||
OSCTimeTag result;
|
|
||||||
result.seconds = 0;
|
|
||||||
result.fraction = 1;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) {
|
|
||||||
OSCTimeTag result;
|
|
||||||
result.seconds = 0;
|
|
||||||
result.fraction = 1;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int OSCTT_Compare(OSCTimeTag left, OSCTimeTag right) {
|
|
||||||
/* Untested! */
|
|
||||||
int highResult = left.seconds - right.seconds;
|
|
||||||
|
|
||||||
if (highResult != 0) return highResult;
|
|
||||||
|
|
||||||
return left.fraction - right.fraction;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAS8BYTEINT */
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (c) 1998. The Regents of the University of California (Regents).
|
|
||||||
All Rights Reserved.
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software and its
|
|
||||||
documentation for educational, research, and not-for-profit purposes, without
|
|
||||||
fee and without a signed licensing agreement, is hereby granted, provided that
|
|
||||||
the above copyright notice, this paragraph and the following two paragraphs
|
|
||||||
appear in all copies, modifications, and distributions. Contact The Office of
|
|
||||||
Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley,
|
|
||||||
CA 94720-1620, (510) 643-7201, for commercial licensing opportunities.
|
|
||||||
|
|
||||||
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
|
||||||
University of California, Berkeley.
|
|
||||||
|
|
||||||
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
|
||||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
|
|
||||||
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
|
|
||||||
REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING
|
|
||||||
DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
|
|
||||||
REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
|
|
||||||
ENHANCEMENTS, OR MODIFICATIONS.
|
|
||||||
|
|
||||||
The OpenSound Control WWW page is
|
|
||||||
http://www.cnmat.berkeley.edu/OpenSoundControl
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
OSC_timeTag.h: library for manipulating OSC time tags
|
|
||||||
Matt Wright, 5/29/97
|
|
||||||
|
|
||||||
Time tags in OSC have the same format as in NTP: 64 bit fixed point, with the
|
|
||||||
top 32 bits giving number of seconds sinve midnight 1/1/1900 and the bottom
|
|
||||||
32 bits giving fractional parts of a second. We represent this by a 64-bit
|
|
||||||
unsigned long if possible, or else a struct.
|
|
||||||
|
|
||||||
NB: On many architectures with 64-bit ints, it's illegal (like maybe a bus error)
|
|
||||||
to dereference a pointer to a 64-bit int that's not 64-bit aligned.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef OSC_TIMETAG
|
|
||||||
#define OSC_TIMETAG
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#ifdef __sgi
|
|
||||||
#define HAS8BYTEINT
|
|
||||||
/* You may have to change this typedef if there's some other
|
|
||||||
way to specify 64 bit ints on your system */
|
|
||||||
typedef long long int64;
|
|
||||||
typedef unsigned long long uint64;
|
|
||||||
typedef unsigned long uint32;
|
|
||||||
#else
|
|
||||||
/* You may have to redefine this typedef if ints on your system
|
|
||||||
aren't 32 bits. */
|
|
||||||
typedef uint32_t uint32;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAS8BYTEINT
|
|
||||||
typedef uint64 OSCTimeTag;
|
|
||||||
#else
|
|
||||||
typedef struct {
|
|
||||||
uint32 seconds;
|
|
||||||
uint32 fraction;
|
|
||||||
} OSCTimeTag;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Return a time tag representing the current time (as of when this
|
|
||||||
procedure is called). */
|
|
||||||
OSCTimeTag OSCTT_CurrentTime(void);
|
|
||||||
|
|
||||||
/* Return the time tag 0x0000000000000001, indicating to the receiving device
|
|
||||||
that it should process the message immediately. */
|
|
||||||
OSCTimeTag OSCTT_Immediately(void);
|
|
||||||
|
|
||||||
/* Return the time tag 0xffffffffffffffff, a time so far in the future that
|
|
||||||
it's effectively infinity. */
|
|
||||||
OSCTimeTag OSCTT_BiggestPossibleTimeTag(void);
|
|
||||||
|
|
||||||
/* Given a time tag and a number of seconds to add to the time tag, return
|
|
||||||
the new time tag */
|
|
||||||
OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset);
|
|
||||||
|
|
||||||
/* Compare two time tags. Return negative if first is < second, 0 if
|
|
||||||
they're equal, and positive if first > second. */
|
|
||||||
int OSCTT_Compare(OSCTimeTag left, OSCTimeTag right);
|
|
||||||
|
|
||||||
#endif /* OSC_TIMETAG */
|
|
@ -1,55 +0,0 @@
|
|||||||
|
|
||||||
#include <io.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
#include "debug.h"
|
|
||||||
#include "lcd.h"
|
|
||||||
#include "rprintf.h"
|
|
||||||
#include "timer.h"
|
|
||||||
#include "osc.h"
|
|
||||||
|
|
||||||
|
|
||||||
u08 debugMode = 0;
|
|
||||||
u08 lcdDebugX;
|
|
||||||
u08 lcdDebugY;
|
|
||||||
|
|
||||||
void debugInitLCD(u08 x, u08 y) {
|
|
||||||
lcdInit();
|
|
||||||
lcdClear();
|
|
||||||
|
|
||||||
lcdDebugX = x;
|
|
||||||
lcdDebugY = y;
|
|
||||||
|
|
||||||
debugMode |= DEBUG_MODE_LCD;
|
|
||||||
|
|
||||||
debug(PSTR("LCD Debug init()"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void debugInitOSC(void) {
|
|
||||||
oscInit();
|
|
||||||
debugMode |= DEBUG_MODE_OSC;
|
|
||||||
}
|
|
||||||
|
|
||||||
void debug(const char PROGMEM *fmt) {
|
|
||||||
int code;
|
|
||||||
|
|
||||||
if (debugMode & DEBUG_MODE_OSC) {
|
|
||||||
oscSendMessageString("/debug",fmt);
|
|
||||||
}
|
|
||||||
if (debugMode & DEBUG_MODE_LCD) {
|
|
||||||
rprintfInit(&lcdDataWrite);
|
|
||||||
lcdGotoXY(lcdDebugX,lcdDebugY);
|
|
||||||
rprintf1RamRom(STRING_IN_ROM, fmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// debugFlush assumes that timerInit() have been called already
|
|
||||||
void debugFlash(const u08 port, const u08 pin) {
|
|
||||||
sbi(DDR(port), pin);
|
|
||||||
cbi(port, pin);
|
|
||||||
timerPause(500);
|
|
||||||
sbi(port, pin);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
#ifndef _DEBUG_H
|
|
||||||
#define _DEBUG_H
|
|
||||||
|
|
||||||
#include <progmem.h>
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
#define DEBUG_MODE_LCD 0x01
|
|
||||||
#define DEBUG_MODE_SERIAL 0x02
|
|
||||||
#define DEBUG_MODE_OSC 0x04
|
|
||||||
|
|
||||||
void debugInitLCD(u08 x, u08 y);
|
|
||||||
|
|
||||||
void debugInitOSC(void);
|
|
||||||
|
|
||||||
void debug(const char * fmt);
|
|
||||||
|
|
||||||
void debugFlash(u08 port, u08 pin);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
|||||||
// Midi.c
|
|
||||||
//
|
|
||||||
// Midi output routines for the atmel atmega163 (and others)
|
|
||||||
//
|
|
||||||
// depends on avrlib for buffer
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "uart.h"
|
|
||||||
#include "midi.h"
|
|
||||||
#include "debug.h"
|
|
||||||
|
|
||||||
|
|
||||||
void midiInit() {
|
|
||||||
uartInit();
|
|
||||||
uartSetBaudRate(MIDI_BAUD_RATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 midiNoteOnOut(u08 note, u08 vel, u08 channel) {
|
|
||||||
uartSendByte(MIDI_NOTE_ON | (channel & MIDI_CHANNEL_MASK));
|
|
||||||
uartSendByte(MIDI_DATA_MASK & note);
|
|
||||||
uartSendByte(MIDI_DATA_MASK & vel);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 midiNoteOffOut(u08 note, u08 vel, u08 channel) {
|
|
||||||
uartSendByte(MIDI_NOTE_OFF | (channel & MIDI_CHANNEL_MASK));
|
|
||||||
uartSendByte(MIDI_DATA_MASK & note);
|
|
||||||
uartSendByte(MIDI_DATA_MASK & vel);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 midiControlChangeOut(u08 controller, u08 value, u08 channel) {
|
|
||||||
uartSendByte(MIDI_CONTROL_CHANGE | (channel & MIDI_CHANNEL_MASK));
|
|
||||||
uartSendByte(MIDI_DATA_MASK & controller);
|
|
||||||
uartSendByte(MIDI_DATA_MASK & value);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 midiProgramChangeOut(u08 program, u08 channel) {
|
|
||||||
uartSendByte(MIDI_PROGRAM_CHANGE | (channel & MIDI_CHANNEL_MASK));
|
|
||||||
uartSendByte(MIDI_DATA_MASK & program);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
|||||||
#ifndef _MIDI_H
|
|
||||||
#define _MIDI_H
|
|
||||||
|
|
||||||
#define MIDI_NOTE_ON 0x90
|
|
||||||
#define MIDI_NOTE_OFF 0x80
|
|
||||||
|
|
||||||
// 1001cccc 0nnnnnnn 0vvvvvvv
|
|
||||||
#define MIDI_POLY_PRESSURE 0xA0
|
|
||||||
// 1011cccc 0nnnnnnn 0vvvvvvv
|
|
||||||
#define MIDI_CONTROL_CHANGE 0xB0
|
|
||||||
// 1100cccc 0ppppppp
|
|
||||||
#define MIDI_PROGRAM_CHANGE 0xC0
|
|
||||||
|
|
||||||
#define MIDI_DATA_MASK 0x7F
|
|
||||||
#define MIDI_STATUS_MASK 0xF0
|
|
||||||
#define MIDI_CHANNEL_MASK 0x0F
|
|
||||||
|
|
||||||
#define MIDI_BAUD_RATE 31250
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include "buffer.h"
|
|
||||||
|
|
||||||
void midiInit(void);
|
|
||||||
u08 midiNoteOnOut(u08 note, u08 vel, u08 channel);
|
|
||||||
u08 midiNoteOffOut(u08 note, u08 vel, u08 channel);
|
|
||||||
u08 midiControlChangeOut(u08 controller, u08 value, u08 channel);
|
|
||||||
u08 midiProgramChangeOut(u08 program, u08 channel);
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,96 +0,0 @@
|
|||||||
// osc.c
|
|
||||||
//
|
|
||||||
// Open Sound Control message sending fn's for avrmini
|
|
||||||
//
|
|
||||||
// Scott Wilson
|
|
||||||
// July 21, 2002
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <progmem.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include "OSC-client.h"
|
|
||||||
#include "osc.h"
|
|
||||||
//#include "debug.h"
|
|
||||||
#include "uart.h"
|
|
||||||
|
|
||||||
#define OSC_BUFFER_LEN 40
|
|
||||||
|
|
||||||
void _oscSendPacket();
|
|
||||||
|
|
||||||
u08 oscDataBuffer[OSC_BUFFER_LEN];
|
|
||||||
OSCbuf oscbuf;
|
|
||||||
|
|
||||||
void oscInit() {
|
|
||||||
uartInit();
|
|
||||||
OSC_initBuffer(&oscbuf, OSC_BUFFER_LEN, oscDataBuffer);
|
|
||||||
// debug(PSTR("OSC init ok packet"));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// call oscInit() and uartInit() before using this function
|
|
||||||
void oscSendMessage(const char PROGMEM *address) {
|
|
||||||
OSC_writeAddress(&oscbuf, address);
|
|
||||||
|
|
||||||
_oscSendPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
void oscSendMessageInt(const char PROGMEM *address, s32 arg) {
|
|
||||||
OSC_writeAddress(&oscbuf, address);
|
|
||||||
|
|
||||||
OSC_writeIntArg(&oscbuf, arg);
|
|
||||||
|
|
||||||
_oscSendPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
void oscSendMessageIntInt(const char PROGMEM *address, s32 arg, s32 arg2) {
|
|
||||||
OSC_writeAddress(&oscbuf, address);
|
|
||||||
|
|
||||||
OSC_writeIntArg(&oscbuf, arg);
|
|
||||||
OSC_writeIntArg(&oscbuf, arg2);
|
|
||||||
|
|
||||||
_oscSendPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
void oscSendMessageString(const char PROGMEM *address, const char PROGMEM *arg) {
|
|
||||||
OSC_writeAddress(&oscbuf, address);
|
|
||||||
|
|
||||||
OSC_writeStringArg(&oscbuf, arg);
|
|
||||||
|
|
||||||
_oscSendPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void _oscSendPacket() {
|
|
||||||
u08 j;
|
|
||||||
u08 *oscDataPtr;
|
|
||||||
u08 oscPacketSize;
|
|
||||||
register u08 checksum=0;
|
|
||||||
register u08 data;
|
|
||||||
|
|
||||||
// send the packet
|
|
||||||
if (OSC_isBufferDone(&oscbuf)) {
|
|
||||||
// begin packet sync byte
|
|
||||||
uartSendByte((u08)0xbe);
|
|
||||||
|
|
||||||
// send length byte
|
|
||||||
uartSendByte((u08)(OSC_BUFFER_LEN - OSC_freeSpaceInBuffer(&oscbuf)));
|
|
||||||
|
|
||||||
oscDataPtr = OSC_getPacket(&oscbuf);
|
|
||||||
oscPacketSize = OSC_packetSize(&oscbuf);
|
|
||||||
// debug(PSTR("packet size: %x"),(unsigned int)oscPacketSize);
|
|
||||||
for (j=0; j<oscPacketSize; j++) {
|
|
||||||
data = *(oscDataPtr+j);
|
|
||||||
checksum += data;
|
|
||||||
uartSendByte(data);
|
|
||||||
}
|
|
||||||
// send checksum byte
|
|
||||||
uartSendByte(checksum);
|
|
||||||
OSC_resetBuffer(&oscbuf);
|
|
||||||
} else {
|
|
||||||
//debug(PSTR("Error creating OSC packet"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
|||||||
// osc.h
|
|
||||||
//
|
|
||||||
// Open Sound Control message sending fn's for avrmini
|
|
||||||
//
|
|
||||||
// Scott Wilson
|
|
||||||
// July 21, 2002
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef _OSC_H
|
|
||||||
#define _OSC_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include <progmem.h>
|
|
||||||
|
|
||||||
#define oscSendMessageOneArg oscSendMessageInt
|
|
||||||
|
|
||||||
void oscInit(void);
|
|
||||||
void oscSendMessage(const char PROGMEM *address);
|
|
||||||
void oscSendMessageInt(const char PROGMEM *address, s32 arg);
|
|
||||||
void oscSendMessageIntInt(const char PROGMEM *address, s32 arg, s32 arg2);
|
|
||||||
void oscSendMessageString(const char PROGMEM *address, const char PROGMEM *arg);
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,448 +0,0 @@
|
|||||||
/*! \file cmdline.c \brief Command-Line Interface Library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'cmdline.c'
|
|
||||||
// Title : Command-Line Interface Library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2003
|
|
||||||
// Created : 2003.07.16
|
|
||||||
// Revised : 2003.07.23
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
//----- Include Files ---------------------------------------------------------
|
|
||||||
#include <avr/io.h> // include I/O definitions (port names, pin names, etc)
|
|
||||||
#include <avr/signal.h> // include "signal" names (interrupt names)
|
|
||||||
#include <avr/interrupt.h> // include interrupt support
|
|
||||||
#include <avr/pgmspace.h> // include AVR program memory support
|
|
||||||
#include <string.h> // include standard C string functions
|
|
||||||
#include <stdlib.h> // include stdlib for string conversion functions
|
|
||||||
|
|
||||||
#include "global.h" // include our global settings
|
|
||||||
#include "cmdline.h"
|
|
||||||
|
|
||||||
// include project-specific configuration
|
|
||||||
#include "cmdlineconf.h"
|
|
||||||
|
|
||||||
// defines
|
|
||||||
#define ASCII_BEL 0x07
|
|
||||||
#define ASCII_BS 0x08
|
|
||||||
#define ASCII_CR 0x0D
|
|
||||||
#define ASCII_LF 0x0A
|
|
||||||
#define ASCII_ESC 0x1B
|
|
||||||
#define ASCII_DEL 0x7F
|
|
||||||
|
|
||||||
#define VT100_ARROWUP 'A'
|
|
||||||
#define VT100_ARROWDOWN 'B'
|
|
||||||
#define VT100_ARROWRIGHT 'C'
|
|
||||||
#define VT100_ARROWLEFT 'D'
|
|
||||||
|
|
||||||
#define CMDLINE_HISTORY_SAVE 0
|
|
||||||
#define CMDLINE_HISTORY_PREV 1
|
|
||||||
#define CMDLINE_HISTORY_NEXT 2
|
|
||||||
|
|
||||||
|
|
||||||
// Global variables
|
|
||||||
|
|
||||||
// strings
|
|
||||||
u08 PROGMEM CmdlinePrompt[] = "cmd>";
|
|
||||||
u08 PROGMEM CmdlineNotice[] = "cmdline: ";
|
|
||||||
u08 PROGMEM CmdlineCmdNotFound[] = "command not found";
|
|
||||||
|
|
||||||
// command list
|
|
||||||
// -commands are null-terminated strings
|
|
||||||
static char CmdlineCommandList[CMDLINE_MAX_COMMANDS][CMDLINE_MAX_CMD_LENGTH];
|
|
||||||
// command function pointer list
|
|
||||||
static CmdlineFuncPtrType CmdlineFunctionList[CMDLINE_MAX_COMMANDS];
|
|
||||||
// number of commands currently registered
|
|
||||||
u08 CmdlineNumCommands;
|
|
||||||
|
|
||||||
u08 CmdlineBuffer[CMDLINE_BUFFERSIZE];
|
|
||||||
u08 CmdlineBufferLength;
|
|
||||||
u08 CmdlineBufferEditPos;
|
|
||||||
u08 CmdlineInputVT100State;
|
|
||||||
u08 CmdlineHistory[CMDLINE_HISTORYSIZE][CMDLINE_BUFFERSIZE];
|
|
||||||
CmdlineFuncPtrType CmdlineExecFunction;
|
|
||||||
|
|
||||||
// Functions
|
|
||||||
|
|
||||||
// function pointer to single character output routine
|
|
||||||
static void (*cmdlineOutputFunc)(unsigned char c);
|
|
||||||
|
|
||||||
void cmdlineInit(void)
|
|
||||||
{
|
|
||||||
// reset vt100 processing state
|
|
||||||
CmdlineInputVT100State = 0;
|
|
||||||
// initialize input buffer
|
|
||||||
CmdlineBufferLength = 0;
|
|
||||||
CmdlineBufferEditPos = 0;
|
|
||||||
// initialize executing function
|
|
||||||
CmdlineExecFunction = 0;
|
|
||||||
// initialize command list
|
|
||||||
CmdlineNumCommands = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cmdlineAddCommand(u08* newCmdString, CmdlineFuncPtrType newCmdFuncPtr)
|
|
||||||
{
|
|
||||||
// add command string to end of command list
|
|
||||||
strcpy(CmdlineCommandList[CmdlineNumCommands], newCmdString);
|
|
||||||
// add command function ptr to end of function list
|
|
||||||
CmdlineFunctionList[CmdlineNumCommands] = newCmdFuncPtr;
|
|
||||||
// increment number of registered commands
|
|
||||||
CmdlineNumCommands++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cmdlineSetOutputFunc(void (*output_func)(unsigned char c))
|
|
||||||
{
|
|
||||||
// set new output function
|
|
||||||
cmdlineOutputFunc = output_func;
|
|
||||||
|
|
||||||
// should we really do this?
|
|
||||||
// print a prompt
|
|
||||||
//cmdlinePrintPrompt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void cmdlineInputFunc(unsigned char c)
|
|
||||||
{
|
|
||||||
u08 i;
|
|
||||||
// process the received character
|
|
||||||
|
|
||||||
// VT100 handling
|
|
||||||
// are we processing a VT100 command?
|
|
||||||
if(CmdlineInputVT100State == 2)
|
|
||||||
{
|
|
||||||
// we have already received ESC and [
|
|
||||||
// now process the vt100 code
|
|
||||||
switch(c)
|
|
||||||
{
|
|
||||||
case VT100_ARROWUP:
|
|
||||||
cmdlineDoHistory(CMDLINE_HISTORY_PREV);
|
|
||||||
break;
|
|
||||||
case VT100_ARROWDOWN:
|
|
||||||
cmdlineDoHistory(CMDLINE_HISTORY_NEXT);
|
|
||||||
break;
|
|
||||||
case VT100_ARROWRIGHT:
|
|
||||||
// if the edit position less than current string length
|
|
||||||
if(CmdlineBufferEditPos < CmdlineBufferLength)
|
|
||||||
{
|
|
||||||
// increment the edit position
|
|
||||||
CmdlineBufferEditPos++;
|
|
||||||
// move cursor forward one space (no erase)
|
|
||||||
cmdlineOutputFunc(ASCII_ESC);
|
|
||||||
cmdlineOutputFunc('[');
|
|
||||||
cmdlineOutputFunc(VT100_ARROWRIGHT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// else, ring the bell
|
|
||||||
cmdlineOutputFunc(ASCII_BEL);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case VT100_ARROWLEFT:
|
|
||||||
// if the edit position is non-zero
|
|
||||||
if(CmdlineBufferEditPos)
|
|
||||||
{
|
|
||||||
// decrement the edit position
|
|
||||||
CmdlineBufferEditPos--;
|
|
||||||
// move cursor back one space (no erase)
|
|
||||||
cmdlineOutputFunc(ASCII_BS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// else, ring the bell
|
|
||||||
cmdlineOutputFunc(ASCII_BEL);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// done, reset state
|
|
||||||
CmdlineInputVT100State = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if(CmdlineInputVT100State == 1)
|
|
||||||
{
|
|
||||||
// we last received [ESC]
|
|
||||||
if(c == '[')
|
|
||||||
{
|
|
||||||
CmdlineInputVT100State = 2;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
CmdlineInputVT100State = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// anything else, reset state
|
|
||||||
CmdlineInputVT100State = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Regular handling
|
|
||||||
if( (c >= 0x20) && (c < 0x7F) )
|
|
||||||
{
|
|
||||||
// character is printable
|
|
||||||
// is this a simple append
|
|
||||||
if(CmdlineBufferEditPos == CmdlineBufferLength)
|
|
||||||
{
|
|
||||||
// echo character to the output
|
|
||||||
cmdlineOutputFunc(c);
|
|
||||||
// add it to the command line buffer
|
|
||||||
CmdlineBuffer[CmdlineBufferEditPos++] = c;
|
|
||||||
// update buffer length
|
|
||||||
CmdlineBufferLength++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// edit/cursor position != end of buffer
|
|
||||||
// we're inserting characters at a mid-line edit position
|
|
||||||
// make room at the insert point
|
|
||||||
CmdlineBufferLength++;
|
|
||||||
for(i=CmdlineBufferLength; i>CmdlineBufferEditPos; i--)
|
|
||||||
CmdlineBuffer[i] = CmdlineBuffer[i-1];
|
|
||||||
// insert character
|
|
||||||
CmdlineBuffer[CmdlineBufferEditPos++] = c;
|
|
||||||
// repaint
|
|
||||||
cmdlineRepaint();
|
|
||||||
// reposition cursor
|
|
||||||
for(i=CmdlineBufferEditPos; i<CmdlineBufferLength; i++)
|
|
||||||
cmdlineOutputFunc(ASCII_BS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// handle special characters
|
|
||||||
else if(c == ASCII_CR)
|
|
||||||
{
|
|
||||||
// user pressed [ENTER]
|
|
||||||
// echo CR and LF to terminal
|
|
||||||
cmdlineOutputFunc(ASCII_CR);
|
|
||||||
cmdlineOutputFunc(ASCII_LF);
|
|
||||||
// add null termination to command
|
|
||||||
CmdlineBuffer[CmdlineBufferLength++] = 0;
|
|
||||||
CmdlineBufferEditPos++;
|
|
||||||
// command is complete, process it
|
|
||||||
cmdlineProcessInputString();
|
|
||||||
// reset buffer
|
|
||||||
CmdlineBufferLength = 0;
|
|
||||||
CmdlineBufferEditPos = 0;
|
|
||||||
}
|
|
||||||
else if(c == ASCII_BS)
|
|
||||||
{
|
|
||||||
if(CmdlineBufferEditPos)
|
|
||||||
{
|
|
||||||
// is this a simple delete (off the end of the line)
|
|
||||||
if(CmdlineBufferEditPos == CmdlineBufferLength)
|
|
||||||
{
|
|
||||||
// destructive backspace
|
|
||||||
// echo backspace-space-backspace
|
|
||||||
cmdlineOutputFunc(ASCII_BS);
|
|
||||||
cmdlineOutputFunc(' ');
|
|
||||||
cmdlineOutputFunc(ASCII_BS);
|
|
||||||
// decrement our buffer length and edit position
|
|
||||||
CmdlineBufferLength--;
|
|
||||||
CmdlineBufferEditPos--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// edit/cursor position != end of buffer
|
|
||||||
// we're deleting characters at a mid-line edit position
|
|
||||||
// shift characters down, effectively deleting
|
|
||||||
CmdlineBufferLength--;
|
|
||||||
CmdlineBufferEditPos--;
|
|
||||||
for(i=CmdlineBufferEditPos; i<CmdlineBufferLength; i++)
|
|
||||||
CmdlineBuffer[i] = CmdlineBuffer[i+1];
|
|
||||||
// repaint
|
|
||||||
cmdlineRepaint();
|
|
||||||
// add space to clear leftover characters
|
|
||||||
cmdlineOutputFunc(' ');
|
|
||||||
// reposition cursor
|
|
||||||
for(i=CmdlineBufferEditPos; i<(CmdlineBufferLength+1); i++)
|
|
||||||
cmdlineOutputFunc(ASCII_BS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// else, ring the bell
|
|
||||||
cmdlineOutputFunc(ASCII_BEL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(c == ASCII_DEL)
|
|
||||||
{
|
|
||||||
// not yet handled
|
|
||||||
}
|
|
||||||
else if(c == ASCII_ESC)
|
|
||||||
{
|
|
||||||
CmdlineInputVT100State = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cmdlineRepaint(void)
|
|
||||||
{
|
|
||||||
u08* ptr;
|
|
||||||
u08 i;
|
|
||||||
|
|
||||||
// carriage return
|
|
||||||
cmdlineOutputFunc(ASCII_CR);
|
|
||||||
// print fresh prompt
|
|
||||||
cmdlinePrintPrompt();
|
|
||||||
// print the new command line buffer
|
|
||||||
i = CmdlineBufferLength;
|
|
||||||
ptr = CmdlineBuffer;
|
|
||||||
while(i--) cmdlineOutputFunc(*ptr++);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cmdlineDoHistory(u08 action)
|
|
||||||
{
|
|
||||||
switch(action)
|
|
||||||
{
|
|
||||||
case CMDLINE_HISTORY_SAVE:
|
|
||||||
// copy CmdlineBuffer to history if not null string
|
|
||||||
if( strlen(CmdlineBuffer) )
|
|
||||||
strcpy(CmdlineHistory[0], CmdlineBuffer);
|
|
||||||
break;
|
|
||||||
case CMDLINE_HISTORY_PREV:
|
|
||||||
// copy history to current buffer
|
|
||||||
strcpy(CmdlineBuffer, CmdlineHistory[0]);
|
|
||||||
// set the buffer position to the end of the line
|
|
||||||
CmdlineBufferLength = strlen(CmdlineBuffer);
|
|
||||||
CmdlineBufferEditPos = CmdlineBufferLength;
|
|
||||||
// "re-paint" line
|
|
||||||
cmdlineRepaint();
|
|
||||||
break;
|
|
||||||
case CMDLINE_HISTORY_NEXT:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cmdlineProcessInputString(void)
|
|
||||||
{
|
|
||||||
u08 cmdIndex;
|
|
||||||
u08 i=0;
|
|
||||||
|
|
||||||
// save command in history
|
|
||||||
cmdlineDoHistory(CMDLINE_HISTORY_SAVE);
|
|
||||||
|
|
||||||
// find the end of the command (excluding arguments)
|
|
||||||
// find first whitespace character in CmdlineBuffer
|
|
||||||
while( !((CmdlineBuffer[i] == ' ') || (CmdlineBuffer[i] == 0)) ) i++;
|
|
||||||
|
|
||||||
if(!i)
|
|
||||||
{
|
|
||||||
// command was null or empty
|
|
||||||
// output a new prompt
|
|
||||||
cmdlinePrintPrompt();
|
|
||||||
// we're done
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// search command list for match with entered command
|
|
||||||
for(cmdIndex=0; cmdIndex<CmdlineNumCommands; cmdIndex++)
|
|
||||||
{
|
|
||||||
if( !strncmp(CmdlineCommandList[cmdIndex], CmdlineBuffer, i) )
|
|
||||||
{
|
|
||||||
// user-entered command matched a command in the list (database)
|
|
||||||
// run the corresponding function
|
|
||||||
CmdlineExecFunction = CmdlineFunctionList[cmdIndex];
|
|
||||||
// new prompt will be output after user function runs
|
|
||||||
// and we're done
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we did not get a match
|
|
||||||
// output an error message
|
|
||||||
cmdlinePrintError();
|
|
||||||
// output a new prompt
|
|
||||||
cmdlinePrintPrompt();
|
|
||||||
}
|
|
||||||
|
|
||||||
void cmdlineMainLoop(void)
|
|
||||||
{
|
|
||||||
// do we have a command/function to be executed
|
|
||||||
if(CmdlineExecFunction)
|
|
||||||
{
|
|
||||||
// run it
|
|
||||||
CmdlineExecFunction();
|
|
||||||
// reset
|
|
||||||
CmdlineExecFunction = 0;
|
|
||||||
// output new prompt
|
|
||||||
cmdlinePrintPrompt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cmdlinePrintPrompt(void)
|
|
||||||
{
|
|
||||||
// print a new command prompt
|
|
||||||
u08* ptr = CmdlinePrompt;
|
|
||||||
while(pgm_read_byte(ptr)) cmdlineOutputFunc( pgm_read_byte(ptr++) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void cmdlinePrintError(void)
|
|
||||||
{
|
|
||||||
u08 * ptr;
|
|
||||||
|
|
||||||
// print a notice header
|
|
||||||
// (u08*) cast used to avoid compiler warning
|
|
||||||
ptr = (u08*)CmdlineNotice;
|
|
||||||
while(pgm_read_byte(ptr)) cmdlineOutputFunc( pgm_read_byte(ptr++) );
|
|
||||||
|
|
||||||
// print the offending command
|
|
||||||
ptr = CmdlineBuffer;
|
|
||||||
while((*ptr) && (*ptr != ' ')) cmdlineOutputFunc(*ptr++);
|
|
||||||
|
|
||||||
cmdlineOutputFunc(':');
|
|
||||||
cmdlineOutputFunc(' ');
|
|
||||||
|
|
||||||
// print the not-found message
|
|
||||||
// (u08*) cast used to avoid compiler warning
|
|
||||||
ptr = (u08*)CmdlineCmdNotFound;
|
|
||||||
while(pgm_read_byte(ptr)) cmdlineOutputFunc( pgm_read_byte(ptr++) );
|
|
||||||
|
|
||||||
cmdlineOutputFunc('\r');
|
|
||||||
cmdlineOutputFunc('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
// argument retrieval commands
|
|
||||||
|
|
||||||
// return string pointer to argument [argnum]
|
|
||||||
u08* cmdlineGetArgStr(u08 argnum)
|
|
||||||
{
|
|
||||||
// find the offset of argument number [argnum]
|
|
||||||
u08 idx=0;
|
|
||||||
u08 arg;
|
|
||||||
|
|
||||||
// find the first non-whitespace character
|
|
||||||
while( (CmdlineBuffer[idx] != 0) && (CmdlineBuffer[idx] == ' ')) idx++;
|
|
||||||
|
|
||||||
// we are at the first argument
|
|
||||||
for(arg=0; arg<argnum; arg++)
|
|
||||||
{
|
|
||||||
// find the next whitespace character
|
|
||||||
while( (CmdlineBuffer[idx] != 0) && (CmdlineBuffer[idx] != ' ')) idx++;
|
|
||||||
// find the first non-whitespace character
|
|
||||||
while( (CmdlineBuffer[idx] != 0) && (CmdlineBuffer[idx] == ' ')) idx++;
|
|
||||||
}
|
|
||||||
// we are at the requested argument or the end of the buffer
|
|
||||||
return &CmdlineBuffer[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
// return argument [argnum] interpreted as a decimal integer
|
|
||||||
long cmdlineGetArgInt(u08 argnum)
|
|
||||||
{
|
|
||||||
char* endptr;
|
|
||||||
return strtol(cmdlineGetArgStr(argnum), &endptr, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
// return argument [argnum] interpreted as a hex integer
|
|
||||||
long cmdlineGetArgHex(u08 argnum)
|
|
||||||
{
|
|
||||||
char* endptr;
|
|
||||||
return strtol(cmdlineGetArgStr(argnum), &endptr, 16);
|
|
||||||
}
|
|
@ -1,109 +0,0 @@
|
|||||||
/*! \file cmdline.h \brief Command-Line Interface Library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'cmdline.h'
|
|
||||||
// Title : Command-Line Interface Library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2003
|
|
||||||
// Created : 2003.07.16
|
|
||||||
// Revised : 2003.07.16
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// Description :
|
|
||||||
// This Command-Line interface library is meant to provide a reusable
|
|
||||||
// terminal-like user interface much like a DOS command line or UNIX terminal.
|
|
||||||
//
|
|
||||||
// The cmdline library does the following things for you:
|
|
||||||
// -Prints command prompts
|
|
||||||
// -Gathers a command string from the user (with editing features)
|
|
||||||
// -Parses the command string when the user presses [ENTER]
|
|
||||||
// -Compares the entered command to the command database
|
|
||||||
// \-Executes the corresponding function if a match is found
|
|
||||||
// \-Reports an error if no match is found
|
|
||||||
// -Provides functions to retrieve the command arguments:
|
|
||||||
// \-as strings
|
|
||||||
// \-as decimal integers
|
|
||||||
// \-as hex integers
|
|
||||||
//
|
|
||||||
// Supported editing features include:
|
|
||||||
// -Backspace support
|
|
||||||
// -Mid-line editing, inserting and deleting (left/right-arrows)
|
|
||||||
// -Command History (up-arrow) (currently only one command deep)
|
|
||||||
//
|
|
||||||
// To use the cmdline system, you will need to associate command strings
|
|
||||||
// (commands the user will be typing) with your function that you wish to have
|
|
||||||
// called when the user enters that command. This is done by using the
|
|
||||||
// cmdlineAddCommand() function.
|
|
||||||
//
|
|
||||||
// To setup the cmdline system, you must do these things:
|
|
||||||
// -Initialize it: cmdlineInit()
|
|
||||||
// -Add one or more commands to the database: cmdlineAddCommand()
|
|
||||||
// -Set an output function for your terminal: cmdlineSetOutputFunc()
|
|
||||||
//
|
|
||||||
// To operate the cmdline system, you must do these things repeatedly:
|
|
||||||
// -Pass user input from the terminal to: cmdlineSetOutputFunc()
|
|
||||||
// -Call cmdlineMainLoop() from your program's main loop
|
|
||||||
//
|
|
||||||
// The cmdline library does not assume an input or output device, but can be
|
|
||||||
// configured to use any user function for output using cmdlineSetOutputFunc()
|
|
||||||
// and accepts input by calling cmdlineInputFunc(). This means the cmdline
|
|
||||||
// library can operate over any interface including UART (serial port),
|
|
||||||
// I2c, ethernet, etc.
|
|
||||||
//
|
|
||||||
// ***** FOR MORE INFORMATION ABOUT USING cmdline SEE THE AVRLIB EXAMPLE *****
|
|
||||||
// ***** CODE IN THE avrlib/examples DIRECTORY *****
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef CMDLINE_H
|
|
||||||
#define CMDLINE_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
// constants/macros/typdefs
|
|
||||||
typedef void (*CmdlineFuncPtrType)(void);
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
//! initalize the command line system
|
|
||||||
void cmdlineInit(void);
|
|
||||||
|
|
||||||
//! add a new command to the database of known commands
|
|
||||||
// newCmdString should be a null-terminated command string with no whitespace
|
|
||||||
// newCmdFuncPtr should be a pointer to the function to execute when
|
|
||||||
// the user enters the corresponding command tring
|
|
||||||
void cmdlineAddCommand(u08* newCmdString, CmdlineFuncPtrType newCmdFuncPtr);
|
|
||||||
|
|
||||||
//! sets the function used for sending characters to the user terminal
|
|
||||||
void cmdlineSetOutputFunc(void (*output_func)(unsigned char c));
|
|
||||||
|
|
||||||
//! call this function to pass input charaters from the user terminal
|
|
||||||
void cmdlineInputFunc(unsigned char c);
|
|
||||||
|
|
||||||
//! call this function in your program's main loop
|
|
||||||
void cmdlineMainLoop(void);
|
|
||||||
|
|
||||||
// internal commands
|
|
||||||
void cmdlineRepaint(void);
|
|
||||||
void cmdlineDoHistory(u08 action);
|
|
||||||
void cmdlineProcessInputString(void);
|
|
||||||
void cmdlinePrintPrompt(void);
|
|
||||||
void cmdlinePrintError(void);
|
|
||||||
|
|
||||||
// argument retrieval commands
|
|
||||||
//! returns a string pointer to argument number [argnum] on the command line
|
|
||||||
u08* cmdlineGetArgStr(u08 argnum);
|
|
||||||
//! returns the decimal integer interpretation of argument number [argnum]
|
|
||||||
long cmdlineGetArgInt(u08 argnum);
|
|
||||||
//! returns the hex integer interpretation of argument number [argnum]
|
|
||||||
long cmdlineGetArgHex(u08 argnum);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,44 +0,0 @@
|
|||||||
/*! \file ataconf.h \brief IDE-ATA interface driver configuration. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'ataconf.h'
|
|
||||||
// Title : IDE-ATA interface driver for hard disks
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2000-2002
|
|
||||||
// Date : 11/22/2000
|
|
||||||
// Revised : 12/29/2000
|
|
||||||
// Version : 0.3
|
|
||||||
// Target MCU : Atmel AVR Series)
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef ATA_IFCONF_H
|
|
||||||
#define ATA_IFCONF_H
|
|
||||||
|
|
||||||
// constants
|
|
||||||
#define SECTOR_BUFFER_ADDR 0x1E00
|
|
||||||
|
|
||||||
// ATA register base address
|
|
||||||
#define ATA_REG_BASE 0x8000
|
|
||||||
// ATA register offset
|
|
||||||
#define ATA_REG_DATAL 0x00
|
|
||||||
#define ATA_REG_ERROR 0x01
|
|
||||||
#define ATA_REG_SECCOUNT 0x02
|
|
||||||
#define ATA_REG_STARTSEC 0x03
|
|
||||||
#define ATA_REG_CYLLO 0x04
|
|
||||||
#define ATA_REG_CYLHI 0x05
|
|
||||||
#define ATA_REG_HDDEVSEL 0x06
|
|
||||||
#define ATA_REG_CMDSTATUS1 0x07
|
|
||||||
#define ATA_REG_CMDSTATUS2 0x08
|
|
||||||
#define ATA_REG_ACTSTATUS 0x09
|
|
||||||
|
|
||||||
#define ATA_REG_DATAH 0x10
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,46 +0,0 @@
|
|||||||
/*! \file cmdlineconf.h \brief Command-Line Interface Library Configuration. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'cmdlineconf.h'
|
|
||||||
// Title : Command-Line Interface Library Configuration
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2003
|
|
||||||
// Created : 2003.07.16
|
|
||||||
// Revised : 2003.07.21
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef CMDLINECONF_H
|
|
||||||
#define CMDLINECONF_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
// constants/macros/typdefs
|
|
||||||
|
|
||||||
// size of command database
|
|
||||||
// (maximum number of commands the cmdline system can handle)
|
|
||||||
#define CMDLINE_MAX_COMMANDS 10
|
|
||||||
|
|
||||||
// maximum length (number of characters) of each command string
|
|
||||||
// (quantity must include one additional byte for a null terminator)
|
|
||||||
#define CMDLINE_MAX_CMD_LENGTH 15
|
|
||||||
|
|
||||||
// allotted buffer size for command entry
|
|
||||||
// (must be enough chars for typed commands and the arguments that follow)
|
|
||||||
#define CMDLINE_BUFFERSIZE 80
|
|
||||||
|
|
||||||
// number of lines of command history to keep
|
|
||||||
// (each history buffer is CMDLINE_BUFFERSIZE in size)
|
|
||||||
// ***** ONLY ONE LINE OF COMMAND HISTORY IS CURRENTLY SUPPORTED
|
|
||||||
#define CMDLINE_HISTORYSIZE 1
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,167 +0,0 @@
|
|||||||
/*! \file encoderconf.h \brief Quadrature Encoder driver configuration. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'encoderconf.h'
|
|
||||||
// Title : Quadrature Encoder driver configuration
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2003-2004
|
|
||||||
// Created : 2003.01.26
|
|
||||||
// Revised : 2004.06.25
|
|
||||||
// Version : 0.2
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// The default number of encoders supported is 2 because most AVR processors
|
|
||||||
// have two external interrupts. To use more or fewer encoders, you must do
|
|
||||||
// four things:
|
|
||||||
//
|
|
||||||
// 1. Use a processor with at least as many external interrutps as number of
|
|
||||||
// encoders you want to have.
|
|
||||||
// 2. Set NUM_ENCODERS to the number of encoders you will use.
|
|
||||||
// 3. Comment/Uncomment the proper ENCx_SIGNAL defines for your encoders
|
|
||||||
// (the encoders must be used sequentially, 0 then 1 then 2 then 3)
|
|
||||||
// 4. Configure the various defines so that they match your processor and
|
|
||||||
// specific hardware. The notes below may help.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// -------------------- NOTES --------------------
|
|
||||||
// The external interrupt pins are mapped as follows on most AVR processors:
|
|
||||||
// (90s8515, mega161, mega163, mega323, mega16, mega32, etc)
|
|
||||||
//
|
|
||||||
// INT0 -> PD2 (PORTD, pin 2)
|
|
||||||
// INT1 -> PD3 (PORTD, pin 3)
|
|
||||||
//
|
|
||||||
// The external interrupt pins on the processors mega128 and mega64 are:
|
|
||||||
//
|
|
||||||
// INT0 -> PD0 (PORTD, pin 0)
|
|
||||||
// INT1 -> PD1 (PORTD, pin 1)
|
|
||||||
// INT2 -> PD2 (PORTD, pin 2)
|
|
||||||
// INT3 -> PD3 (PORTD, pin 3)
|
|
||||||
// INT4 -> PE4 (PORTE, pin 4)
|
|
||||||
// INT5 -> PE5 (PORTE, pin 5)
|
|
||||||
// INT6 -> PE6 (PORTE, pin 6)
|
|
||||||
// INT7 -> PE7 (PORTE, pin 7)
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef ENCODERCONF_H
|
|
||||||
#define ENCODERCONF_H
|
|
||||||
|
|
||||||
// constants/macros/typdefs
|
|
||||||
|
|
||||||
// defines for processor compatibility
|
|
||||||
// quick compatiblity for mega128, mega64
|
|
||||||
//#ifndef MCUCR
|
|
||||||
// #define MCUCR EICRA
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
// Set the total number of encoders you wish to support
|
|
||||||
#define NUM_ENCODERS 2
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------- Encoder 0 connections --------------------
|
|
||||||
// Phase A quadrature encoder output should connect to this interrupt line:
|
|
||||||
// *** NOTE: the choice of interrupt PORT, DDR, and PIN must match the external
|
|
||||||
// interrupt you are using on your processor. Consult the External Interrupts
|
|
||||||
// section of your processor's datasheet for more information.
|
|
||||||
|
|
||||||
// Interrupt Configuration
|
|
||||||
#define ENC0_SIGNAL SIG_INTERRUPT0 // Interrupt signal name
|
|
||||||
#define ENC0_INT INT0 // matching INTx bit in GIMSK/EIMSK
|
|
||||||
#define ENC0_ICR MCUCR // matching Int. Config Register (MCUCR,EICRA/B)
|
|
||||||
#define ENC0_ISCX0 ISC00 // matching Interrupt Sense Config bit0
|
|
||||||
#define ENC0_ISCX1 ISC01 // matching Interrupt Sense Config bit1
|
|
||||||
// PhaseA Port/Pin Configuration
|
|
||||||
// *** PORTx, DDRx, PINx, and Pxn should all have the same letter for "x" ***
|
|
||||||
#define ENC0_PHASEA_PORT PORTD // PhaseA port register
|
|
||||||
#define ENC0_PHASEA_DDR DDRD // PhaseA port direction register
|
|
||||||
#define ENC0_PHASEA_PORTIN PIND // PhaseA port input register
|
|
||||||
#define ENC0_PHASEA_PIN PD2 // PhaseA port pin
|
|
||||||
// Phase B quadrature encoder output should connect to this direction line:
|
|
||||||
// *** PORTx, DDRx, PINx, and Pxn should all have the same letter for "x" ***
|
|
||||||
#define ENC0_PHASEB_PORT PORTC // PhaseB port register
|
|
||||||
#define ENC0_PHASEB_DDR DDRC // PhaseB port direction register
|
|
||||||
#define ENC0_PHASEB_PORTIN PINC // PhaseB port input register
|
|
||||||
#define ENC0_PHASEB_PIN PC0 // PhaseB port pin
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------- Encoder 1 connections --------------------
|
|
||||||
// Phase A quadrature encoder output should connect to this interrupt line:
|
|
||||||
// *** NOTE: the choice of interrupt pin and port must match the external
|
|
||||||
// interrupt you are using on your processor. Consult the External Interrupts
|
|
||||||
// section of your processor's datasheet for more information.
|
|
||||||
|
|
||||||
// Interrupt Configuration
|
|
||||||
#define ENC1_SIGNAL SIG_INTERRUPT1 // Interrupt signal name
|
|
||||||
#define ENC1_INT INT1 // matching INTx bit in GIMSK/EIMSK
|
|
||||||
#define ENC1_ICR MCUCR // matching Int. Config Register (MCUCR,EICRA/B)
|
|
||||||
#define ENC1_ISCX0 ISC10 // matching Interrupt Sense Config bit0
|
|
||||||
#define ENC1_ISCX1 ISC11 // matching Interrupt Sense Config bit1
|
|
||||||
// PhaseA Port/Pin Configuration
|
|
||||||
// *** PORTx, DDRx, PINx, and Pxn should all have the same letter for "x" ***
|
|
||||||
#define ENC1_PHASEA_PORT PORTD // PhaseA port register
|
|
||||||
#define ENC1_PHASEA_PORTIN PIND // PhaseA port input register
|
|
||||||
#define ENC1_PHASEA_DDR DDRD // PhaseA port direction register
|
|
||||||
#define ENC1_PHASEA_PIN PD3 // PhaseA port pin
|
|
||||||
// Phase B quadrature encoder output should connect to this direction line:
|
|
||||||
// *** PORTx, DDRx, PINx, and Pxn should all have the same letter for "x" ***
|
|
||||||
#define ENC1_PHASEB_PORT PORTC // PhaseB port register
|
|
||||||
#define ENC1_PHASEB_DDR DDRC // PhaseB port direction register
|
|
||||||
#define ENC1_PHASEB_PORTIN PINC // PhaseB port input register
|
|
||||||
#define ENC1_PHASEB_PIN PC1 // PhaseB port pin
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------- Encoder 2 connections --------------------
|
|
||||||
// Phase A quadrature encoder output should connect to this interrupt line:
|
|
||||||
// *** NOTE: the choice of interrupt pin and port must match the external
|
|
||||||
// interrupt you are using on your processor. Consult the External Interrupts
|
|
||||||
// section of your processor's datasheet for more information.
|
|
||||||
|
|
||||||
// Interrupt Configuration
|
|
||||||
//#define ENC2_SIGNAL SIG_INTERRUPT6 // Interrupt signal name
|
|
||||||
#define ENC2_INT INT6 // matching INTx bit in GIMSK/EIMSK
|
|
||||||
#define ENC2_ICR EICRB // matching Int. Config Register (MCUCR,EICRA/B)
|
|
||||||
#define ENC2_ISCX0 ISC60 // matching Interrupt Sense Config bit0
|
|
||||||
#define ENC2_ISCX1 ISC61 // matching Interrupt Sense Config bit1
|
|
||||||
// PhaseA Port/Pin Configuration
|
|
||||||
// *** PORTx, DDRx, PINx, and Pxn should all have the same letter for "x" ***
|
|
||||||
#define ENC2_PHASEA_PORT PORTE // PhaseA port register
|
|
||||||
#define ENC2_PHASEA_PORTIN PINE // PhaseA port input register
|
|
||||||
#define ENC2_PHASEA_DDR DDRE // PhaseA port direction register
|
|
||||||
#define ENC2_PHASEA_PIN PE6 // PhaseA port pin
|
|
||||||
// Phase B quadrature encoder output should connect to this direction line:
|
|
||||||
// *** PORTx, DDRx, PINx, and Pxn should all have the same letter for "x" ***
|
|
||||||
#define ENC2_PHASEB_PORT PORTC // PhaseB port register
|
|
||||||
#define ENC2_PHASEB_DDR DDRC // PhaseB port direction register
|
|
||||||
#define ENC2_PHASEB_PORTIN PINC // PhaseB port input register
|
|
||||||
#define ENC2_PHASEB_PIN PC2 // PhaseB port pin
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------- Encoder 3 connections --------------------
|
|
||||||
// Phase A quadrature encoder output should connect to this interrupt line:
|
|
||||||
// *** NOTE: the choice of interrupt pin and port must match the external
|
|
||||||
// interrupt you are using on your processor. Consult the External Interrupts
|
|
||||||
// section of your processor's datasheet for more information.
|
|
||||||
|
|
||||||
// Interrupt Configuration
|
|
||||||
//#define ENC3_SIGNAL SIG_INTERRUPT7 // Interrupt signal name
|
|
||||||
#define ENC3_INT INT7 // matching INTx bit in GIMSK/EIMSK
|
|
||||||
#define ENC3_ICR EICRB // matching Int. Config Register (MCUCR,EICRA/B)
|
|
||||||
#define ENC3_ISCX0 ISC70 // matching Interrupt Sense Config bit0
|
|
||||||
#define ENC3_ISCX1 ISC71 // matching Interrupt Sense Config bit1
|
|
||||||
// PhaseA Port/Pin Configuration
|
|
||||||
// *** PORTx, DDRx, PINx, and Pxn should all have the same letter for "x" ***
|
|
||||||
#define ENC3_PHASEA_PORT PORTE // PhaseA port register
|
|
||||||
#define ENC3_PHASEA_PORTIN PINE // PhaseA port input register
|
|
||||||
#define ENC3_PHASEA_DDR DDRE // PhaseA port direction register
|
|
||||||
#define ENC3_PHASEA_PIN PE7 // PhaseA port pin
|
|
||||||
// Phase B quadrature encoder output should connect to this direction line:
|
|
||||||
// *** PORTx, DDRx, PINx, and Pxn should all have the same letter for "x" ***
|
|
||||||
#define ENC3_PHASEB_PORT PORTC // PhaseB port register
|
|
||||||
#define ENC3_PHASEB_DDR DDRC // PhaseB port direction register
|
|
||||||
#define ENC3_PHASEB_PORTIN PINC // PhaseB port input register
|
|
||||||
#define ENC3_PHASEB_PIN PC3 // PhaseB port pin
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,40 +0,0 @@
|
|||||||
/*! \file fatconf.h \brief FAT16/32 file system driver configuration. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'fatconf.h'
|
|
||||||
// Title : FAT16/32 file system driver configuration
|
|
||||||
// Author : Pascal Stang
|
|
||||||
// Date : 4/19/2003
|
|
||||||
// Revised : 4/19/2003
|
|
||||||
// Version : 0.3
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef FATCONF_H
|
|
||||||
#define FATCONF_H
|
|
||||||
|
|
||||||
// debug on/off
|
|
||||||
#define DEBUG_FAT
|
|
||||||
|
|
||||||
#define SECTOR_BUFFER1_ADDR 0x0600+0x0600
|
|
||||||
#define SECTOR_BUFFER1_SIZE 0x0200
|
|
||||||
|
|
||||||
#define LONGNAME_BUFFER_ADDR 0x0200+0x0600
|
|
||||||
#define LONGNAME_BUFFER_SIZE 0x0100
|
|
||||||
|
|
||||||
#define DIRNAME_BUFFER_ADDR 0x0300+0x0600
|
|
||||||
#define DIRNAME_BUFFER_SIZE 0x0100
|
|
||||||
|
|
||||||
#define FAT_CACHE_ADDR 0x0400+0x0600
|
|
||||||
#define FAT_CACHE_SIZE 0x0200
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,40 +0,0 @@
|
|||||||
/*! \file global.h \brief AVRlib project global include. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'global.h'
|
|
||||||
// Title : AVRlib project global include
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2001-2002
|
|
||||||
// Created : 7/12/2001
|
|
||||||
// Revised : 9/30/2002
|
|
||||||
// Version : 1.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// Description : This include file is designed to contain items useful to all
|
|
||||||
// code files and projects.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef GLOBAL_H
|
|
||||||
#define GLOBAL_H
|
|
||||||
|
|
||||||
// global AVRLIB defines
|
|
||||||
#include "avrlibdefs.h"
|
|
||||||
// global AVRLIB types definitions
|
|
||||||
#include "avrlibtypes.h"
|
|
||||||
|
|
||||||
// project/system dependent defines
|
|
||||||
|
|
||||||
// CPU clock speed
|
|
||||||
//#define F_CPU 16000000 // 16MHz processor
|
|
||||||
//#define F_CPU 14745000 // 14.745MHz processor
|
|
||||||
//#define F_CPU 8000000 // 8MHz processor
|
|
||||||
#define F_CPU 7372800 // 7.37MHz processor
|
|
||||||
//#define F_CPU 4000000 // 4MHz processor
|
|
||||||
//#define F_CPU 3686400 // 3.69MHz processor
|
|
||||||
#define CYCLES_PER_US ((F_CPU+500000)/1000000) // cpu cycles per microsecond
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,28 +0,0 @@
|
|||||||
/*! \file i2cconf.h \brief I2C (TWI) interface configuration. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'i2cconf.h'
|
|
||||||
// Title : I2C (TWI) interface configuration
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002-2003
|
|
||||||
// Created : 2002.06.25
|
|
||||||
// Revised : 2003.03.02
|
|
||||||
// Version : 0.7
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef I2CCONF_H
|
|
||||||
#define I2CCONF_H
|
|
||||||
|
|
||||||
// define I2C data buffer sizes
|
|
||||||
// These buffers are used in interrupt-driven Master sending and receiving,
|
|
||||||
// and in slave sending and receiving. They must be large enough to store
|
|
||||||
// the largest I2C packet you expect to send and receive, respectively.
|
|
||||||
#define I2C_SEND_DATA_BUFFER_SIZE 0x20
|
|
||||||
#define I2C_RECEIVE_DATA_BUFFER_SIZE 0x20
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,32 +0,0 @@
|
|||||||
/*! \file i2cswconf.h \brief Software-driven I2C interface configuration. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'i2cswconf.h'
|
|
||||||
// Title : software-driven I2C interface using port pins
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2000-2002
|
|
||||||
// Created : 11/22/2000
|
|
||||||
// Revised : 5/2/2002
|
|
||||||
// Version : 1.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef I2CSWCONF_H
|
|
||||||
#define I2CSWCONF_H
|
|
||||||
|
|
||||||
// clock line port
|
|
||||||
#define SCLPORT PORTD // i2c clock port
|
|
||||||
#define SCLDDR DDRD // i2c clock port direction
|
|
||||||
// data line port
|
|
||||||
#define SDAPORT PORTD // i2c data port
|
|
||||||
#define SDADDR DDRD // i2c data port direction
|
|
||||||
#define SDAPIN PIND // i2c data port input
|
|
||||||
// pin assignments
|
|
||||||
#define SCL PD0 // i2c clock pin
|
|
||||||
#define SDA PD1 // i2c data pin
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,85 +0,0 @@
|
|||||||
/*! \file ks0108conf.h \brief Graphic LCD driver configuration. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'ks0108conf.h'
|
|
||||||
// Title : Graphic LCD driver for HD61202/KS0108 displays
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2001-2003
|
|
||||||
// Date : 10/19/2001
|
|
||||||
// Revised : 5/1/2003
|
|
||||||
// Version : 0.5
|
|
||||||
// Target MCU : Atmel AVR
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef KS0108CONF_H
|
|
||||||
#define KS0108CONF_H
|
|
||||||
|
|
||||||
// define LCD hardware interface
|
|
||||||
// -LCD_MEMORY_INTERFACE assumes that the registers of the LCD have been mapped
|
|
||||||
// into the external memory space of the AVR processor memory bus
|
|
||||||
// -LCD_PORT_INTERFACE is a direct-connection interface from port pins to LCD
|
|
||||||
// SELECT (UNCOMMENT) ONLY ONE!
|
|
||||||
|
|
||||||
// *** NOTE: memory interface is not yet fully supported, but it might work
|
|
||||||
|
|
||||||
//#define GLCD_MEMORY_INTERFACE
|
|
||||||
#define GLCD_PORT_INTERFACE
|
|
||||||
|
|
||||||
// GLCD_PORT_INTERFACE specifics
|
|
||||||
#ifdef GLCD_PORT_INTERFACE
|
|
||||||
// make sure these parameters are not already defined elsewhere
|
|
||||||
#ifndef GLCD_CTRL_PORT
|
|
||||||
#define GLCD_CTRL_PORT PORTB // PORT for LCD control signals
|
|
||||||
#define GLCD_CTRL_DDR DDRB // DDR register of LCD_CTRL_PORT
|
|
||||||
#define GLCD_CTRL_RS PB0 // pin for LCD Register Select
|
|
||||||
#define GLCD_CTRL_RW PB1 // pin for LCD Read/Write
|
|
||||||
#define GLCD_CTRL_E PB2 // pin for LCD Enable
|
|
||||||
#define GLCD_CTRL_CS0 PB3 // pin for LCD Controller 0 Chip Select
|
|
||||||
#define GLCD_CTRL_CS1 PB4 // pin for LCD Controller 1 Chip Select(*)
|
|
||||||
#define GLCD_CTRL_CS2 PB6 // pin for LCD Controller 2 Chip Select(*)
|
|
||||||
#define GLCD_CTRL_CS3 PB7 // pin for LCD Controller 3 Chip Select(*)
|
|
||||||
#define GLCD_CTRL_RESET PB5 // pin for LCD Reset
|
|
||||||
// (*) NOTE: additonal controller chip selects are optional and
|
|
||||||
// will be automatically used per each step in 64 pixels of display size
|
|
||||||
// Example: Display with 128 hozizontal pixels uses 2 controllers
|
|
||||||
#endif
|
|
||||||
#ifndef GLCD_DATA_PORT
|
|
||||||
#define GLCD_DATA_PORT PORTC // PORT for LCD data signals
|
|
||||||
#define GLCD_DATA_DDR DDRC // DDR register of LCD_DATA_PORT
|
|
||||||
#define GLCD_DATA_PIN PINC // PIN register of LCD_DATA_PORT
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// GLCD_MEMORY_INTERFACE specifics
|
|
||||||
#ifdef GLCD_MEMORY_INTERFACE
|
|
||||||
// make sure these parameters are not already defined elsewhere
|
|
||||||
#ifndef GLCD_CONTROLLER0_CTRL_ADDR
|
|
||||||
// absolute address of LCD Controller #0 CTRL and DATA registers
|
|
||||||
#define GLCD_CONTROLLER0_CTRL_ADDR 0x1000
|
|
||||||
#define GLCD_CONTROLLER0_DATA_ADDR 0x1001
|
|
||||||
// offset of other controllers with respect to controller0
|
|
||||||
#define GLCD_CONTROLLER_ADDR_OFFSET 0x0002
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// LCD geometry defines (change these definitions to adapt code/settings)
|
|
||||||
#define GLCD_XPIXELS 128 // pixel width of entire display
|
|
||||||
#define GLCD_YPIXELS 64 // pixel height of entire display
|
|
||||||
#define GLCD_CONTROLLER_XPIXELS 64 // pixel width of one display controller
|
|
||||||
|
|
||||||
// Set text size of display
|
|
||||||
// These definitions are not currently used and will probably move to glcd.h
|
|
||||||
#define GLCD_TEXT_LINES 8 // visible lines
|
|
||||||
#define GLCD_TEXT_LINE_LENGTH 22 // internal line length
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,97 +0,0 @@
|
|||||||
/*! \file lcdconf.h \brief Character LCD driver configuration. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'lcdconf.h'
|
|
||||||
// Title : Character LCD driver for HD44780/SED1278 displays
|
|
||||||
// (usable in mem-mapped, or I/O mode)
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2000-2002
|
|
||||||
// Created : 11/22/2000
|
|
||||||
// Revised : 4/30/2002
|
|
||||||
// Version : 1.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef LCDCONF_H
|
|
||||||
#define LCDCONF_H
|
|
||||||
|
|
||||||
// Define type of interface used to access the LCD
|
|
||||||
// LCD_MEMORY_INTERFACE:
|
|
||||||
// To use this mode you must supply the necessary hardware to connect the
|
|
||||||
// LCD to the CPU's memory bus. The CONTROL and DATA registers of the LCD
|
|
||||||
// (HD44780 chip) must appear in the CPU's memory map. This mode is faster
|
|
||||||
// than the port interface but requires a little extra hardware to make it
|
|
||||||
// work. It is especially useful when your CPU is already configured to
|
|
||||||
// use an external memory bus for other purposes (like accessing memory).
|
|
||||||
//
|
|
||||||
// LCD_PORT_INTERFACE:
|
|
||||||
// This mode allows you to connect the control and data lines of the LCD
|
|
||||||
// directly to the I/O port pins (no interfacing hardware is needed),
|
|
||||||
// but it generally runs slower than the LCD_MEMORY_INTERFACE.
|
|
||||||
// Depending on your needs, when using the LCD_PORT_INTERFACE, the LCD may
|
|
||||||
// be accessed in 8-bit or 4-bit mode. In 8-bit mode, one whole I/O port
|
|
||||||
// (pins 0-7) is required for the LCD data lines, but transfers are faster.
|
|
||||||
// In 4-bit mode, only I/O port pins 4-7 are needed for data lines, but LCD
|
|
||||||
// access is slower. In either mode, three additional port pins are
|
|
||||||
// required for the LCD interface control lines (RS, R/W, and E).
|
|
||||||
|
|
||||||
// Enable one of the following interfaces to your LCD
|
|
||||||
//#define LCD_MEMORY_INTERFACE
|
|
||||||
#define LCD_PORT_INTERFACE
|
|
||||||
|
|
||||||
// Enter the parameters for your chosen interface'
|
|
||||||
// if you chose the LCD_PORT_INTERFACE:
|
|
||||||
#ifdef LCD_PORT_INTERFACE
|
|
||||||
#ifndef LCD_CTRL_PORT
|
|
||||||
// port and pins you will use for control lines
|
|
||||||
#define LCD_CTRL_PORT PORTC
|
|
||||||
#define LCD_CTRL_DDR DDRC
|
|
||||||
#define LCD_CTRL_RS 2
|
|
||||||
#define LCD_CTRL_RW 3
|
|
||||||
#define LCD_CTRL_E 4
|
|
||||||
#endif
|
|
||||||
#ifndef LCD_DATA_POUT
|
|
||||||
// port you will use for data lines
|
|
||||||
#define LCD_DATA_POUT PORTA
|
|
||||||
#define LCD_DATA_PIN PINA
|
|
||||||
#define LCD_DATA_DDR DDRA
|
|
||||||
// access mode you will use (default is 8bit unless 4bit is selected)
|
|
||||||
//#define LCD_DATA_4BIT
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// if you chose the LCD_MEMORY_INTERFACE:
|
|
||||||
#ifdef LCD_MEMORY_INTERFACE
|
|
||||||
#ifndef LCD_CTRL_ADDR
|
|
||||||
// CPU memory address of the LCD control register
|
|
||||||
#define LCD_CTRL_ADDR 0x1000
|
|
||||||
#endif
|
|
||||||
#ifndef LCD_DATA_ADDR
|
|
||||||
// CPU memory address of the LCD data register
|
|
||||||
#define LCD_DATA_ADDR 0x1001
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// LCD display geometry
|
|
||||||
// change these definitions to adapt settings
|
|
||||||
#define LCD_LINES 4 // visible lines
|
|
||||||
#define LCD_LINE_LENGTH 20 // line length (in characters)
|
|
||||||
// cursor position to DDRAM mapping
|
|
||||||
#define LCD_LINE0_DDRAMADDR 0x00
|
|
||||||
#define LCD_LINE1_DDRAMADDR 0x40
|
|
||||||
#define LCD_LINE2_DDRAMADDR 0x14
|
|
||||||
#define LCD_LINE3_DDRAMADDR 0x54
|
|
||||||
|
|
||||||
// LCD delay
|
|
||||||
// This delay affects how quickly accesses are made to the LCD controller.
|
|
||||||
// If your clock frequency is low, you can reduce the number of NOPs in the
|
|
||||||
// delay. If your clock frequency is high, you may need to add NOPs.
|
|
||||||
// The number of NOPs should be between at least 1 and up to 20.
|
|
||||||
#define LCD_DELAY asm volatile ("nop\n nop\n nop\n nop\n");
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,33 +0,0 @@
|
|||||||
/*! \file mmcconf.h \brief MultiMedia and SD Flash Card Interface Configuration. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'mmc.h'
|
|
||||||
// Title : MultiMedia and SD Flash Card Interface Configuration
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2004
|
|
||||||
// Created : 2004.09.22
|
|
||||||
// Revised : 2004.09.22
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef MMCCONF_H
|
|
||||||
#define MMCCONF_H
|
|
||||||
|
|
||||||
// define to enable debugging print statements
|
|
||||||
//#define MMC_DEBUG
|
|
||||||
|
|
||||||
// MMC card chip select pin defines
|
|
||||||
#define MMC_CS_PORT PORTB
|
|
||||||
#define MMC_CS_DDR DDRB
|
|
||||||
#define MMC_CS_PIN 0
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,24 +0,0 @@
|
|||||||
|
|
||||||
--- AVRlib "conf" files ---
|
|
||||||
|
|
||||||
AVRlib contains many function/code libraries which depend upon particular aspects of the
|
|
||||||
user's hardware. The most basic of these is the processor clock rate. The clock rate defines
|
|
||||||
dozens of aspects of processor operation from code delays to UART baud rates.
|
|
||||||
|
|
||||||
To allow AVRlib to work easily with hardware that may vary from project to project, all
|
|
||||||
user-configurable parameters of AVRlib are contained in the template configuration files in
|
|
||||||
this directory. NOTE that these files are only templates and should be copied, as needed,
|
|
||||||
to an individual project's code directory and edited to suit that project's hardware.
|
|
||||||
|
|
||||||
|
|
||||||
global.h is the only configuration include file that is common to the entire AVRlib code base.
|
|
||||||
To use AVRlib libraries, you must copy global.h to your project's code directory and modify
|
|
||||||
the options inside global.h to match your hardware.) Each project should have its own global.h.
|
|
||||||
|
|
||||||
Other *conf.h files should be copied to your project's code directory as needed. For example,
|
|
||||||
if you intend to use the lcd.c library, you will need to copy lcdconf.h and modify it to match
|
|
||||||
the I/O and LCD configuration of your hardware.
|
|
||||||
|
|
||||||
** If you fail to copy the configuration files needed for the AVRlib libraries you use,
|
|
||||||
the problem will usually exhibit itself as a compile-time error.
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
|||||||
/*! \file servoconf.h \brief Interrupt-driven RC Servo configuration. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'servoconf.h'
|
|
||||||
// Title : Interrupt-driven RC Servo function library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002
|
|
||||||
// Created : 07/31/2002
|
|
||||||
// Revised : 09/30/2002
|
|
||||||
// Version : 1.0
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: you need the latest version (3.2+) of the AVR-GCC compiler to use this
|
|
||||||
// function library. Download it from http://www.avrfreaks.net/AVRGCC
|
|
||||||
//
|
|
||||||
// Description : This code allows you to drive up to 8 RC servos from any
|
|
||||||
// combination of ports and pins on the AVR processor. Using interrupts,
|
|
||||||
// this code continuously sends control signals to the servo to maintain
|
|
||||||
// position even while your code is doing other work.
|
|
||||||
//
|
|
||||||
// The servoInit and servoOff effectively turn on and turn off servo
|
|
||||||
// control. When you run ServoInit, it automatically assigns each
|
|
||||||
// "channel" of servo control to be output on the SERVO_DEFAULT_PORT.
|
|
||||||
// One "channel" of servo control can control one servo and must be
|
|
||||||
// assigned single I/O pin for output.
|
|
||||||
//
|
|
||||||
// If you're using all eight channels (SERVO_NUM_CHANNELS = 8), then
|
|
||||||
// then by default the code will use SERVO_DEFAULT_PORT pins 0-7.
|
|
||||||
// If you're only using four channels, then pins 0-3 will be used by
|
|
||||||
// default.
|
|
||||||
//
|
|
||||||
// The command servoSetChannelIO(channel, port, pin) allows you to
|
|
||||||
// reassign the output of any channel to any port and I/O pin you
|
|
||||||
// choose. For exampe, if you have an RC servo connected to PORTC, pin 6,
|
|
||||||
// and you wish to use channel 2 to control it, use:
|
|
||||||
//
|
|
||||||
// servoSerChannelIO( 2, _SFR_IO_ADDR(PORTC), 6)
|
|
||||||
//
|
|
||||||
// (NOTE: you must include the "_SRF_IO_ADDR()" part around your port)
|
|
||||||
//
|
|
||||||
// The servoSetPostion and servoGetPosition commands allow you to command
|
|
||||||
// a given servo to your desired position. The position you request must
|
|
||||||
// lie between the SERVO_MIN and SERVO_MAX limit you defined.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef SERVOCONF_H
|
|
||||||
#define SERVOCONF_H
|
|
||||||
|
|
||||||
// set number of servo channels (1 to 8)
|
|
||||||
// This is the number of servos you would like to drive
|
|
||||||
// Each "Channel" can control one servo and by default will
|
|
||||||
// map directly to the port pin of the same number on the
|
|
||||||
// SERVO_DEFAULT_PORT. You can change this default port/pin
|
|
||||||
// assignment for a given channel to any port/pin you like.
|
|
||||||
// See the "servoSetChannelIO" function.
|
|
||||||
#define SERVO_NUM_CHANNELS 4
|
|
||||||
// set default SERVO output port
|
|
||||||
// This is the AVR port which you have connected to your servos
|
|
||||||
// See top of file for how servo "channels" map to port pins
|
|
||||||
#define SERVO_DEFAULT_PORT PORTB
|
|
||||||
// set servo characteristics (min and max raw position)
|
|
||||||
// You must find these by testing using your brand/type of servos.
|
|
||||||
// The min/max settings will change proportional to F_CPU, the CPU
|
|
||||||
// clock frequency.
|
|
||||||
// The numbers below good for parallax servos at an F_CPU of ~8MHz.
|
|
||||||
//#define SERVO_MAX 71
|
|
||||||
//#define SERVO_MIN 17
|
|
||||||
// The numbers below good for parallax servos at an F_CPU of ~14.745MHz.
|
|
||||||
#define SERVO_MAX 138
|
|
||||||
#define SERVO_MIN 34
|
|
||||||
|
|
||||||
// set servo scaled range
|
|
||||||
// This sets the scaled position range of the servo. Allowed scaled
|
|
||||||
// positions are 0 -> SERVO_POSITION_MAX, and correspond to raw
|
|
||||||
// positions of SERVO_MIN -> SERVO_MAX.
|
|
||||||
#define SERVO_POSITION_MAX 255
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,42 +0,0 @@
|
|||||||
/*! \file sramswconf.h \brief Software-driven SRAM memory bus access configuration. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'sramswconf.h'
|
|
||||||
// Title : Software-driven SRAM memory bus access functions
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002
|
|
||||||
// Created : 11/11/2002
|
|
||||||
// Revised : 11/13/2002
|
|
||||||
// Version : 1.0
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef SRAMSWCONF_H
|
|
||||||
#define SRAMSWCONF_H
|
|
||||||
|
|
||||||
// defines
|
|
||||||
|
|
||||||
// data bus (DATA[0:7]) and low address (ADDR[0:7]) port
|
|
||||||
#define SRAM_ADL PORTA
|
|
||||||
#define SRAM_ADL_DDR DDRA
|
|
||||||
#define SRAM_ADL_IN PINA
|
|
||||||
// high address port (ADDR[8:15])
|
|
||||||
#define SRAM_AH PORTC
|
|
||||||
#define SRAM_AH_DDR DDRC
|
|
||||||
// page address port (PAGE[0:3])
|
|
||||||
#define SRAM_PAGE PORTB
|
|
||||||
#define SRAM_PAGE_DDR DDRB
|
|
||||||
#define SRAM_PAGE_MASK 0x0F
|
|
||||||
// control port
|
|
||||||
#define SRAM_CTRL PORTD
|
|
||||||
#define SRAM_CTRL_DDR DDRD
|
|
||||||
// control lines
|
|
||||||
#define SRAM_ALE PD5
|
|
||||||
#define SRAM_WR PD6
|
|
||||||
#define SRAM_RD PD7
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,34 +0,0 @@
|
|||||||
/*! \file sta013conf.h \brief STA013 MP3 player driver configuration. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'sta013.h'
|
|
||||||
// Title : STMicroelectronics STA013 MP3 player driver
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2000-2002
|
|
||||||
// Created : 10/22/2000
|
|
||||||
// Revised : 12/04/2000
|
|
||||||
// Version : 0.3
|
|
||||||
// Target MCU : ATmega103 (should work for Atmel AVR Series)
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef STA013CONF_H
|
|
||||||
#define STA013CONF_H
|
|
||||||
|
|
||||||
// STA013 Configuration
|
|
||||||
|
|
||||||
// STA013 demand line
|
|
||||||
#define STA013_DEMAND_PORT PORTE // port to which DEMAND line is connected
|
|
||||||
#define STA013_DEMAND_PORTIN PINE // input port to which DEMAND line is connected
|
|
||||||
#define STA013_DEMAND_PIN PE4 // port pin to which DEMAND line is connected
|
|
||||||
#define STA013_DEMAND_INTR SIG_INTERRUPT4 // interrupt to which DEMAND line is connected
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,28 +0,0 @@
|
|||||||
/*! \file stxetxconf.h \brief STX/ETX Packet Protocol Implementation Configuration. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'stxetx.h'
|
|
||||||
// Title : STX/ETX Packet Protocol Implementation Configuration
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002-2003
|
|
||||||
// Created : 10/9/2002
|
|
||||||
// Revised : 02/10/2003
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : any
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef STXETXCONF_H
|
|
||||||
#define STXETXCONF_H
|
|
||||||
|
|
||||||
// STX/ETX Configuration Options
|
|
||||||
|
|
||||||
// This determines the size of the Packet Receive Buffer
|
|
||||||
// where whole verified packets are copied after being received
|
|
||||||
#define STXETX_MAXRXPACKETSIZE 20 // length of packet buffer
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,68 +0,0 @@
|
|||||||
/*! \file uartsw2conf.h \brief Interrupt-driven Software UART Driver Configuration. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'uartsw2conf.h'
|
|
||||||
// Title : Interrupt-driven Software UART Driver Configuration
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002-2003
|
|
||||||
// Created : 7/20/2002
|
|
||||||
// Revised : 4/27/2004
|
|
||||||
// Version : 0.6
|
|
||||||
// Target MCU : Atmel AVR Series (intended for the ATmega16 and ATmega32)
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// Description :
|
|
||||||
// This uart library emulates the operation of a UART (serial port) using
|
|
||||||
// the AVR's hardware timers, I/O pins, and some software.
|
|
||||||
//
|
|
||||||
// Specifically, this code uses:
|
|
||||||
// -Timer 2 Output Capture for transmit timing
|
|
||||||
// -Timer 0 Output Capture for receive timing
|
|
||||||
// -External Interrupt 2 for receive triggering
|
|
||||||
//
|
|
||||||
// The above resources cannot be used for other purposes while this software
|
|
||||||
// UART is enabled. The overflow interrupts from Timer0 and Timer2 can still
|
|
||||||
// be used for other timing, but the prescalers for these timers must not be
|
|
||||||
// changed.
|
|
||||||
//
|
|
||||||
// Serial output from this UART can be routed to any I/O pin. Serial input
|
|
||||||
// for this UART must come from the External Interrupt 2 (INT2) I/O pin.
|
|
||||||
// These options should be configured by editing your local copy of
|
|
||||||
// "uartsw2conf.h".
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef UARTSW2CONF_H
|
|
||||||
#define UARTSW2CONF_H
|
|
||||||
|
|
||||||
// constants/macros/typdefs
|
|
||||||
|
|
||||||
#define UARTSW_RX_BUFFER_SIZE 0x20 ///< UART receive buffer size in bytes
|
|
||||||
|
|
||||||
#define UARTSW_INVERT ///< define to invert polarity of RX/TX signals
|
|
||||||
// when non-inverted, the serial line is appropriate for passing though
|
|
||||||
// an RS232 driver like the MAX232. When inverted, the serial line can
|
|
||||||
// directly drive/receive RS232 signals to/from a DB9 connector. Be sure
|
|
||||||
// to use a current-limiting resistor and perhaps a diode-clamp circuit when
|
|
||||||
// connecting incoming RS232 signals to a microprocessor I/O pin.
|
|
||||||
|
|
||||||
// if non-inverted, the serial line idles high (logic 1) between bytes
|
|
||||||
// if inverted, the serial line idles low (logic 0) between bytes
|
|
||||||
|
|
||||||
|
|
||||||
// UART transmit pin defines
|
|
||||||
#define UARTSW_TX_PORT PORTB ///< UART Transmit Port
|
|
||||||
#define UARTSW_TX_DDR DDRB ///< UART Transmit DDR
|
|
||||||
#define UARTSW_TX_PIN PB3 ///< UART Transmit Pin
|
|
||||||
|
|
||||||
// UART receive pin defines
|
|
||||||
// This pin must correspond to the
|
|
||||||
// External Interrupt 2 (INT2) pin for your processor
|
|
||||||
#define UARTSW_RX_PORT PORTB ///< UART Receive Port
|
|
||||||
#define UARTSW_RX_DDR DDRB ///< UART Receive DDR
|
|
||||||
#define UARTSW_RX_PORTIN PINB ///< UART Receive Port Input
|
|
||||||
#define UARTSW_RX_PIN PB2 ///< UART Receive Pin
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,67 +0,0 @@
|
|||||||
/*! \file uartswconf.h \brief Interrupt-driven Software UART Driver Configuration. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'uartswconf.h'
|
|
||||||
// Title : Interrupt-driven Software UART Driver Configuration
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002-2004
|
|
||||||
// Created : 7/20/2002
|
|
||||||
// Revised : 4/27/2004
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series (intended for the ATmega16 and ATmega32)
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// Description :
|
|
||||||
// This uart library emulates the operation of a UART (serial port) using
|
|
||||||
// the AVR's hardware timers, I/O pins, and some software.
|
|
||||||
//
|
|
||||||
// Specifically, this code uses:
|
|
||||||
// -Timer 1 Output Compare A for transmit timing
|
|
||||||
// -Timer 1 Output Compare B for receive timing
|
|
||||||
// -Timer 1 Input Capture for receive triggering
|
|
||||||
//
|
|
||||||
// The above resources cannot be used for other purposes while this software
|
|
||||||
// UART is enabled. The overflow interrupt from Timer1 can still be used for
|
|
||||||
// other timing, but the prescaler for Timer1 must not be changed.
|
|
||||||
//
|
|
||||||
// Serial output from this UART can be routed to any I/O pin. Serial input
|
|
||||||
// for this UART must come from the Timer1 Input Capture (IC1) I/O pin.
|
|
||||||
// These options should be configured by editing your local copy of
|
|
||||||
// "uartswconf.h".
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef UARTSWCONF_H
|
|
||||||
#define UARTSWCONF_H
|
|
||||||
|
|
||||||
// constants/macros/typdefs
|
|
||||||
|
|
||||||
#define UARTSW_RX_BUFFER_SIZE 0x20 ///< UART receive buffer size in bytes
|
|
||||||
|
|
||||||
#define UARTSW_INVERT ///< define to invert polarity of RX/TX signals
|
|
||||||
// when non-inverted, the serial line is appropriate for passing though
|
|
||||||
// an RS232 driver like the MAX232. When inverted, the serial line can
|
|
||||||
// directly drive/receive RS232 signals to/from a DB9 connector. Be sure
|
|
||||||
// to use a current-limiting resistor and perhaps a diode-clamp circuit when
|
|
||||||
// connecting incoming RS232 signals to a microprocessor I/O pin.
|
|
||||||
|
|
||||||
// if non-inverted, the serial line idles high (logic 1) between bytes
|
|
||||||
// if inverted, the serial line idles low (logic 0) between bytes
|
|
||||||
|
|
||||||
|
|
||||||
// UART transmit pin defines
|
|
||||||
#define UARTSW_TX_PORT PORTD ///< UART Transmit Port
|
|
||||||
#define UARTSW_TX_DDR DDRD ///< UART Transmit DDR
|
|
||||||
#define UARTSW_TX_PIN PD5 ///< UART Transmit Pin
|
|
||||||
|
|
||||||
// UART receive pin defines
|
|
||||||
// This pin must correspond to the
|
|
||||||
// Timer1 Input Capture (ICP or IC1) pin for your processor
|
|
||||||
#define UARTSW_RX_PORT PORTD ///< UART Receive Port
|
|
||||||
#define UARTSW_RX_DDR DDRD ///< UART Receive DDR
|
|
||||||
#define UARTSW_RX_PORTIN PIND ///< UART Receive Port Input
|
|
||||||
#define UARTSW_RX_PIN PD6 ///< UART Receive Pin
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,99 +0,0 @@
|
|||||||
/*! \file debug.c \brief Debugging function library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'debug.c'
|
|
||||||
// Title : Helpful debugging functions
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2003
|
|
||||||
// Created : 2003-03-13
|
|
||||||
// Revised : 2003-03-13
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// Description : This file contains a set of functions which may be useful
|
|
||||||
// for general debugging.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/signal.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include "debug.h"
|
|
||||||
|
|
||||||
#include "rprintf.h" // include printf support
|
|
||||||
|
|
||||||
// global variables
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
// Print a part of memory as a formatted hex table with ascii translation
|
|
||||||
void debugPrintHexTable(u16 length, u08 *buffer)
|
|
||||||
{
|
|
||||||
u08 i;
|
|
||||||
u16 j;
|
|
||||||
u08 *buf;
|
|
||||||
u08 s;
|
|
||||||
|
|
||||||
buf = buffer;
|
|
||||||
|
|
||||||
// print the low order address indicies and ASCII header
|
|
||||||
rprintfProgStrM(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 0123456789ABCDEF\r\n");
|
|
||||||
rprintfProgStrM(" ----------------------------------------------- ---- ASCII -----\r\n");
|
|
||||||
|
|
||||||
// print the data
|
|
||||||
for(j=0; j<((length+15)>>4); j++)
|
|
||||||
{
|
|
||||||
// print the high order address index for this line
|
|
||||||
rprintfu16(j<<4);
|
|
||||||
rprintfChar(' ');
|
|
||||||
|
|
||||||
// print the hex data
|
|
||||||
for(i=0; i<0x10; i++)
|
|
||||||
{
|
|
||||||
// be nice and print only up to the exact end of the data
|
|
||||||
if( ((j<<4)+i) < length)
|
|
||||||
{
|
|
||||||
// print hex byte
|
|
||||||
rprintfu08(buf[(j<<4)+i]);
|
|
||||||
rprintfChar(' ');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// we're past the end of the data's length
|
|
||||||
// print spaces
|
|
||||||
rprintfProgStrM(" ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// leave some space
|
|
||||||
rprintfChar(' ');
|
|
||||||
|
|
||||||
// print the ascii data
|
|
||||||
for(i=0; i<0x10; i++)
|
|
||||||
{
|
|
||||||
// be nice and print only up to the exact end of the data
|
|
||||||
if( ((j<<4)+i) < length)
|
|
||||||
{
|
|
||||||
// get the character
|
|
||||||
s = buf[(j<<4)+i];
|
|
||||||
// make sure character is printable
|
|
||||||
if(s >= 0x20)
|
|
||||||
rprintfChar(s);
|
|
||||||
else
|
|
||||||
rprintfChar('.');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// we're past the end of the data's length
|
|
||||||
// print a space
|
|
||||||
rprintfChar(' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rprintfCRLF();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
/*! \file debug.h \brief Debugging function library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'debug.h'
|
|
||||||
// Title : Helpful debugging functions
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2003
|
|
||||||
// Created : 2003-03-13
|
|
||||||
// Revised : 2003-03-13
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// Description : This file contains a set of functions which may be useful
|
|
||||||
// for general debugging.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef DEBUG_H
|
|
||||||
#define DEBUG_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
// defines
|
|
||||||
|
|
||||||
// function prototypes
|
|
||||||
|
|
||||||
//! Print a part of memory as a formatted hex table with ascii translation
|
|
||||||
void debugPrintHexTable(u16 length, u08 *buffer);
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,147 +0,0 @@
|
|||||||
/*! \file ds1631.c \brief Dallas DS1631 Temperature Sensor Driver Library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'ds1631.c'
|
|
||||||
// Title : Dallas DS1631 Temperature Sensor Driver Library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2004
|
|
||||||
// Created : 2004.02.10
|
|
||||||
// Revised : 2004.02.19
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/signal.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include "timer.h"
|
|
||||||
#include "i2c.h"
|
|
||||||
#include "ds1631.h"
|
|
||||||
|
|
||||||
// global variables
|
|
||||||
|
|
||||||
// Functions
|
|
||||||
u08 ds1631Init(u08 i2cAddr)
|
|
||||||
{
|
|
||||||
u08 chip_ok;
|
|
||||||
// issue a reset
|
|
||||||
if(ds1631Reset(i2cAddr) == I2C_OK)
|
|
||||||
chip_ok = TRUE;
|
|
||||||
else
|
|
||||||
chip_ok = FALSE;
|
|
||||||
// set a default configuration
|
|
||||||
// (1-shot mode, T_OUT active high, and 12-bit conversion)
|
|
||||||
ds1631SetConfig(i2cAddr,
|
|
||||||
DS1631_CONFIG_1SHOT | DS1631_CONFIG_POL |
|
|
||||||
DS1631_CONFIG_R0 | DS1631_CONFIG_R1);
|
|
||||||
return chip_ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 ds1631Reset(u08 i2cAddr)
|
|
||||||
{
|
|
||||||
u08 buffer[1];
|
|
||||||
// return the DS1631 to power-on reset defaults
|
|
||||||
buffer[0] = DS1631_CMD_SWPOR;
|
|
||||||
return i2cMasterSendNI(i2cAddr, 1, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ds1631SetConfig(u08 i2cAddr, u08 config)
|
|
||||||
{
|
|
||||||
u08 buffer[2];
|
|
||||||
// write the DS1631 configuration byte
|
|
||||||
buffer[0] = DS1631_CMD_ACCESSCONFIG;
|
|
||||||
buffer[1] = config;
|
|
||||||
i2cMasterSendNI(i2cAddr, 2, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 ds1631GetConfig(u08 i2cAddr)
|
|
||||||
{
|
|
||||||
u08 buffer[1];
|
|
||||||
// write the DS1631 configuration byte
|
|
||||||
buffer[0] = DS1631_CMD_ACCESSCONFIG;
|
|
||||||
i2cMasterSendNI(i2cAddr, 2, buffer);
|
|
||||||
i2cMasterReceiveNI(i2cAddr, 2, buffer);
|
|
||||||
return buffer[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
void ds1631StartConvert(u08 i2cAddr)
|
|
||||||
{
|
|
||||||
u08 buffer[1];
|
|
||||||
// send the DS1631 Start Convert command
|
|
||||||
buffer[0] = DS1631_CMD_STARTCONV;
|
|
||||||
i2cMasterSendNI(i2cAddr, 1, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ds1631StopConvert(u08 i2cAddr)
|
|
||||||
{
|
|
||||||
u08 buffer[1];
|
|
||||||
// send the DS1631 Stop Convert command
|
|
||||||
buffer[0] = DS1631_CMD_STOPCONV;
|
|
||||||
i2cMasterSendNI(i2cAddr, 1, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
s16 ds1631ReadTemp(u08 i2cAddr)
|
|
||||||
{
|
|
||||||
// read the Temperature register and return the result
|
|
||||||
return ds1631ReadTempReg(i2cAddr, DS1631_CMD_READTEMP);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ds1631SetTH(u08 i2cAddr, s16 value)
|
|
||||||
{
|
|
||||||
// write the TH register
|
|
||||||
ds1631WriteTempReg(i2cAddr, DS1631_CMD_ACCESSTH, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ds1631SetTL(u08 i2cAddr, s16 value)
|
|
||||||
{
|
|
||||||
// write the TL register
|
|
||||||
ds1631WriteTempReg(i2cAddr, DS1631_CMD_ACCESSTL, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
s16 ds1631GetTH(u08 i2cAddr)
|
|
||||||
{
|
|
||||||
// read the TH register and return the result
|
|
||||||
return ds1631ReadTempReg(i2cAddr, DS1631_CMD_ACCESSTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
s16 ds1631GetTL(u08 i2cAddr)
|
|
||||||
{
|
|
||||||
// read the TL register and return the result
|
|
||||||
return ds1631ReadTempReg(i2cAddr, DS1631_CMD_ACCESSTL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
s16 ds1631ReadTempReg(u08 i2cAddr, u08 cmd)
|
|
||||||
{
|
|
||||||
u08 buffer[2];
|
|
||||||
s16 T;
|
|
||||||
|
|
||||||
// read the temperature value from the requested register
|
|
||||||
i2cMasterSendNI(i2cAddr, 1, &cmd);
|
|
||||||
i2cMasterReceiveNI(i2cAddr, 2, buffer);
|
|
||||||
// pack bytes
|
|
||||||
T = (s16)((buffer[0]<<8) | buffer[1]);
|
|
||||||
// return result
|
|
||||||
return T;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ds1631WriteTempReg(u08 i2cAddr, u08 cmd, s16 value)
|
|
||||||
{
|
|
||||||
u08 buffer[3];
|
|
||||||
|
|
||||||
// write the requested register with a temperature value
|
|
||||||
buffer[0] = cmd;
|
|
||||||
buffer[1] = value>>8;
|
|
||||||
buffer[2] = value;
|
|
||||||
i2cMasterSendNI(i2cAddr, 3, buffer);
|
|
||||||
}
|
|
@ -1,86 +0,0 @@
|
|||||||
/*! \file ds1631.h \brief Dallas DS1631 Temperature Sensor Driver Library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'ds1631.h'
|
|
||||||
// Title : Dallas DS1631 Temperature Sensor Driver Library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2004
|
|
||||||
// Created : 2004.02.10
|
|
||||||
// Revised : 2004.02.19
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef DS1631_H
|
|
||||||
#define DS1631_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
// constants/macros/typdefs
|
|
||||||
#define DS1631_I2C_ADDR 0x90 //< Base I2C address of DS1631 devices
|
|
||||||
|
|
||||||
#define DS1631_CMD_STARTCONV 0x51 //< DS1631 Start conversion command byte
|
|
||||||
#define DS1631_CMD_STOPCONV 0x22 //< DS1631 Stop conversion command byte
|
|
||||||
#define DS1631_CMD_READTEMP 0xAA //< DS1631 Read Temperature command byte
|
|
||||||
#define DS1631_CMD_ACCESSTH 0xA1 //< DS1631 TH read/write command byte
|
|
||||||
#define DS1631_CMD_ACCESSTL 0xA2 //< DS1631 TL read/write command byte
|
|
||||||
#define DS1631_CMD_ACCESSCONFIG 0xAC //< DS1631 Config read/write command byte
|
|
||||||
#define DS1631_CMD_SWPOR 0x54 //< DS1631 Software Reset command byte
|
|
||||||
|
|
||||||
#define DS1631_CONFIG_1SHOT 0x01
|
|
||||||
#define DS1631_CONFIG_POL 0x02
|
|
||||||
#define DS1631_CONFIG_R0 0x04
|
|
||||||
#define DS1631_CONFIG_R1 0x08
|
|
||||||
#define DS1631_CONFIG_NVB 0x10
|
|
||||||
#define DS1631_CONFIG_TLF 0x20
|
|
||||||
#define DS1631_CONFIG_THF 0x40
|
|
||||||
#define DS1631_CONFIG_DONE 0x80
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
//! Initialize the DS1631 chip
|
|
||||||
u08 ds1631Init(u08 i2cAddr);
|
|
||||||
|
|
||||||
//! Reset the DS1631 chip to its power-on defaults
|
|
||||||
u08 ds1631Reset(u08 i2cAddr);
|
|
||||||
|
|
||||||
//! Set the configuration byte of the DS1631
|
|
||||||
void ds1631SetConfig(u08 i2cAddr, u08 config);
|
|
||||||
|
|
||||||
//! Get the configuration byte of the DS1631
|
|
||||||
u08 ds1631GetConfig(u08 i2cAddr);
|
|
||||||
|
|
||||||
//! Start a temperature conversion
|
|
||||||
void ds1631StartConvert(u08 i2cAddr);
|
|
||||||
|
|
||||||
//! Stop a temperature conversion (or stop continuous conversion mode)
|
|
||||||
void ds1631StopConvert(u08 i2cAddr);
|
|
||||||
|
|
||||||
//! Read the result of a temperature conversion
|
|
||||||
s16 ds1631ReadTemp(u08 i2cAddr);
|
|
||||||
|
|
||||||
//! Set the Temp-High threshold
|
|
||||||
void ds1631SetTH(u08 i2cAddr, s16 value);
|
|
||||||
|
|
||||||
//! Set the Temp-Low threshold
|
|
||||||
void ds1631SetTL(u08 i2cAddr, s16 value);
|
|
||||||
|
|
||||||
//! Get the Temp-High threshold
|
|
||||||
s16 ds1631GetTH(u08 i2cAddr);
|
|
||||||
|
|
||||||
//! Get the Temp-Low threshold
|
|
||||||
s16 ds1631GetTL(u08 i2cAddr);
|
|
||||||
|
|
||||||
void ds1631WriteTempReg(u08 i2cAddr, u08 cmd, s16 value);
|
|
||||||
s16 ds1631ReadTempReg(u08 i2cAddr, u08 cmd);
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,229 +0,0 @@
|
|||||||
/*! \file encoder.c \brief Quadrature Encoder reader/driver. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'encoder.c'
|
|
||||||
// Title : Quadrature Encoder reader/driver
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2003-2004
|
|
||||||
// Created : 2003.01.26
|
|
||||||
// Revised : 2004.06.25
|
|
||||||
// Version : 0.3
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/signal.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include "encoder.h"
|
|
||||||
|
|
||||||
// Program ROM constants
|
|
||||||
|
|
||||||
// Global variables
|
|
||||||
volatile EncoderStateType EncoderState[NUM_ENCODERS];
|
|
||||||
|
|
||||||
// Functions
|
|
||||||
|
|
||||||
// encoderInit() initializes hardware and encoder position readings
|
|
||||||
// Run this init routine once before using any other encoder functions.
|
|
||||||
void encoderInit(void)
|
|
||||||
{
|
|
||||||
u08 i;
|
|
||||||
|
|
||||||
// initialize/clear encoder data
|
|
||||||
for(i=0; i<NUM_ENCODERS; i++)
|
|
||||||
{
|
|
||||||
EncoderState[i].position = 0;
|
|
||||||
//EncoderState[i].velocity = 0; // NOT CURRENTLY USED
|
|
||||||
}
|
|
||||||
|
|
||||||
// configure direction and interrupt I/O pins:
|
|
||||||
// - for input
|
|
||||||
// - apply pullup resistors
|
|
||||||
// - any-edge interrupt triggering
|
|
||||||
// - enable interrupt
|
|
||||||
|
|
||||||
#ifdef ENC0_SIGNAL
|
|
||||||
// set interrupt pins to input and apply pullup resistor
|
|
||||||
cbi(ENC0_PHASEA_DDR, ENC0_PHASEA_PIN);
|
|
||||||
sbi(ENC0_PHASEA_PORT, ENC0_PHASEA_PIN);
|
|
||||||
// set encoder direction pin for input and apply pullup resistor
|
|
||||||
cbi(ENC0_PHASEB_DDR, ENC0_PHASEB_PIN);
|
|
||||||
sbi(ENC0_PHASEB_PORT, ENC0_PHASEB_PIN);
|
|
||||||
// configure interrupts for any-edge triggering
|
|
||||||
sbi(ENC0_ICR, ENC0_ISCX0);
|
|
||||||
cbi(ENC0_ICR, ENC0_ISCX1);
|
|
||||||
// enable interrupts
|
|
||||||
sbi(IMSK, ENC0_INT); // ISMK is auto-defined in encoder.h
|
|
||||||
#endif
|
|
||||||
#ifdef ENC1_SIGNAL
|
|
||||||
// set interrupt pins to input and apply pullup resistor
|
|
||||||
cbi(ENC1_PHASEA_DDR, ENC1_PHASEA_PIN);
|
|
||||||
sbi(ENC1_PHASEA_PORT, ENC1_PHASEA_PIN);
|
|
||||||
// set encoder direction pin for input and apply pullup resistor
|
|
||||||
cbi(ENC1_PHASEB_DDR, ENC1_PHASEB_PIN);
|
|
||||||
sbi(ENC1_PHASEB_PORT, ENC1_PHASEB_PIN);
|
|
||||||
// configure interrupts for any-edge triggering
|
|
||||||
sbi(ENC1_ICR, ENC1_ISCX0);
|
|
||||||
cbi(ENC1_ICR, ENC1_ISCX1);
|
|
||||||
// enable interrupts
|
|
||||||
sbi(IMSK, ENC1_INT); // ISMK is auto-defined in encoder.h
|
|
||||||
#endif
|
|
||||||
#ifdef ENC2_SIGNAL
|
|
||||||
// set interrupt pins to input and apply pullup resistor
|
|
||||||
cbi(ENC2_PHASEA_DDR, ENC2_PHASEA_PIN);
|
|
||||||
sbi(ENC2_PHASEA_PORT, ENC2_PHASEA_PIN);
|
|
||||||
// set encoder direction pin for input and apply pullup resistor
|
|
||||||
cbi(ENC2_PHASEB_DDR, ENC2_PHASEB_PIN);
|
|
||||||
sbi(ENC2_PHASEB_PORT, ENC2_PHASEB_PIN);
|
|
||||||
// configure interrupts for any-edge triggering
|
|
||||||
sbi(ENC2_ICR, ENC2_ISCX0);
|
|
||||||
cbi(ENC2_ICR, ENC2_ISCX1);
|
|
||||||
// enable interrupts
|
|
||||||
sbi(IMSK, ENC2_INT); // ISMK is auto-defined in encoder.h
|
|
||||||
#endif
|
|
||||||
#ifdef ENC3_SIGNAL
|
|
||||||
// set interrupt pins to input and apply pullup resistor
|
|
||||||
cbi(ENC3_PHASEA_DDR, ENC3_PHASEA_PIN);
|
|
||||||
sbi(ENC3_PHASEA_PORT, ENC3_PHASEA_PIN);
|
|
||||||
// set encoder direction pin for input and apply pullup resistor
|
|
||||||
cbi(ENC3_PHASEB_DDR, ENC3_PHASEB_PIN);
|
|
||||||
sbi(ENC3_PHASEB_PORT, ENC3_PHASEB_PIN);
|
|
||||||
// configure interrupts for any-edge triggering
|
|
||||||
sbi(ENC3_ICR, ENC3_ISCX0);
|
|
||||||
cbi(ENC3_ICR, ENC3_ISCX1);
|
|
||||||
// enable interrupts
|
|
||||||
sbi(IMSK, ENC3_INT); // ISMK is auto-defined in encoder.h
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// enable global interrupts
|
|
||||||
sei();
|
|
||||||
}
|
|
||||||
|
|
||||||
// encoderOff() disables hardware and stops encoder position updates
|
|
||||||
void encoderOff(void)
|
|
||||||
{
|
|
||||||
// disable encoder interrupts
|
|
||||||
#ifdef ENC0_SIGNAL
|
|
||||||
// disable interrupts
|
|
||||||
sbi(IMSK, INT0); // ISMK is auto-defined in encoder.h
|
|
||||||
#endif
|
|
||||||
#ifdef ENC1_SIGNAL
|
|
||||||
// disable interrupts
|
|
||||||
sbi(IMSK, INT1); // ISMK is auto-defined in encoder.h
|
|
||||||
#endif
|
|
||||||
#ifdef ENC2_SIGNAL
|
|
||||||
// disable interrupts
|
|
||||||
sbi(IMSK, INT2); // ISMK is auto-defined in encoder.h
|
|
||||||
#endif
|
|
||||||
#ifdef ENC3_SIGNAL
|
|
||||||
// disable interrupts
|
|
||||||
sbi(IMSK, INT3); // ISMK is auto-defined in encoder.h
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// encoderGetPosition() reads the current position of the encoder
|
|
||||||
s32 encoderGetPosition(u08 encoderNum)
|
|
||||||
{
|
|
||||||
// sanity check
|
|
||||||
if(encoderNum < NUM_ENCODERS)
|
|
||||||
return EncoderState[encoderNum].position;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// encoderSetPosition() sets the current position of the encoder
|
|
||||||
void encoderSetPosition(u08 encoderNum, s32 position)
|
|
||||||
{
|
|
||||||
// sanity check
|
|
||||||
if(encoderNum < NUM_ENCODERS)
|
|
||||||
EncoderState[encoderNum].position = position;
|
|
||||||
// else do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENC0_SIGNAL
|
|
||||||
//! Encoder 0 interrupt handler
|
|
||||||
SIGNAL(ENC0_SIGNAL)
|
|
||||||
{
|
|
||||||
// encoder has generated a pulse
|
|
||||||
// check the relative phase of the input channels
|
|
||||||
// and update position accordingly
|
|
||||||
if( ((inb(ENC0_PHASEA_PORTIN) & (1<<ENC0_PHASEA_PIN)) == 0) ^
|
|
||||||
((inb(ENC0_PHASEB_PORTIN) & (1<<ENC0_PHASEB_PIN)) == 0) )
|
|
||||||
{
|
|
||||||
EncoderState[0].position++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EncoderState[0].position--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENC1_SIGNAL
|
|
||||||
//! Encoder 1 interrupt handler
|
|
||||||
SIGNAL(ENC1_SIGNAL)
|
|
||||||
{
|
|
||||||
// encoder has generated a pulse
|
|
||||||
// check the relative phase of the input channels
|
|
||||||
// and update position accordingly
|
|
||||||
if( ((inb(ENC1_PHASEA_PORTIN) & (1<<ENC1_PHASEA_PIN)) == 0) ^
|
|
||||||
((inb(ENC1_PHASEB_PORTIN) & (1<<ENC1_PHASEB_PIN)) == 0) )
|
|
||||||
{
|
|
||||||
EncoderState[1].position++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EncoderState[1].position--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENC2_SIGNAL
|
|
||||||
//! Encoder 2 interrupt handler
|
|
||||||
SIGNAL(ENC2_SIGNAL)
|
|
||||||
{
|
|
||||||
// encoder has generated a pulse
|
|
||||||
// check the relative phase of the input channels
|
|
||||||
// and update position accordingly
|
|
||||||
if( ((inb(ENC2_PHASEA_PORTIN) & (1<<ENC2_PHASEA_PIN)) == 0) ^
|
|
||||||
((inb(ENC2_PHASEB_PORTIN) & (1<<ENC2_PHASEB_PIN)) == 0) )
|
|
||||||
{
|
|
||||||
EncoderState[2].position++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EncoderState[2].position--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENC3_SIGNAL
|
|
||||||
//! Encoder 3 interrupt handler
|
|
||||||
SIGNAL(ENC3_SIGNAL)
|
|
||||||
{
|
|
||||||
// encoder has generated a pulse
|
|
||||||
// check the relative phase of the input channels
|
|
||||||
// and update position accordingly
|
|
||||||
if( ((inb(ENC3_PHASEA_PORTIN) & (1<<ENC3_PHASEA_PIN)) == 0) ^
|
|
||||||
((inb(ENC3_PHASEB_PORTIN) & (1<<ENC3_PHASEB_PIN)) == 0) )
|
|
||||||
{
|
|
||||||
EncoderState[3].position++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EncoderState[3].position--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,119 +0,0 @@
|
|||||||
/*! \file encoder.h \brief Quadrature Encoder reader/driver. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'encoder.h'
|
|
||||||
// Title : Quadrature Encoder reader/driver
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2003-2004
|
|
||||||
// Created : 2003.01.26
|
|
||||||
// Revised : 2004.06.25
|
|
||||||
// Version : 0.3
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// Description : This library allows easy interfacing of quadrature encoders
|
|
||||||
// to the Atmel AVR-series processors.
|
|
||||||
//
|
|
||||||
// Quadrature encoders have two digital outputs usually called PhaseA and
|
|
||||||
// PhaseB. When the encoder rotates, PhaseA and PhaseB produce square wave
|
|
||||||
// pulses where each pulse represents a fraction of a turn of the encoder
|
|
||||||
// shaft. Encoders are rated for a certain number of pulses (or counts) per
|
|
||||||
// complete revolution of the shaft. Common counts/revolution specs are 50,
|
|
||||||
// 100,128,200,250,256,500,etc. By counting the number of pulses output on
|
|
||||||
// one of the phases starting from time0, you can calculate the total
|
|
||||||
// rotational distance the encoder has traveled.
|
|
||||||
//
|
|
||||||
// Often, however, we want current position not just total distance traveled.
|
|
||||||
// For this it is necessary to know not only how far the encoder has traveled,
|
|
||||||
// but also which direction it was going at each step of the way. To do this
|
|
||||||
// we need to use both outputs (or phases) of the quadrature encoder.
|
|
||||||
//
|
|
||||||
// The pulses from PhaseA and PhaseB on quadrature encoders are always aligned
|
|
||||||
// 90 degrees out-of-phase (otherwise said: 1/4 wavelength apart). This
|
|
||||||
// special phase relationship lets us extract both the distance and direction
|
|
||||||
// the encoder has rotated from the outputs.
|
|
||||||
//
|
|
||||||
// To do this, consider Phase A to be the distance counter. On each rising
|
|
||||||
// edge of PhaseA we will count 1 "tic" of distance, but we need to know the
|
|
||||||
// direction. Look at the quadrature waveform plot below. Notice that when
|
|
||||||
// we travel forward in time (left->right), PhaseB is always low (logic 0) at
|
|
||||||
// the rising edge of PhaseA. When we travel backwards in time (right->left),
|
|
||||||
// PhaseB is always high (logic 1) at the rising edge of PhaseA. Note that
|
|
||||||
// traveling forward or backwards in time is the same thing as rotating
|
|
||||||
// forwards or bardwards. Thus, if PhaseA is our counter, PhaseB indicates
|
|
||||||
// direction.
|
|
||||||
//
|
|
||||||
// Here is an example waveform from a quadrature encoder:
|
|
||||||
/*
|
|
||||||
// /---\ /---\ /---\ /---\ /---\ /---\
|
|
||||||
// Phase A: | | | | | | | | | | | |
|
|
||||||
// ---/ \---/ \---/ \---/ \---/ \---/ \-
|
|
||||||
// -\ /---\ /---\ /---\ /---\ /---\ /---
|
|
||||||
// Phase B: | | | | | | | | | | | |
|
|
||||||
// \---/ \---/ \---/ \---/ \---/ \---/
|
|
||||||
// Time: <--------------------------------------------------->
|
|
||||||
// Rotate FWD: >---------------------------------------------->
|
|
||||||
// Rotate REV: <----------------------------------------------<
|
|
||||||
*/
|
|
||||||
// To keep track of the encoder position in software, we connect PhaseA to an
|
|
||||||
// external processor interrupt line, and PhaseB to any I/O pin. We set up
|
|
||||||
// the external interrupt to trigger whenever PhaseA produces a rising edge.
|
|
||||||
// When a rising edge is detected, our interrupt handler function is executed.
|
|
||||||
// Inside the handler function, we quickly check the PhaseB line to see if it
|
|
||||||
// is high or low. If it is high, we increment the encoder's position
|
|
||||||
// counter, otherwise we decrement it. The encoder position counter can be
|
|
||||||
// read at any time to find out the current position.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef ENCODER_H
|
|
||||||
#define ENCODER_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
// include encoder configuration file
|
|
||||||
#include "encoderconf.h"
|
|
||||||
|
|
||||||
// constants/macros/typdefs
|
|
||||||
|
|
||||||
// defines for processor compatibility
|
|
||||||
// chose proper Interrupt Mask (IMSK)
|
|
||||||
#ifdef EIMSK
|
|
||||||
#define IMSK EIMSK // for processors mega128, mega64
|
|
||||||
#else
|
|
||||||
#define IMSK GIMSK // for other processors 90s8515, mega163, etc
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//! Encoder state structure
|
|
||||||
// stores the position and other information from each encoder
|
|
||||||
typedef struct struct_EncoderState
|
|
||||||
{
|
|
||||||
s32 position; ///< position
|
|
||||||
// s32 velocity; ///< velocity
|
|
||||||
} EncoderStateType;
|
|
||||||
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
//! encoderInit() initializes hardware and encoder position readings
|
|
||||||
// Run this init routine once before using any other encoder function.
|
|
||||||
void encoderInit(void);
|
|
||||||
|
|
||||||
//! encoderOff() disables hardware and stops encoder position updates
|
|
||||||
void encoderOff(void);
|
|
||||||
|
|
||||||
//! encoderGetPosition() reads the current position of the encoder
|
|
||||||
s32 encoderGetPosition(u08 encoderNum);
|
|
||||||
|
|
||||||
//! encoderSetPosition() sets the current position of the encoder
|
|
||||||
void encoderSetPosition(u08 encoderNum, s32 position);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,182 +0,0 @@
|
|||||||
/*! \file extint.c \brief External-Interrupt function library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'extint.c'
|
|
||||||
// Title : External-Interrupt function library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002-2004
|
|
||||||
// Created : 5/10/2002
|
|
||||||
// Revised : 11/16/2004
|
|
||||||
// Version : 1.0
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// Notes: This library provides convenient standardized configuration and
|
|
||||||
// access to external interrupts. The library is designed to make
|
|
||||||
// it possible to write code that uses external interrupts without
|
|
||||||
// digging into the processor datasheets to find register names and
|
|
||||||
// bit-defines. The library also strives to allow code which uses
|
|
||||||
// external interrupts to more easily cross-compile between different
|
|
||||||
// microcontrollers.
|
|
||||||
//
|
|
||||||
// NOTE: Using this library has certain advantages, but also adds
|
|
||||||
// overhead and latency to interrupt servicing. If the smallest
|
|
||||||
// code size or fastest possible latency is needed, do NOT use this
|
|
||||||
// library; link your interrupts directly.
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/signal.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include "extint.h"
|
|
||||||
|
|
||||||
// Global variables
|
|
||||||
typedef void (*voidFuncPtr)(void);
|
|
||||||
volatile static voidFuncPtr ExtIntFunc[EXTINT_NUM_INTERRUPTS];
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
//! initializes extint library
|
|
||||||
void extintInit(void)
|
|
||||||
{
|
|
||||||
u08 intNum;
|
|
||||||
// detach all user functions from interrupts
|
|
||||||
for(intNum=0; intNum<EXTINT_NUM_INTERRUPTS; intNum++)
|
|
||||||
extintDetach(intNum);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Configure external interrupt trigger
|
|
||||||
// NOTE: this function is not complete!!!
|
|
||||||
void extintConfigure(u08 interruptNum, u08 configuration)
|
|
||||||
{
|
|
||||||
if(interruptNum == EXTINT0)
|
|
||||||
{
|
|
||||||
MCUCR &= ~((1<<ISC01) | (1<<ISC00));
|
|
||||||
MCUCR |= configuration;
|
|
||||||
}
|
|
||||||
#ifdef SIG_INTERRUPT1
|
|
||||||
else if(interruptNum == EXTINT1)
|
|
||||||
{
|
|
||||||
MCUCR &= ~((1<<ISC11) | (1<<ISC10));
|
|
||||||
MCUCR |= configuration<<2;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef SIG_INTERRUPT2
|
|
||||||
else if(interruptNum == EXTINT2)
|
|
||||||
{
|
|
||||||
if(configuration == EXTINT_EDGE_RISING)
|
|
||||||
sbi(MCUCSR, ISC2);
|
|
||||||
else
|
|
||||||
cbi(MCUCSR, ISC2);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// need to handle a lot more cases
|
|
||||||
// and differences between processors.
|
|
||||||
// looking for clean way to do it...
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Attach a user function to an external interrupt
|
|
||||||
void extintAttach(u08 interruptNum, void (*userHandler)(void) )
|
|
||||||
{
|
|
||||||
// make sure the interrupt number is within bounds
|
|
||||||
if(interruptNum < EXTINT_NUM_INTERRUPTS)
|
|
||||||
{
|
|
||||||
// set the interrupt function to run
|
|
||||||
// the supplied user's function
|
|
||||||
ExtIntFunc[interruptNum] = userHandler;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Detach a user function from an external interrupt
|
|
||||||
void extintDetach(u08 interruptNum)
|
|
||||||
{
|
|
||||||
// make sure the interrupt number is within bounds
|
|
||||||
if(interruptNum < EXTINT_NUM_INTERRUPTS)
|
|
||||||
{
|
|
||||||
// set the interrupt function to run
|
|
||||||
// the supplied user's function
|
|
||||||
ExtIntFunc[interruptNum] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Interrupt handler for INT0
|
|
||||||
EXTINT_INTERRUPT_HANDLER(SIG_INTERRUPT0)
|
|
||||||
{
|
|
||||||
// if a user function is defined, execute it
|
|
||||||
if(ExtIntFunc[EXTINT0])
|
|
||||||
ExtIntFunc[EXTINT0]();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SIG_INTERRUPT1
|
|
||||||
//! Interrupt handler for INT1
|
|
||||||
EXTINT_INTERRUPT_HANDLER(SIG_INTERRUPT1)
|
|
||||||
{
|
|
||||||
// if a user function is defined, execute it
|
|
||||||
if(ExtIntFunc[EXTINT1])
|
|
||||||
ExtIntFunc[EXTINT1]();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SIG_INTERRUPT2
|
|
||||||
//! Interrupt handler for INT2
|
|
||||||
EXTINT_INTERRUPT_HANDLER(SIG_INTERRUPT2)
|
|
||||||
{
|
|
||||||
// if a user function is defined, execute it
|
|
||||||
if(ExtIntFunc[EXTINT2])
|
|
||||||
ExtIntFunc[EXTINT2]();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SIG_INTERRUPT3
|
|
||||||
//! Interrupt handler for INT3
|
|
||||||
EXTINT_INTERRUPT_HANDLER(SIG_INTERRUPT3)
|
|
||||||
{
|
|
||||||
// if a user function is defined, execute it
|
|
||||||
if(ExtIntFunc[EXTINT3])
|
|
||||||
ExtIntFunc[EXTINT3]();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SIG_INTERRUPT4
|
|
||||||
//! Interrupt handler for INT4
|
|
||||||
EXTINT_INTERRUPT_HANDLER(SIG_INTERRUPT4)
|
|
||||||
{
|
|
||||||
// if a user function is defined, execute it
|
|
||||||
if(ExtIntFunc[EXTINT4])
|
|
||||||
ExtIntFunc[EXTINT4]();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SIG_INTERRUPT5
|
|
||||||
//! Interrupt handler for INT5
|
|
||||||
EXTINT_INTERRUPT_HANDLER(SIG_INTERRUPT5)
|
|
||||||
{
|
|
||||||
// if a user function is defined, execute it
|
|
||||||
if(ExtIntFunc[EXTINT5])
|
|
||||||
ExtIntFunc[EXTINT5]();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SIG_INTERRUPT6
|
|
||||||
//! Interrupt handler for INT6
|
|
||||||
EXTINT_INTERRUPT_HANDLER(SIG_INTERRUPT6)
|
|
||||||
{
|
|
||||||
// if a user function is defined, execute it
|
|
||||||
if(ExtIntFunc[EXTINT6])
|
|
||||||
ExtIntFunc[EXTINT6]();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SIG_INTERRUPT7
|
|
||||||
//! Interrupt handler for INT7
|
|
||||||
EXTINT_INTERRUPT_HANDLER(SIG_INTERRUPT7)
|
|
||||||
{
|
|
||||||
// if a user function is defined, execute it
|
|
||||||
if(ExtIntFunc[EXTINT7])
|
|
||||||
ExtIntFunc[EXTINT7]();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
|||||||
/*! \file extint.h \brief External-Interrupt function library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'extint.h'
|
|
||||||
// Title : External-Interrupt function library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002-2004
|
|
||||||
// Created : 5/10/2002
|
|
||||||
// Revised : 11/16/2004
|
|
||||||
// Version : 1.0
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// Notes: This library provides convenient standardized configuration and
|
|
||||||
// access to external interrupts. The library is designed to make
|
|
||||||
// it possible to write code that uses external interrupts without
|
|
||||||
// digging into the processor datasheets to find register names and
|
|
||||||
// bit-defines. The library also strives to allow code which uses
|
|
||||||
// external interrupts to more easily cross-compile between different
|
|
||||||
// microcontrollers.
|
|
||||||
//
|
|
||||||
// NOTE: Using this library has certain advantages, but also adds
|
|
||||||
// overhead and latency to interrupt servicing. If the smallest
|
|
||||||
// code size or fastest possible latency is needed, do NOT use this
|
|
||||||
// library; link your interrupts directly.
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef EXTINT_H
|
|
||||||
#define EXTINT_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
// constants/macros/typdefs
|
|
||||||
|
|
||||||
// interrupt macros for attaching user functions to external interrupts
|
|
||||||
// use these with extintAttach( intNum, function )
|
|
||||||
#define EXTINT0 0x00 ///< External Interrupt 0
|
|
||||||
#define EXTINT1 0x01 ///< External Interrupt 1
|
|
||||||
#define EXTINT2 0x02 ///< External Interrupt 2
|
|
||||||
#define EXTINT3 0x03 ///< External Interrupt 3
|
|
||||||
#define EXTINT4 0x04 ///< External Interrupt 4
|
|
||||||
#define EXTINT5 0x05 ///< External Interrupt 5
|
|
||||||
#define EXTINT6 0x06 ///< External Interrupt 6
|
|
||||||
#define EXTINT7 0x07 ///< External Interrupt 7
|
|
||||||
|
|
||||||
#define EXTINT_LEVEL_LOW 0x00 ///< Trigger on low level
|
|
||||||
#define EXTINT_EDGE_ANY 0x01 ///< Trigger on any edge
|
|
||||||
#define EXTINT_EDGE_FALLING 0x02 ///< Trigger on falling edge
|
|
||||||
#define EXTINT_EDGE_RISING 0x03 ///< Trigger on rising edge
|
|
||||||
|
|
||||||
// type of interrupt handler to use
|
|
||||||
// *do not change unless you know what you're doing
|
|
||||||
// Value may be SIGNAL or INTERRUPT
|
|
||||||
#ifndef EXTINT_INTERRUPT_HANDLER
|
|
||||||
#define EXTINT_INTERRUPT_HANDLER SIGNAL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// processor-adaptive defines
|
|
||||||
// mainstream AVR processors generally have 1,2,3, or 8 external interrupts
|
|
||||||
// (if someone has a better idea of how to manage this, let me know)
|
|
||||||
#ifdef SIG_INTERRUPT7
|
|
||||||
#define EXTINT_NUM_INTERRUPTS 8
|
|
||||||
#else
|
|
||||||
#ifdef SIG_INTERRUPT2
|
|
||||||
#define EXTINT_NUM_INTERRUPTS 3
|
|
||||||
#else
|
|
||||||
#ifdef SIG_INTERRUPT1
|
|
||||||
#define EXTINT_NUM_INTERRUPTS 2
|
|
||||||
#else
|
|
||||||
#define EXTINT_NUM_INTERRUPTS 1
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
//! initializes extint library
|
|
||||||
void extintInit(void);
|
|
||||||
|
|
||||||
//! Configure external interrupt trigger
|
|
||||||
void extintConfigure(u08 interruptNum, u08 configuration);
|
|
||||||
|
|
||||||
// extintAttach and extintDetach commands
|
|
||||||
// These functions allow the attachment (or detachment) of any user
|
|
||||||
// function to an external interrupt. "Attaching" one of your own
|
|
||||||
// functions to an interrupt means that it will be called whenever
|
|
||||||
// that interrupt is triggered. Example usage:
|
|
||||||
//
|
|
||||||
// extintAttach(EXTINT0, myInterruptHandler);
|
|
||||||
// extintDetach(EXTINT0);
|
|
||||||
//
|
|
||||||
// extintAttach causes the myInterruptHandler() to be attached, and therefore
|
|
||||||
// execute, whenever the corresponding interrupt occurs. extintDetach removes
|
|
||||||
// the association and executes no user function when the interrupt occurs.
|
|
||||||
// myInterruptFunction must be defined with no return value and no arguments:
|
|
||||||
//
|
|
||||||
// void myInterruptHandler(void) { ... }
|
|
||||||
|
|
||||||
//! Attach a user function to an external interrupt
|
|
||||||
void extintAttach(u08 interruptNum, void (*userHandler)(void) );
|
|
||||||
//! Detach a user function from an external interrupt
|
|
||||||
void extintDetach(u08 interruptNum);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,364 +0,0 @@
|
|||||||
/*! \file fat.c \brief FAT16/32 file system driver. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'fat.c'
|
|
||||||
// Title : FAT16/32 file system driver
|
|
||||||
// Author : Pascal Stang
|
|
||||||
// Date : 11/07/2000
|
|
||||||
// Revised : 12/12/2000
|
|
||||||
// Version : 0.3
|
|
||||||
// Target MCU : ATmega103 (should work for Atmel AVR Series)
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is based in part on work done by Jesper Hansen for his
|
|
||||||
// YAMPP MP3 player project.
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "ata.h"
|
|
||||||
#include "rprintf.h"
|
|
||||||
|
|
||||||
#include "fat.h"
|
|
||||||
#include "fatconf.h"
|
|
||||||
|
|
||||||
// globals
|
|
||||||
unsigned char *SectorBuffer = (unsigned char *) SECTOR_BUFFER1_ADDR;
|
|
||||||
unsigned char *LongNameBuffer = (unsigned char *) LONGNAME_BUFFER_ADDR;
|
|
||||||
unsigned char *DirNameBuffer = (unsigned char *) DIRNAME_BUFFER_ADDR;
|
|
||||||
|
|
||||||
struct partrecord PartInfo;
|
|
||||||
unsigned char Fat32Enabled;
|
|
||||||
unsigned long FirstDataSector;
|
|
||||||
unsigned int BytesPerSector;
|
|
||||||
unsigned int SectorsPerCluster;
|
|
||||||
unsigned long FirstFATSector;
|
|
||||||
unsigned long FirstDirSector;
|
|
||||||
unsigned long FileSize;
|
|
||||||
unsigned long FatInCache = 0;
|
|
||||||
|
|
||||||
/*************************************************************************/
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
unsigned long fatClustToSect(unsigned long clust)
|
|
||||||
{
|
|
||||||
return ((clust-2) * SectorsPerCluster) + FirstDataSector;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int fatClusterSize(void)
|
|
||||||
{
|
|
||||||
// return the number of sectors in a disk cluster
|
|
||||||
return SectorsPerCluster;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char fatInit( unsigned char device)
|
|
||||||
{
|
|
||||||
//struct partrecord *pr;
|
|
||||||
struct bpb710 *bpb;
|
|
||||||
|
|
||||||
// read partition table
|
|
||||||
// TODO.... error checking
|
|
||||||
ataReadSectors(DRIVE0, 0, 1, SectorBuffer);
|
|
||||||
// map first partition record
|
|
||||||
// save partition information to global PartInfo
|
|
||||||
PartInfo = *((struct partrecord *) ((struct partsector *) SectorBuffer)->psPart);
|
|
||||||
// PartInfo = *pr;
|
|
||||||
|
|
||||||
// Read the Partition BootSector
|
|
||||||
// **first sector of partition in PartInfo.prStartLBA
|
|
||||||
ataReadSectors( DRIVE0, PartInfo.prStartLBA, 1, SectorBuffer );
|
|
||||||
bpb = (struct bpb710 *) ((struct bootsector710 *) SectorBuffer)->bsBPB;
|
|
||||||
|
|
||||||
// setup global disk constants
|
|
||||||
FirstDataSector = PartInfo.prStartLBA;
|
|
||||||
if(bpb->bpbFATsecs)
|
|
||||||
{
|
|
||||||
// bpbFATsecs is non-zero and is therefore valid
|
|
||||||
FirstDataSector += bpb->bpbResSectors + bpb->bpbFATs * bpb->bpbFATsecs;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// bpbFATsecs is zero, real value is in bpbBigFATsecs
|
|
||||||
FirstDataSector += bpb->bpbResSectors + bpb->bpbFATs * bpb->bpbBigFATsecs;
|
|
||||||
}
|
|
||||||
SectorsPerCluster = bpb->bpbSecPerClust;
|
|
||||||
BytesPerSector = bpb->bpbBytesPerSec;
|
|
||||||
FirstFATSector = bpb->bpbResSectors + PartInfo.prStartLBA;
|
|
||||||
|
|
||||||
switch (PartInfo.prPartType)
|
|
||||||
{
|
|
||||||
case PART_TYPE_DOSFAT16:
|
|
||||||
case PART_TYPE_FAT16:
|
|
||||||
case PART_TYPE_FAT16LBA:
|
|
||||||
// first directory cluster is 2 by default (clusters range 2->big)
|
|
||||||
FirstDirSector = CLUST_FIRST;
|
|
||||||
// push data sector pointer to end of root directory area
|
|
||||||
//FirstDataSector += (bpb->bpbRootDirEnts)/DIRENTRIES_PER_SECTOR;
|
|
||||||
Fat32Enabled = FALSE;
|
|
||||||
break;
|
|
||||||
case PART_TYPE_FAT32LBA:
|
|
||||||
case PART_TYPE_FAT32:
|
|
||||||
// bpbRootClust field exists in FAT32 bpb710, but not in lesser bpb's
|
|
||||||
FirstDirSector = bpb->bpbRootClust;
|
|
||||||
// push data sector pointer to end of root directory area
|
|
||||||
// need this? FirstDataSector += (bpb->bpbRootDirEnts)/DIRENTRIES_PER_SECTOR;
|
|
||||||
Fat32Enabled = TRUE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
rprintfProgStrM("Found: No Partition!\r\n");
|
|
||||||
//return 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG_FAT
|
|
||||||
switch (PartInfo.prPartType)
|
|
||||||
{
|
|
||||||
case PART_TYPE_DOSFAT16:
|
|
||||||
rprintfProgStrM("Found: DOSFAT 16\r\n");
|
|
||||||
break;
|
|
||||||
case PART_TYPE_FAT16:
|
|
||||||
rprintfProgStrM("Found: FAT16\r\n");
|
|
||||||
break;
|
|
||||||
case PART_TYPE_FAT16LBA:
|
|
||||||
rprintfProgStrM("Found: FAT16 LBA\r\n");
|
|
||||||
break;
|
|
||||||
case PART_TYPE_FAT32LBA:
|
|
||||||
rprintfProgStrM("Found: FAT32 LBA\r\n");
|
|
||||||
break;
|
|
||||||
case PART_TYPE_FAT32:
|
|
||||||
rprintfProgStrM("Found: FAT32\r\n");
|
|
||||||
//return 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
rprintfProgStrM("Found: No Partition!\r\n");
|
|
||||||
//return 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
rprintfProgStrM("First sector : "); rprintfu32(PartInfo.prStartLBA); rprintfCRLF();
|
|
||||||
rprintfProgStrM("Size : "); rprintfu32(PartInfo.prSize); rprintfCRLF();
|
|
||||||
rprintfProgStrM("bytes/sector : "); rprintfu16(bpb->bpbBytesPerSec); rprintfCRLF();
|
|
||||||
rprintfProgStrM("sectors/cluster : "); rprintfu08(bpb->bpbSecPerClust); rprintfCRLF();
|
|
||||||
rprintfProgStrM("reserved sectors: "); rprintfu16(bpb->bpbResSectors); rprintfCRLF();
|
|
||||||
rprintfProgStrM("FatSectors : "); rprintfu16(bpb->bpbFATsecs); rprintfCRLF();
|
|
||||||
rprintfProgStrM("BigFatSectors : "); rprintfu32(bpb->bpbBigFATsecs); rprintfCRLF();
|
|
||||||
rprintfProgStrM("Number of Fats : "); rprintfu08(bpb->bpbFATs); rprintfCRLF();
|
|
||||||
rprintfProgStrM("First Fat Sector: "); rprintfu32(FirstFATSector); rprintfCRLF();
|
|
||||||
rprintfProgStrM("First Data Sect : "); rprintfu32(FirstDataSector); rprintfCRLF();
|
|
||||||
rprintfProgStrM("First Dir Clust : "); rprintfu32(FirstDirSector); rprintfCRLF();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
unsigned int baseentry = 0;
|
|
||||||
unsigned int entrycount = 0;
|
|
||||||
|
|
||||||
|
|
||||||
unsigned long fatGetDirEntry(unsigned int entry, unsigned int count)
|
|
||||||
{
|
|
||||||
unsigned long sector;
|
|
||||||
struct direntry *de = 0; // avoid compiler warning by initializing
|
|
||||||
struct winentry *we;
|
|
||||||
unsigned int hasBuffer;
|
|
||||||
unsigned int b;
|
|
||||||
int i,index;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
if(count == 0)
|
|
||||||
{
|
|
||||||
entrycount = 0;
|
|
||||||
DirNameBuffer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read dir data
|
|
||||||
sector = fatClustToSect(FirstDirSector);
|
|
||||||
|
|
||||||
hasBuffer = 0;
|
|
||||||
|
|
||||||
index = 16; // crank it up
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if(index == 16) // time for next sector ?
|
|
||||||
{
|
|
||||||
ataReadSectors( DRIVE0, sector++, 1, SectorBuffer);
|
|
||||||
de = (struct direntry *) SectorBuffer;
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(*de->deName != 0xE5)
|
|
||||||
{
|
|
||||||
// if not a deleted entry
|
|
||||||
if(de->deAttributes == ATTR_LONG_FILENAME)
|
|
||||||
{
|
|
||||||
// we have a long name entry
|
|
||||||
we = (struct winentry *) de;
|
|
||||||
b = 13 *( (we->weCnt-1) & 0x0f); // index into string
|
|
||||||
p = &LongNameBuffer[b];
|
|
||||||
for (i=0;i<5;i++) *p++ = we->wePart1[i*2]; // copy first part
|
|
||||||
for (i=0;i<6;i++) *p++ = we->wePart2[i*2]; // second part
|
|
||||||
for (i=0;i<2;i++) *p++ = we->wePart3[i*2]; // and third part
|
|
||||||
if (we->weCnt & 0x40) *p = 0; // in case dirnamelength is multiple of 13
|
|
||||||
if ((we->weCnt & 0x0f) == 1) hasBuffer = 1; // mark that we have a long entry
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// we have a short name entry
|
|
||||||
// check if this is the end of a multi-part long name entry
|
|
||||||
if(hasBuffer)
|
|
||||||
{
|
|
||||||
// a long entry name has been collected
|
|
||||||
// is it a directory ?
|
|
||||||
if(de->deAttributes == ATTR_DIRECTORY)
|
|
||||||
{
|
|
||||||
unsigned long save = FirstDirSector;
|
|
||||||
unsigned int save2 = baseentry;
|
|
||||||
unsigned long rval;
|
|
||||||
|
|
||||||
strcpy(DirNameBuffer,LongNameBuffer);
|
|
||||||
strcat(DirNameBuffer,"/");
|
|
||||||
|
|
||||||
// rprintfStr(LongNameBuffer); rprintfProgStrM("/"); //EOL();
|
|
||||||
|
|
||||||
// call recursively
|
|
||||||
FirstDirSector = ((unsigned long)de->deHighClust << 16) + de->deStartCluster;
|
|
||||||
rval = fatGetDirEntry(entry,1);
|
|
||||||
FirstDirSector = save;
|
|
||||||
baseentry = save2;
|
|
||||||
if (rval)
|
|
||||||
return rval;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// reload original sector
|
|
||||||
ataReadSectors( DRIVE0, sector-1, 1, SectorBuffer);
|
|
||||||
entrycount--; // decrement entry counter
|
|
||||||
*DirNameBuffer = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // normal file entry
|
|
||||||
if(entrycount == entry)
|
|
||||||
break;
|
|
||||||
hasBuffer = 0; // clear buffer
|
|
||||||
entrycount++; // increment entry counter
|
|
||||||
}
|
|
||||||
// else ignore short_name_only entries
|
|
||||||
}
|
|
||||||
}
|
|
||||||
de++;
|
|
||||||
index++;
|
|
||||||
} while (*de->deName || index == 16); // 0 in de->deName[0] if no more entries
|
|
||||||
|
|
||||||
if (hasBuffer == 0) // end of entries
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
FileSize = de->deFileSize;
|
|
||||||
return (unsigned long) ((unsigned long)de->deHighClust << 16) + de->deStartCluster;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// return the size of the last directory entry
|
|
||||||
unsigned long fatGetFilesize(void)
|
|
||||||
{
|
|
||||||
return FileSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// return the long name of the last directory entry
|
|
||||||
char* fatGetFilename(void)
|
|
||||||
{
|
|
||||||
return LongNameBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// return the directory of the last directory entry
|
|
||||||
char* fatGetDirname(void)
|
|
||||||
{
|
|
||||||
return DirNameBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// load a clusterfull of data
|
|
||||||
void fatLoadCluster(unsigned long cluster, unsigned char *buffer)
|
|
||||||
{
|
|
||||||
register unsigned char i;
|
|
||||||
// read cluster
|
|
||||||
//while ( ataReadSectors( DRIVE0, clust2sect(cluster), SectorsPerCluster, buffer) != 0);
|
|
||||||
for(i=0; i<SectorsPerCluster; i++)
|
|
||||||
{
|
|
||||||
// ataReadSectors( DRIVE0, clust2sect(cluster)+i, 1, buffer+(i<<9) );
|
|
||||||
// temporary fix for wierd misaligned cluster problem
|
|
||||||
// (only when using FAT16?)
|
|
||||||
ataReadSectors( DRIVE0, fatClustToSect(cluster+8)+i, 1, buffer+(i<<9) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// find next cluster in the FAT chain
|
|
||||||
unsigned long fatNextCluster(unsigned long cluster)
|
|
||||||
{
|
|
||||||
unsigned long nextCluster;
|
|
||||||
unsigned long fatMask;
|
|
||||||
unsigned long fatOffset;
|
|
||||||
unsigned long sector;
|
|
||||||
unsigned int offset;
|
|
||||||
|
|
||||||
// get fat offset in bytes
|
|
||||||
if(Fat32Enabled)
|
|
||||||
{
|
|
||||||
// four FAT bytes (32 bits) for every cluster
|
|
||||||
fatOffset = cluster << 2;
|
|
||||||
// set the FAT bit mask
|
|
||||||
fatMask = FAT32_MASK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// two FAT bytes (16 bits) for every cluster
|
|
||||||
fatOffset = cluster << 1;
|
|
||||||
// set the FAT bit mask
|
|
||||||
fatMask = FAT16_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate the FAT sector that we're interested in
|
|
||||||
sector = FirstFATSector + (fatOffset / BytesPerSector);
|
|
||||||
// calculate offset of the our entry within that FAT sector
|
|
||||||
offset = fatOffset % BytesPerSector;
|
|
||||||
|
|
||||||
// if we don't already have this FAT chunk loaded, go get it
|
|
||||||
if (sector != FatInCache)
|
|
||||||
{
|
|
||||||
// read sector of FAT table
|
|
||||||
while (ataReadSectors( DRIVE0, sector, 1, (unsigned char*)FAT_CACHE_ADDR) != 0);
|
|
||||||
FatInCache = sector;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read the nextCluster value
|
|
||||||
nextCluster = (*((unsigned long*) &((char*)FAT_CACHE_ADDR)[offset])) & fatMask;
|
|
||||||
|
|
||||||
// check to see if we're at the end of the chain
|
|
||||||
if (nextCluster == (CLUST_EOFE & fatMask))
|
|
||||||
nextCluster = 0;
|
|
||||||
|
|
||||||
#ifdef DEBUG_FAT
|
|
||||||
rprintfProgStrM(">");
|
|
||||||
rprintfu32(nextCluster);
|
|
||||||
rprintfCRLF();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return nextCluster;
|
|
||||||
}
|
|
@ -1,375 +0,0 @@
|
|||||||
/*! \file fat.h \brief FAT16/32 file system driver. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'fat.h'
|
|
||||||
// Title : FAT16/32 file system driver
|
|
||||||
// Author : Pascal Stang
|
|
||||||
// Date : 11/07/2000
|
|
||||||
// Revised : 12/12/2000
|
|
||||||
// Version : 0.3
|
|
||||||
// Target MCU : ATmega103 (should work for Atmel AVR Series)
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef FAT_H
|
|
||||||
#define FAT_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
|
|
||||||
// Some useful cluster numbers
|
|
||||||
#define MSDOSFSROOT 0 // cluster 0 means the root dir
|
|
||||||
#define CLUST_FREE 0 // cluster 0 also means a free cluster
|
|
||||||
#define MSDOSFSFREE CLUST_FREE
|
|
||||||
#define CLUST_FIRST 2 // first legal cluster number
|
|
||||||
#define CLUST_RSRVD 0xfffffff6 // reserved cluster range
|
|
||||||
#define CLUST_BAD 0xfffffff7 // a cluster with a defect
|
|
||||||
#define CLUST_EOFS 0xfffffff8 // start of eof cluster range
|
|
||||||
#define CLUST_EOFE 0xffffffff // end of eof cluster range
|
|
||||||
|
|
||||||
#define FAT12_MASK 0x00000fff // mask for 12 bit cluster numbers
|
|
||||||
#define FAT16_MASK 0x0000ffff // mask for 16 bit cluster numbers
|
|
||||||
#define FAT32_MASK 0x0fffffff // mask for FAT32 cluster numbers
|
|
||||||
|
|
||||||
|
|
||||||
// Partition Type used in the partition record
|
|
||||||
#define PART_TYPE_UNKNOWN 0x00
|
|
||||||
#define PART_TYPE_FAT12 0x01
|
|
||||||
#define PART_TYPE_XENIX 0x02
|
|
||||||
#define PART_TYPE_DOSFAT16 0x04
|
|
||||||
#define PART_TYPE_EXTDOS 0x05
|
|
||||||
#define PART_TYPE_FAT16 0x06
|
|
||||||
#define PART_TYPE_NTFS 0x07
|
|
||||||
#define PART_TYPE_FAT32 0x0B
|
|
||||||
#define PART_TYPE_FAT32LBA 0x0C
|
|
||||||
#define PART_TYPE_FAT16LBA 0x0E
|
|
||||||
#define PART_TYPE_EXTDOSLBA 0x0F
|
|
||||||
#define PART_TYPE_ONTRACK 0x33
|
|
||||||
#define PART_TYPE_NOVELL 0x40
|
|
||||||
#define PART_TYPE_PCIX 0x4B
|
|
||||||
#define PART_TYPE_PHOENIXSAVE 0xA0
|
|
||||||
#define PART_TYPE_CPM 0xDB
|
|
||||||
#define PART_TYPE_DBFS 0xE0
|
|
||||||
#define PART_TYPE_BBT 0xFF
|
|
||||||
|
|
||||||
struct partrecord // length 16 bytes
|
|
||||||
{
|
|
||||||
BYTE prIsActive; // 0x80 indicates active partition
|
|
||||||
BYTE prStartHead; // starting head for partition
|
|
||||||
WORD prStartCylSect; // starting cylinder and sector
|
|
||||||
BYTE prPartType; // partition type (see above)
|
|
||||||
BYTE prEndHead; // ending head for this partition
|
|
||||||
WORD prEndCylSect; // ending cylinder and sector
|
|
||||||
DWORD prStartLBA; // first LBA sector for this partition
|
|
||||||
DWORD prSize; // size of this partition (bytes or sectors ?)
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct partsector
|
|
||||||
{
|
|
||||||
CHAR psPartCode[512-64-2]; // pad so struct is 512b
|
|
||||||
BYTE psPart[64]; // four partition records (64 bytes)
|
|
||||||
BYTE psBootSectSig0; // two signature bytes (2 bytes)
|
|
||||||
BYTE psBootSectSig1;
|
|
||||||
#define BOOTSIG0 0x55
|
|
||||||
#define BOOTSIG1 0xaa
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Format of a boot sector. This is the first sector on a DOS floppy disk
|
|
||||||
// or the first sector of a partition on a hard disk. But, it is not the
|
|
||||||
// first sector of a partitioned hard disk.
|
|
||||||
struct bootsector33 {
|
|
||||||
BYTE bsJump[3]; // jump inst E9xxxx or EBxx90
|
|
||||||
CHAR bsOemName[8]; // OEM name and version
|
|
||||||
CHAR bsBPB[19]; // BIOS parameter block
|
|
||||||
CHAR bsDriveNumber; // drive number (0x80)
|
|
||||||
CHAR bsBootCode[479]; // pad so struct is 512b
|
|
||||||
BYTE bsBootSectSig0; // boot sector signature byte 0x55
|
|
||||||
BYTE bsBootSectSig1; // boot sector signature byte 0xAA
|
|
||||||
#define BOOTSIG0 0x55
|
|
||||||
#define BOOTSIG1 0xaa
|
|
||||||
};
|
|
||||||
|
|
||||||
struct extboot {
|
|
||||||
CHAR exDriveNumber; // drive number (0x80)
|
|
||||||
CHAR exReserved1; // reserved
|
|
||||||
CHAR exBootSignature; // ext. boot signature (0x29)
|
|
||||||
#define EXBOOTSIG 0x29
|
|
||||||
CHAR exVolumeID[4]; // volume ID number
|
|
||||||
CHAR exVolumeLabel[11]; // volume label
|
|
||||||
CHAR exFileSysType[8]; // fs type (FAT12 or FAT16)
|
|
||||||
};
|
|
||||||
|
|
||||||
struct bootsector50 {
|
|
||||||
BYTE bsJump[3]; // jump inst E9xxxx or EBxx90
|
|
||||||
CHAR bsOemName[8]; // OEM name and version
|
|
||||||
CHAR bsBPB[25]; // BIOS parameter block
|
|
||||||
CHAR bsExt[26]; // Bootsector Extension
|
|
||||||
CHAR bsBootCode[448]; // pad so structure is 512b
|
|
||||||
BYTE bsBootSectSig0; // boot sector signature byte 0x55
|
|
||||||
BYTE bsBootSectSig1; // boot sector signature byte 0xAA
|
|
||||||
#define BOOTSIG0 0x55
|
|
||||||
#define BOOTSIG1 0xaa
|
|
||||||
};
|
|
||||||
|
|
||||||
struct bootsector710 {
|
|
||||||
BYTE bsJump[3]; // jump inst E9xxxx or EBxx90
|
|
||||||
CHAR bsOEMName[8]; // OEM name and version
|
|
||||||
CHAR bsBPB[53]; // BIOS parameter block
|
|
||||||
CHAR bsExt[26]; // Bootsector Extension
|
|
||||||
CHAR bsBootCode[418]; // pad so structure is 512b
|
|
||||||
BYTE bsBootSectSig2; // 2 & 3 are only defined for FAT32?
|
|
||||||
BYTE bsBootSectSig3;
|
|
||||||
BYTE bsBootSectSig0; // boot sector signature byte 0x55
|
|
||||||
BYTE bsBootSectSig1; // boot sector signature byte 0xAA
|
|
||||||
#define BOOTSIG0 0x55
|
|
||||||
#define BOOTSIG1 0xaa
|
|
||||||
#define BOOTSIG2 0
|
|
||||||
#define BOOTSIG3 0
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************/
|
|
||||||
/***************************************************************/
|
|
||||||
|
|
||||||
// BIOS Parameter Block (BPB) for DOS 3.3
|
|
||||||
struct bpb33 {
|
|
||||||
WORD bpbBytesPerSec; // bytes per sector
|
|
||||||
BYTE bpbSecPerClust; // sectors per cluster
|
|
||||||
WORD bpbResSectors; // number of reserved sectors
|
|
||||||
BYTE bpbFATs; // number of FATs
|
|
||||||
WORD bpbRootDirEnts; // number of root directory entries
|
|
||||||
WORD bpbSectors; // total number of sectors
|
|
||||||
BYTE bpbMedia; // media descriptor
|
|
||||||
WORD bpbFATsecs; // number of sectors per FAT
|
|
||||||
WORD bpbSecPerTrack; // sectors per track
|
|
||||||
WORD bpbHeads; // number of heads
|
|
||||||
WORD bpbHiddenSecs; // number of hidden sectors
|
|
||||||
};
|
|
||||||
|
|
||||||
// BPB for DOS 5.0
|
|
||||||
// The difference is bpbHiddenSecs is a short for DOS 3.3,
|
|
||||||
// and bpbHugeSectors is not present in the DOS 3.3 bpb.
|
|
||||||
struct bpb50 {
|
|
||||||
WORD bpbBytesPerSec; // bytes per sector
|
|
||||||
BYTE bpbSecPerClust; // sectors per cluster
|
|
||||||
WORD bpbResSectors; // number of reserved sectors
|
|
||||||
BYTE bpbFATs; // number of FATs
|
|
||||||
WORD bpbRootDirEnts; // number of root directory entries
|
|
||||||
WORD bpbSectors; // total number of sectors
|
|
||||||
BYTE bpbMedia; // media descriptor
|
|
||||||
WORD bpbFATsecs; // number of sectors per FAT
|
|
||||||
WORD bpbSecPerTrack; // sectors per track
|
|
||||||
WORD bpbHeads; // number of heads
|
|
||||||
DWORD bpbHiddenSecs; // # of hidden sectors
|
|
||||||
// 3.3 compat ends here
|
|
||||||
DWORD bpbHugeSectors; // # of sectors if bpbSectors == 0
|
|
||||||
};
|
|
||||||
|
|
||||||
// BPB for DOS 7.10 (FAT32)
|
|
||||||
// This one has a few extensions to bpb50.
|
|
||||||
struct bpb710 {
|
|
||||||
WORD bpbBytesPerSec; // bytes per sector
|
|
||||||
BYTE bpbSecPerClust; // sectors per cluster
|
|
||||||
WORD bpbResSectors; // number of reserved sectors
|
|
||||||
BYTE bpbFATs; // number of FATs
|
|
||||||
WORD bpbRootDirEnts; // number of root directory entries
|
|
||||||
WORD bpbSectors; // total number of sectors
|
|
||||||
BYTE bpbMedia; // media descriptor
|
|
||||||
WORD bpbFATsecs; // number of sectors per FAT
|
|
||||||
WORD bpbSecPerTrack; // sectors per track
|
|
||||||
WORD bpbHeads; // number of heads
|
|
||||||
DWORD bpbHiddenSecs; // # of hidden sectors
|
|
||||||
// 3.3 compat ends here
|
|
||||||
DWORD bpbHugeSectors; // # of sectors if bpbSectors == 0
|
|
||||||
// 5.0 compat ends here
|
|
||||||
DWORD bpbBigFATsecs;// like bpbFATsecs for FAT32
|
|
||||||
WORD bpbExtFlags; // extended flags:
|
|
||||||
#define FATNUM 0xf // mask for numbering active FAT
|
|
||||||
#define FATMIRROR 0x80 // FAT is mirrored (like it always was)
|
|
||||||
WORD bpbFSVers; // filesystem version
|
|
||||||
#define FSVERS 0 // currently only 0 is understood
|
|
||||||
DWORD bpbRootClust; // start cluster for root directory
|
|
||||||
WORD bpbFSInfo; // filesystem info structure sector
|
|
||||||
WORD bpbBackup; // backup boot sector
|
|
||||||
// There is a 12 byte filler here, but we ignore it
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ***************************************************************
|
|
||||||
// * byte versions of the above structs *
|
|
||||||
// ***************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
// BIOS Parameter Block (BPB) for DOS 3.3
|
|
||||||
struct byte_bpb33 {
|
|
||||||
CHAR bpbBytesPerSec[2]; // bytes per sector
|
|
||||||
CHAR bpbSecPerClust; // sectors per cluster
|
|
||||||
CHAR bpbResSectors[2]; // number of reserved sectors
|
|
||||||
CHAR bpbFATs; // number of FATs
|
|
||||||
CHAR bpbRootDirEnts[2]; // number of root directory entries
|
|
||||||
CHAR bpbSectors[2]; // total number of sectors
|
|
||||||
CHAR bpbMedia; // media descriptor
|
|
||||||
CHAR bpbFATsecs[2]; // number of sectors per FAT
|
|
||||||
CHAR bpbSecPerTrack[2]; // sectors per track
|
|
||||||
CHAR bpbHeads[2]; // number of heads
|
|
||||||
CHAR bpbHiddenSecs[2]; // number of hidden sectors
|
|
||||||
};
|
|
||||||
|
|
||||||
// BPB for DOS 5.0
|
|
||||||
// The difference is bpbHiddenSecs is a short for DOS 3.3,
|
|
||||||
// and bpbHugeSectors is not in the 3.3 bpb.
|
|
||||||
struct byte_bpb50 {
|
|
||||||
CHAR bpbBytesPerSec[2]; // bytes per sector
|
|
||||||
CHAR bpbSecPerClust; // sectors per cluster
|
|
||||||
CHAR bpbResSectors[2]; // number of reserved sectors
|
|
||||||
CHAR bpbFATs; // number of FATs
|
|
||||||
CHAR bpbRootDirEnts[2]; // number of root directory entries
|
|
||||||
CHAR bpbSectors[2]; // total number of sectors
|
|
||||||
CHAR bpbMedia; // media descriptor
|
|
||||||
CHAR bpbFATsecs[2]; // number of sectors per FAT
|
|
||||||
CHAR bpbSecPerTrack[2]; // sectors per track
|
|
||||||
CHAR bpbHeads[2]; // number of heads
|
|
||||||
CHAR bpbHiddenSecs[4]; // number of hidden sectors
|
|
||||||
CHAR bpbHugeSectors[4]; // # of sectors if bpbSectors == 0
|
|
||||||
};
|
|
||||||
|
|
||||||
// BPB for DOS 7.10 (FAT32).
|
|
||||||
// This one has a few extensions to bpb50.
|
|
||||||
struct byte_bpb710 {
|
|
||||||
BYTE bpbBytesPerSec[2]; // bytes per sector
|
|
||||||
BYTE bpbSecPerClust; // sectors per cluster
|
|
||||||
BYTE bpbResSectors[2]; // number of reserved sectors
|
|
||||||
BYTE bpbFATs; // number of FATs
|
|
||||||
BYTE bpbRootDirEnts[2]; // number of root directory entries
|
|
||||||
BYTE bpbSectors[2]; // total number of sectors
|
|
||||||
BYTE bpbMedia; // media descriptor
|
|
||||||
BYTE bpbFATsecs[2]; // number of sectors per FAT
|
|
||||||
BYTE bpbSecPerTrack[2]; // sectors per track
|
|
||||||
BYTE bpbHeads[2]; // number of heads
|
|
||||||
BYTE bpbHiddenSecs[4]; // # of hidden sectors
|
|
||||||
BYTE bpbHugeSectors[4]; // # of sectors if bpbSectors == 0
|
|
||||||
BYTE bpbBigFATsecs[4]; // like bpbFATsecs for FAT32
|
|
||||||
BYTE bpbExtFlags[2]; // extended flags:
|
|
||||||
BYTE bpbFSVers[2]; // filesystem version
|
|
||||||
BYTE bpbRootClust[4]; // start cluster for root directory
|
|
||||||
BYTE bpbFSInfo[2]; // filesystem info structure sector
|
|
||||||
BYTE bpbBackup[2]; // backup boot sector
|
|
||||||
// There is a 12 byte filler here, but we ignore it
|
|
||||||
};
|
|
||||||
|
|
||||||
// FAT32 FSInfo block.
|
|
||||||
struct fsinfo {
|
|
||||||
BYTE fsisig1[4];
|
|
||||||
BYTE fsifill1[480];
|
|
||||||
BYTE fsisig2[4];
|
|
||||||
BYTE fsinfree[4];
|
|
||||||
BYTE fsinxtfree[4];
|
|
||||||
BYTE fsifill2[12];
|
|
||||||
BYTE fsisig3[4];
|
|
||||||
BYTE fsifill3[508];
|
|
||||||
BYTE fsisig4[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************/
|
|
||||||
/***************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
// Structure of a dos directory entry.
|
|
||||||
struct direntry {
|
|
||||||
BYTE deName[8]; // filename, blank filled
|
|
||||||
#define SLOT_EMPTY 0x00 // slot has never been used
|
|
||||||
#define SLOT_E5 0x05 // the real value is 0xe5
|
|
||||||
#define SLOT_DELETED 0xe5 // file in this slot deleted
|
|
||||||
BYTE deExtension[3]; // extension, blank filled
|
|
||||||
BYTE deAttributes; // file attributes
|
|
||||||
#define ATTR_NORMAL 0x00 // normal file
|
|
||||||
#define ATTR_READONLY 0x01 // file is readonly
|
|
||||||
#define ATTR_HIDDEN 0x02 // file is hidden
|
|
||||||
#define ATTR_SYSTEM 0x04 // file is a system file
|
|
||||||
#define ATTR_VOLUME 0x08 // entry is a volume label
|
|
||||||
#define ATTR_LONG_FILENAME 0x0f // this is a long filename entry
|
|
||||||
#define ATTR_DIRECTORY 0x10 // entry is a directory name
|
|
||||||
#define ATTR_ARCHIVE 0x20 // file is new or modified
|
|
||||||
BYTE deLowerCase; // NT VFAT lower case flags
|
|
||||||
#define LCASE_BASE 0x08 // filename base in lower case
|
|
||||||
#define LCASE_EXT 0x10 // filename extension in lower case
|
|
||||||
BYTE deCHundredth; // hundredth of seconds in CTime
|
|
||||||
BYTE deCTime[2]; // create time
|
|
||||||
BYTE deCDate[2]; // create date
|
|
||||||
BYTE deADate[2]; // access date
|
|
||||||
WORD deHighClust; // high bytes of cluster number
|
|
||||||
BYTE deMTime[2]; // last update time
|
|
||||||
BYTE deMDate[2]; // last update date
|
|
||||||
WORD deStartCluster; // starting cluster of file
|
|
||||||
DWORD deFileSize; // size of file in bytes
|
|
||||||
};
|
|
||||||
|
|
||||||
// number of directory entries in one sector
|
|
||||||
#define DIRENTRIES_PER_SECTOR 0x10
|
|
||||||
|
|
||||||
// Structure of a Win95 long name directory entry
|
|
||||||
struct winentry {
|
|
||||||
BYTE weCnt;
|
|
||||||
#define WIN_LAST 0x40
|
|
||||||
#define WIN_CNT 0x3f
|
|
||||||
BYTE wePart1[10];
|
|
||||||
BYTE weAttributes;
|
|
||||||
#define ATTR_WIN95 0x0f
|
|
||||||
BYTE weReserved1;
|
|
||||||
BYTE weChksum;
|
|
||||||
BYTE wePart2[12];
|
|
||||||
WORD weReserved2;
|
|
||||||
BYTE wePart3[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
#define WIN_CHARS 13 // Number of chars per winentry
|
|
||||||
|
|
||||||
// Maximum filename length in Win95
|
|
||||||
// Note: Must be < sizeof(dirent.d_name)
|
|
||||||
#define WIN_MAXLEN 255
|
|
||||||
|
|
||||||
// This is the format of the contents of the deTime field in the direntry
|
|
||||||
// structure.
|
|
||||||
// We don't use bitfields because we don't know how compilers for
|
|
||||||
// arbitrary machines will lay them out.
|
|
||||||
#define DT_2SECONDS_MASK 0x1F // seconds divided by 2
|
|
||||||
#define DT_2SECONDS_SHIFT 0
|
|
||||||
#define DT_MINUTES_MASK 0x7E0 // minutes
|
|
||||||
#define DT_MINUTES_SHIFT 5
|
|
||||||
#define DT_HOURS_MASK 0xF800 // hours
|
|
||||||
#define DT_HOURS_SHIFT 11
|
|
||||||
|
|
||||||
// This is the format of the contents of the deDate field in the direntry
|
|
||||||
// structure.
|
|
||||||
#define DD_DAY_MASK 0x1F // day of month
|
|
||||||
#define DD_DAY_SHIFT 0
|
|
||||||
#define DD_MONTH_MASK 0x1E0 // month
|
|
||||||
#define DD_MONTH_SHIFT 5
|
|
||||||
#define DD_YEAR_MASK 0xFE00 // year - 1980
|
|
||||||
#define DD_YEAR_SHIFT 9
|
|
||||||
|
|
||||||
// Prototypes
|
|
||||||
unsigned char fatInit( unsigned char device);
|
|
||||||
unsigned int fatClusterSize(void);
|
|
||||||
unsigned long fatGetDirEntry(unsigned int entry, unsigned int count);
|
|
||||||
unsigned long fatGetFilesize(void);
|
|
||||||
char* fatGetFilename(void);
|
|
||||||
char* fatGetDirname(void);
|
|
||||||
void fatLoadCluster(unsigned long cluster, unsigned char *buffer);
|
|
||||||
unsigned long fatNextCluster(unsigned long cluster);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,85 +0,0 @@
|
|||||||
/*! \file fixedpt.c \brief Fixed-point math function library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'fixedpt.c'
|
|
||||||
// Title : Fixed-point math function library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2003
|
|
||||||
// Created : 2003.01.26
|
|
||||||
// Revised : 2003.02.02
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
#include "fixedpt.h"
|
|
||||||
|
|
||||||
// Program ROM constants
|
|
||||||
|
|
||||||
// Global variables
|
|
||||||
u08 FixedPtBits;
|
|
||||||
|
|
||||||
// Functions
|
|
||||||
|
|
||||||
// fixedptInit() initializes fixed-point math function library
|
|
||||||
void fixedptInit(u08 fixedPtBits)
|
|
||||||
{
|
|
||||||
// set the number of bits to use behind the point
|
|
||||||
FixedPtBits = fixedPtBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 fixedptConvertFromInt(s32 int_number)
|
|
||||||
{
|
|
||||||
// convert integer to fixed-point number
|
|
||||||
return (int_number<<FixedPtBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 fixedptConvertToInt(s32 fp_number)
|
|
||||||
{
|
|
||||||
// convert fixed-point number to integer
|
|
||||||
// do rounding
|
|
||||||
if( fp_number & 1<<(FixedPtBits-1) )
|
|
||||||
{
|
|
||||||
// bit behind the point was a '1'
|
|
||||||
// round up to next higher integer
|
|
||||||
return (fp_number>>FixedPtBits)+1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// bit behind the point was a '0'
|
|
||||||
// round down (truncate) to next lower integer
|
|
||||||
return (fp_number>>FixedPtBits);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 fixedptAdd(s32 a, s32 b)
|
|
||||||
{
|
|
||||||
// add a and b (a+b) with fixed-point math
|
|
||||||
return a+b;
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 fixedptSubtract(s32 a, s32 b)
|
|
||||||
{
|
|
||||||
// subtract a and b (a-b) with fixed-point math
|
|
||||||
return a-b;
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 fixedptMultiply(s32 a, s32 b)
|
|
||||||
{
|
|
||||||
// multiply a and b (a*b) with fixed-point math
|
|
||||||
return (a*b)>>FixedPtBits;
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 fixedptDivide(s32 numer, s32 denom)
|
|
||||||
{
|
|
||||||
// divide numer by denom (numer/denom) with fixed-point math
|
|
||||||
return (numer<<FixedPtBits)/denom;
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
/*! \file fixedpt.h \brief Fixed-point math function library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'fixedpt.h'
|
|
||||||
// Title : Fixed-point math function library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2003
|
|
||||||
// Created : 2003.01.26
|
|
||||||
// Revised : 2003.02.04
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef FIXEDPT_H
|
|
||||||
#define FIXEDPT_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
// constants/macros/typdefs
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
//! fixedptInit() initializes fixed-point math function library
|
|
||||||
// set the number of bits to use behind the point
|
|
||||||
void fixedptInit(u08 fixedPtBits);
|
|
||||||
|
|
||||||
//! convert integer to fixed-point number
|
|
||||||
s32 fixedptConvertFromInt(s32 int_number);
|
|
||||||
|
|
||||||
//! convert fixed-point number to integer
|
|
||||||
s32 fixedptConvertToInt(s32 fp_number);
|
|
||||||
|
|
||||||
//! add a and b (a+b) with fixed-point math
|
|
||||||
s32 fixedptAdd(s32 a, s32 b);
|
|
||||||
|
|
||||||
//! subtract a and b (a-b) with fixed-point math
|
|
||||||
s32 fixedptSubtract(s32 a, s32 b);
|
|
||||||
|
|
||||||
//! multiply a and b (a*b) with fixed-point math
|
|
||||||
s32 fixedptMultiply(s32 a, s32 b);
|
|
||||||
|
|
||||||
//! divide numer by denom (numer/denom) with fixed-point math
|
|
||||||
s32 fixedptDivide(s32 numer, s32 denom);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,119 +0,0 @@
|
|||||||
/*! \file font5x7.h \brief Graphic LCD Font (Ascii Characters). */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'font5x7.h'
|
|
||||||
// Title : Graphic LCD Font (Ascii Charaters)
|
|
||||||
// Author : Pascal Stang
|
|
||||||
// Date : 10/19/2001
|
|
||||||
// Revised : 10/19/2001
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef FONT5X7_H
|
|
||||||
#define FONT5X7_H
|
|
||||||
|
|
||||||
// standard ascii 5x7 font
|
|
||||||
// defines ascii characters 0x20-0x7F (32-127)
|
|
||||||
static unsigned char __attribute__ ((progmem)) Font5x7[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00,// (space)
|
|
||||||
0x00, 0x00, 0x5F, 0x00, 0x00,// !
|
|
||||||
0x00, 0x07, 0x00, 0x07, 0x00,// "
|
|
||||||
0x14, 0x7F, 0x14, 0x7F, 0x14,// #
|
|
||||||
0x24, 0x2A, 0x7F, 0x2A, 0x12,// $
|
|
||||||
0x23, 0x13, 0x08, 0x64, 0x62,// %
|
|
||||||
0x36, 0x49, 0x55, 0x22, 0x50,// &
|
|
||||||
0x00, 0x05, 0x03, 0x00, 0x00,// '
|
|
||||||
0x00, 0x1C, 0x22, 0x41, 0x00,// (
|
|
||||||
0x00, 0x41, 0x22, 0x1C, 0x00,// )
|
|
||||||
0x08, 0x2A, 0x1C, 0x2A, 0x08,// *
|
|
||||||
0x08, 0x08, 0x3E, 0x08, 0x08,// +
|
|
||||||
0x00, 0x50, 0x30, 0x00, 0x00,// ,
|
|
||||||
0x08, 0x08, 0x08, 0x08, 0x08,// -
|
|
||||||
0x00, 0x60, 0x60, 0x00, 0x00,// .
|
|
||||||
0x20, 0x10, 0x08, 0x04, 0x02,// /
|
|
||||||
0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
|
|
||||||
0x00, 0x42, 0x7F, 0x40, 0x00,// 1
|
|
||||||
0x42, 0x61, 0x51, 0x49, 0x46,// 2
|
|
||||||
0x21, 0x41, 0x45, 0x4B, 0x31,// 3
|
|
||||||
0x18, 0x14, 0x12, 0x7F, 0x10,// 4
|
|
||||||
0x27, 0x45, 0x45, 0x45, 0x39,// 5
|
|
||||||
0x3C, 0x4A, 0x49, 0x49, 0x30,// 6
|
|
||||||
0x01, 0x71, 0x09, 0x05, 0x03,// 7
|
|
||||||
0x36, 0x49, 0x49, 0x49, 0x36,// 8
|
|
||||||
0x06, 0x49, 0x49, 0x29, 0x1E,// 9
|
|
||||||
0x00, 0x36, 0x36, 0x00, 0x00,// :
|
|
||||||
0x00, 0x56, 0x36, 0x00, 0x00,// ;
|
|
||||||
0x00, 0x08, 0x14, 0x22, 0x41,// <
|
|
||||||
0x14, 0x14, 0x14, 0x14, 0x14,// =
|
|
||||||
0x41, 0x22, 0x14, 0x08, 0x00,// >
|
|
||||||
0x02, 0x01, 0x51, 0x09, 0x06,// ?
|
|
||||||
0x32, 0x49, 0x79, 0x41, 0x3E,// @
|
|
||||||
0x7E, 0x11, 0x11, 0x11, 0x7E,// A
|
|
||||||
0x7F, 0x49, 0x49, 0x49, 0x36,// B
|
|
||||||
0x3E, 0x41, 0x41, 0x41, 0x22,// C
|
|
||||||
0x7F, 0x41, 0x41, 0x22, 0x1C,// D
|
|
||||||
0x7F, 0x49, 0x49, 0x49, 0x41,// E
|
|
||||||
0x7F, 0x09, 0x09, 0x01, 0x01,// F
|
|
||||||
0x3E, 0x41, 0x41, 0x51, 0x32,// G
|
|
||||||
0x7F, 0x08, 0x08, 0x08, 0x7F,// H
|
|
||||||
0x00, 0x41, 0x7F, 0x41, 0x00,// I
|
|
||||||
0x20, 0x40, 0x41, 0x3F, 0x01,// J
|
|
||||||
0x7F, 0x08, 0x14, 0x22, 0x41,// K
|
|
||||||
0x7F, 0x40, 0x40, 0x40, 0x40,// L
|
|
||||||
0x7F, 0x02, 0x04, 0x02, 0x7F,// M
|
|
||||||
0x7F, 0x04, 0x08, 0x10, 0x7F,// N
|
|
||||||
0x3E, 0x41, 0x41, 0x41, 0x3E,// O
|
|
||||||
0x7F, 0x09, 0x09, 0x09, 0x06,// P
|
|
||||||
0x3E, 0x41, 0x51, 0x21, 0x5E,// Q
|
|
||||||
0x7F, 0x09, 0x19, 0x29, 0x46,// R
|
|
||||||
0x46, 0x49, 0x49, 0x49, 0x31,// S
|
|
||||||
0x01, 0x01, 0x7F, 0x01, 0x01,// T
|
|
||||||
0x3F, 0x40, 0x40, 0x40, 0x3F,// U
|
|
||||||
0x1F, 0x20, 0x40, 0x20, 0x1F,// V
|
|
||||||
0x7F, 0x20, 0x18, 0x20, 0x7F,// W
|
|
||||||
0x63, 0x14, 0x08, 0x14, 0x63,// X
|
|
||||||
0x03, 0x04, 0x78, 0x04, 0x03,// Y
|
|
||||||
0x61, 0x51, 0x49, 0x45, 0x43,// Z
|
|
||||||
0x00, 0x00, 0x7F, 0x41, 0x41,// [
|
|
||||||
0x02, 0x04, 0x08, 0x10, 0x20,// "\"
|
|
||||||
0x41, 0x41, 0x7F, 0x00, 0x00,// ]
|
|
||||||
0x04, 0x02, 0x01, 0x02, 0x04,// ^
|
|
||||||
0x40, 0x40, 0x40, 0x40, 0x40,// _
|
|
||||||
0x00, 0x01, 0x02, 0x04, 0x00,// `
|
|
||||||
0x20, 0x54, 0x54, 0x54, 0x78,// a
|
|
||||||
0x7F, 0x48, 0x44, 0x44, 0x38,// b
|
|
||||||
0x38, 0x44, 0x44, 0x44, 0x20,// c
|
|
||||||
0x38, 0x44, 0x44, 0x48, 0x7F,// d
|
|
||||||
0x38, 0x54, 0x54, 0x54, 0x18,// e
|
|
||||||
0x08, 0x7E, 0x09, 0x01, 0x02,// f
|
|
||||||
0x08, 0x14, 0x54, 0x54, 0x3C,// g
|
|
||||||
0x7F, 0x08, 0x04, 0x04, 0x78,// h
|
|
||||||
0x00, 0x44, 0x7D, 0x40, 0x00,// i
|
|
||||||
0x20, 0x40, 0x44, 0x3D, 0x00,// j
|
|
||||||
0x00, 0x7F, 0x10, 0x28, 0x44,// k
|
|
||||||
0x00, 0x41, 0x7F, 0x40, 0x00,// l
|
|
||||||
0x7C, 0x04, 0x18, 0x04, 0x78,// m
|
|
||||||
0x7C, 0x08, 0x04, 0x04, 0x78,// n
|
|
||||||
0x38, 0x44, 0x44, 0x44, 0x38,// o
|
|
||||||
0x7C, 0x14, 0x14, 0x14, 0x08,// p
|
|
||||||
0x08, 0x14, 0x14, 0x18, 0x7C,// q
|
|
||||||
0x7C, 0x08, 0x04, 0x04, 0x08,// r
|
|
||||||
0x48, 0x54, 0x54, 0x54, 0x20,// s
|
|
||||||
0x04, 0x3F, 0x44, 0x40, 0x20,// t
|
|
||||||
0x3C, 0x40, 0x40, 0x20, 0x7C,// u
|
|
||||||
0x1C, 0x20, 0x40, 0x20, 0x1C,// v
|
|
||||||
0x3C, 0x40, 0x30, 0x40, 0x3C,// w
|
|
||||||
0x44, 0x28, 0x10, 0x28, 0x44,// x
|
|
||||||
0x0C, 0x50, 0x50, 0x50, 0x3C,// y
|
|
||||||
0x44, 0x64, 0x54, 0x4C, 0x44,// z
|
|
||||||
0x00, 0x08, 0x36, 0x41, 0x00,// {
|
|
||||||
0x00, 0x00, 0x7F, 0x00, 0x00,// |
|
|
||||||
0x00, 0x41, 0x36, 0x08, 0x00,// }
|
|
||||||
0x08, 0x08, 0x2A, 0x1C, 0x08,// ->
|
|
||||||
0x08, 0x1C, 0x2A, 0x08, 0x08 // <-
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,31 +0,0 @@
|
|||||||
/*! \file fontgr.h \brief Graphic LCD Font (Graphic Characters). */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'fontgr.h'
|
|
||||||
// Title : Graphic LCD Font (Graphic Charaters)
|
|
||||||
// Author : Pascal Stang
|
|
||||||
// Date : 10/19/2001
|
|
||||||
// Revised : 10/19/2001
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef FONTGR_H
|
|
||||||
#define FONTGR_H
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
// AVR specific includes
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static unsigned char __attribute__ ((progmem)) FontGr[] =
|
|
||||||
{
|
|
||||||
// format is one character per line:
|
|
||||||
// length, byte array[length]
|
|
||||||
0x0B,0x3E,0x41,0x41,0x41,0x41,0x42,0x42,0x42,0x42,0x3C,0x00,// 0. Folder Icon
|
|
||||||
0x06,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF // 1. Solid 6x8 block
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,164 +0,0 @@
|
|||||||
/*! \file glcd.c \brief Graphic LCD API functions. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'glcd.c'
|
|
||||||
// Title : Graphic LCD API functions
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002
|
|
||||||
// Date : 5/30/2002
|
|
||||||
// Revised : 5/30/2002
|
|
||||||
// Version : 0.5
|
|
||||||
// Target MCU : Atmel AVR
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
// AVR specific includes
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "glcd.h"
|
|
||||||
|
|
||||||
// include hardware support
|
|
||||||
#include "ks0108.h"
|
|
||||||
// include fonts
|
|
||||||
#include "font5x7.h"
|
|
||||||
#include "fontgr.h"
|
|
||||||
|
|
||||||
// graphic routines
|
|
||||||
|
|
||||||
// set dot
|
|
||||||
void glcdSetDot(u08 x, u08 y)
|
|
||||||
{
|
|
||||||
unsigned char temp;
|
|
||||||
|
|
||||||
glcdSetAddress(x, y/8);
|
|
||||||
temp = glcdDataRead(); // dummy read
|
|
||||||
temp = glcdDataRead(); // read back current value
|
|
||||||
glcdSetAddress(x, y/8);
|
|
||||||
glcdDataWrite(temp | (1 << (y % 8)));
|
|
||||||
|
|
||||||
glcdStartLine(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear dot
|
|
||||||
void glcdClearDot(u08 x, u08 y)
|
|
||||||
{
|
|
||||||
unsigned char temp;
|
|
||||||
|
|
||||||
glcdSetAddress(x, y/8);
|
|
||||||
temp = glcdDataRead(); // dummy read
|
|
||||||
temp = glcdDataRead(); // read back current value
|
|
||||||
glcdSetAddress(x, y/8);
|
|
||||||
glcdDataWrite(temp & ~(1 << (y % 8)));
|
|
||||||
|
|
||||||
glcdStartLine(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw line
|
|
||||||
void glcdLine(u08 x1, u08 y1, u08 x2, u08 y2)
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
// draw rectangle
|
|
||||||
void glcdRectangle(u08 x, u08 y, u08 a, u08 b)
|
|
||||||
{
|
|
||||||
unsigned char j;
|
|
||||||
|
|
||||||
for (j = 0; j < a; j++) {
|
|
||||||
glcdSetDot(x, y + j);
|
|
||||||
glcdSetDot(x + b - 1, y + j);
|
|
||||||
}
|
|
||||||
for (j = 0; j < b; j++) {
|
|
||||||
glcdSetDot(x + j, y);
|
|
||||||
glcdSetDot(x + j, y + a - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw circle
|
|
||||||
void glcdCircle(u08 xcenter, u08 ycenter, u08 radius)
|
|
||||||
{
|
|
||||||
int tswitch, y, x = 0;
|
|
||||||
unsigned char d;
|
|
||||||
|
|
||||||
d = ycenter - xcenter;
|
|
||||||
y = radius;
|
|
||||||
tswitch = 3 - 2 * radius;
|
|
||||||
while (x <= y) {
|
|
||||||
glcdSetDot(xcenter + x, ycenter + y); glcdSetDot(xcenter + x, ycenter - y);
|
|
||||||
glcdSetDot(xcenter - x, ycenter + y); glcdSetDot(xcenter - x, ycenter - y);
|
|
||||||
glcdSetDot(ycenter + y - d, ycenter + x); glcdSetDot(ycenter + y - d, ycenter - x);
|
|
||||||
glcdSetDot(ycenter - y - d, ycenter + x); glcdSetDot(ycenter - y - d, ycenter - x);
|
|
||||||
|
|
||||||
if (tswitch < 0) tswitch += (4 * x + 6);
|
|
||||||
else {
|
|
||||||
tswitch += (4 * (x - y) + 10);
|
|
||||||
y--;
|
|
||||||
}
|
|
||||||
x++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// text routines
|
|
||||||
|
|
||||||
// write a character at the current position
|
|
||||||
void glcdWriteChar(unsigned char c)
|
|
||||||
{
|
|
||||||
u08 i = 0;
|
|
||||||
|
|
||||||
for(i=0; i<5; i++)
|
|
||||||
{
|
|
||||||
glcdDataWrite(pgm_read_byte(&Font5x7[((c - 0x20) * 5) + i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// write a spacer line
|
|
||||||
glcdDataWrite(0x00);
|
|
||||||
// unless we're at the end of the display
|
|
||||||
//if(xx == 128)
|
|
||||||
// xx = 0;
|
|
||||||
//else
|
|
||||||
// glcdWriteData(0x00);
|
|
||||||
|
|
||||||
//cbi(GLCD_Control, GLCD_CS1);
|
|
||||||
//cbi(GLCD_Control, GLCD_CS2);
|
|
||||||
glcdStartLine(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void glcdWriteCharGr(u08 grCharIdx)
|
|
||||||
{
|
|
||||||
u08 idx;
|
|
||||||
u08 grLength;
|
|
||||||
u08 grStartIdx = 0;
|
|
||||||
|
|
||||||
// get starting index of graphic bitmap
|
|
||||||
for(idx=0; idx<grCharIdx; idx++)
|
|
||||||
{
|
|
||||||
// add this graphic's length to the startIdx
|
|
||||||
// to get the startIdx of the next one
|
|
||||||
grStartIdx += pgm_read_byte(FontGr+grStartIdx);
|
|
||||||
}
|
|
||||||
grLength = pgm_read_byte(FontGr+grStartIdx);
|
|
||||||
|
|
||||||
// write the lines of the desired graphic to the display
|
|
||||||
for(idx=0; idx<grLength; idx++)
|
|
||||||
{
|
|
||||||
// write the line
|
|
||||||
glcdDataWrite(pgm_read_byte(FontGr+(grStartIdx+1)+idx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void glcdPutStr(unsigned char *data)
|
|
||||||
{
|
|
||||||
while (*data) {
|
|
||||||
glcdWriteChar(*data);
|
|
||||||
data++;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,73 +0,0 @@
|
|||||||
/*! \file glcd.h \brief Graphic LCD API functions. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'glcd.h'
|
|
||||||
// Title : Graphic LCD API functions
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002
|
|
||||||
// Date : 5/30/2002
|
|
||||||
// Revised : 5/30/2002
|
|
||||||
// Version : 0.5
|
|
||||||
// Target MCU : Atmel AVR
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef GLCD_H
|
|
||||||
#define GLCD_H
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
// AVR specific includes
|
|
||||||
#include <avr/io.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
#define LINE1 0
|
|
||||||
#define LINE2 1
|
|
||||||
#define LINE3 2
|
|
||||||
#define LINE4 3
|
|
||||||
#define LINE5 4
|
|
||||||
#define LINE6 5
|
|
||||||
#define LINE7 6
|
|
||||||
#define LINE8 7
|
|
||||||
|
|
||||||
#define ON 1
|
|
||||||
#define OFF 0
|
|
||||||
|
|
||||||
// API-level interface commands
|
|
||||||
// ***** Public Functions *****
|
|
||||||
|
|
||||||
//! set a dot on the display (x is horiz 0:127, y is vert 0:63)
|
|
||||||
void glcdSetDot(u08 x, u08 y);
|
|
||||||
|
|
||||||
//! clear a dot on the display (x is horiz 0:127, y is vert 0:63)
|
|
||||||
void glcdClearDot(u08 x, u08 y);
|
|
||||||
|
|
||||||
//! draw line
|
|
||||||
void glcdLine(u08 x1, u08 y1, u08 x2, u08 y2);
|
|
||||||
|
|
||||||
//! draw rectangle (coords????)
|
|
||||||
void glcdRectangle(u08 x, u08 y, u08 a, u08 b);
|
|
||||||
|
|
||||||
//! draw circle of <radius> at <xcenter,ycenter>
|
|
||||||
void glcdCircle(u08 xcenter, u08 ycenter, u08 radius);
|
|
||||||
|
|
||||||
//! write a standard ascii charater (values 20-127)
|
|
||||||
// to the display at current position
|
|
||||||
void glcdWriteChar(unsigned char c);
|
|
||||||
|
|
||||||
//! write a special graphic character/icon
|
|
||||||
// to the display at current position
|
|
||||||
void glcdWriteCharGr(u08 grCharIndex);
|
|
||||||
|
|
||||||
// ***** Private Functions ***** (or depricated)
|
|
||||||
void glcdPutStr(u08 *data);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,84 +0,0 @@
|
|||||||
/*! \file gps.c \brief GPS position storage and processing library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'gps.c'
|
|
||||||
// Title : GPS position storage and processing function library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002-2005
|
|
||||||
// Created : 2005.01.14
|
|
||||||
// Revised : 2002.07.17
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/signal.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include "rprintf.h"
|
|
||||||
#include "gps.h"
|
|
||||||
|
|
||||||
// Global variables
|
|
||||||
GpsInfoType GpsInfo;
|
|
||||||
|
|
||||||
// Functions
|
|
||||||
void gpsInit(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
GpsInfoType* gpsGetInfo(void)
|
|
||||||
{
|
|
||||||
return &GpsInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gpsInfoPrint(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
rprintfProgStrM("TOW: "); rprintfFloat(8, GpsInfo.TimeOfWeek.f); rprintfCRLF();
|
|
||||||
rprintfProgStrM("WkNum: "); rprintfNum(10,4,0,' ',GpsInfo.WeekNum); rprintfCRLF();
|
|
||||||
rprintfProgStrM("UTCoffset:"); rprintfFloat(8, GpsInfo.UtcOffset.f); rprintfCRLF();
|
|
||||||
rprintfProgStrM("Num SVs: "); rprintfNum(10,4,0,' ',GpsInfo.numSVs); rprintfCRLF();
|
|
||||||
|
|
||||||
rprintfProgStrM("X_ECEF: "); rprintfFloat(8, GpsInfo.PosECEF.x.f); rprintfCRLF();
|
|
||||||
rprintfProgStrM("Y_ECEF: "); rprintfFloat(8, GpsInfo.PosECEF.y.f); rprintfCRLF();
|
|
||||||
rprintfProgStrM("Z_ECEF: "); rprintfFloat(8, GpsInfo.PosECEF.z.f); rprintfCRLF();
|
|
||||||
rprintfProgStrM("TOF: "); rprintfFloat(8, GpsInfo.PosECEF.TimeOfFix.f); rprintfCRLF();
|
|
||||||
rprintfProgStrM("Updates: "); rprintfNum(10,6,0,' ',GpsInfo.PosECEF.updates); rprintfCRLF();
|
|
||||||
|
|
||||||
//u08 str[20];
|
|
||||||
//rprintfProgStrM(" PosLat: "); rprintfStr(dtostrf(GpsInfo.PosLat.f, 10, 5, str));
|
|
||||||
rprintfProgStrM("PosLat: "); rprintfFloat(8, 180*(GpsInfo.PosLLA.lat.f/PI)); rprintfCRLF();
|
|
||||||
rprintfProgStrM("PosLon: "); rprintfFloat(8, 180*(GpsInfo.PosLLA.lon.f/PI)); rprintfCRLF();
|
|
||||||
rprintfProgStrM("PosAlt: "); rprintfFloat(8, GpsInfo.PosLLA.alt.f); rprintfCRLF();
|
|
||||||
rprintfProgStrM("TOF: "); rprintfFloat(8, GpsInfo.PosLLA.TimeOfFix.f); rprintfCRLF();
|
|
||||||
rprintfProgStrM("Updates: "); rprintfNum(10,6,0,' ',GpsInfo.PosLLA.updates); rprintfCRLF();
|
|
||||||
|
|
||||||
rprintfProgStrM("Vel East: "); rprintfFloat(8, GpsInfo.VelENU.east.f); rprintfCRLF();
|
|
||||||
rprintfProgStrM("Vel North:"); rprintfFloat(8, GpsInfo.VelENU.north.f); rprintfCRLF();
|
|
||||||
rprintfProgStrM("Vel Up: "); rprintfFloat(8, GpsInfo.VelENU.up.f); rprintfCRLF();
|
|
||||||
// rprintfProgStrM("TOF: "); rprintfFloat(8, GpsInfo.VelENU.TimeOfFix.f); rprintfCRLF();
|
|
||||||
rprintfProgStrM("Updates: "); rprintfNum(10,6,0,' ',GpsInfo.VelENU.updates); rprintfCRLF();
|
|
||||||
|
|
||||||
rprintfProgStrM("Vel Head: "); rprintfFloat(8, GpsInfo.VelHS.heading.f); rprintfCRLF();
|
|
||||||
rprintfProgStrM("Vel Speed:"); rprintfFloat(8, GpsInfo.VelHS.speed.f); rprintfCRLF();
|
|
||||||
// rprintfProgStrM("TOF: "); rprintfFloat(8, GpsInfo.VelHS.TimeOfFix.f); rprintfCRLF();
|
|
||||||
rprintfProgStrM("Updates: "); rprintfNum(10,6,0,' ',GpsInfo.VelHS.updates); rprintfCRLF();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,106 +0,0 @@
|
|||||||
/*! \file gps.h \brief GPS position storage and processing library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'gps.h'
|
|
||||||
// Title : GPS position storage and processing function library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002
|
|
||||||
// Created : 2002.08.29
|
|
||||||
// Revised : 2002.08.29
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef GPS_H
|
|
||||||
#define GPS_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
// constants/macros/typdefs
|
|
||||||
typedef union union_float_u32
|
|
||||||
{
|
|
||||||
float f;
|
|
||||||
unsigned long i;
|
|
||||||
unsigned char b[4];
|
|
||||||
} float_u32;
|
|
||||||
|
|
||||||
typedef union union_double_u64
|
|
||||||
{
|
|
||||||
double f;
|
|
||||||
unsigned long long i;
|
|
||||||
unsigned char b[8];
|
|
||||||
} double_u64;
|
|
||||||
|
|
||||||
struct PositionLLA
|
|
||||||
{
|
|
||||||
float_u32 lat;
|
|
||||||
float_u32 lon;
|
|
||||||
float_u32 alt;
|
|
||||||
float_u32 TimeOfFix;
|
|
||||||
u16 updates;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct VelocityENU
|
|
||||||
{
|
|
||||||
float_u32 east;
|
|
||||||
float_u32 north;
|
|
||||||
float_u32 up;
|
|
||||||
float_u32 TimeOfFix;
|
|
||||||
u16 updates;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct VelocityHS
|
|
||||||
{
|
|
||||||
float_u32 heading;
|
|
||||||
float_u32 speed;
|
|
||||||
float_u32 TimeOfFix;
|
|
||||||
u16 updates;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PositionECEF
|
|
||||||
{
|
|
||||||
float_u32 x;
|
|
||||||
float_u32 y;
|
|
||||||
float_u32 z;
|
|
||||||
float_u32 TimeOfFix;
|
|
||||||
u16 updates;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct VelocityECEF
|
|
||||||
{
|
|
||||||
float_u32 x;
|
|
||||||
float_u32 y;
|
|
||||||
float_u32 z;
|
|
||||||
float_u32 TimeOfFix;
|
|
||||||
u16 updates;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct struct_GpsInfo
|
|
||||||
{
|
|
||||||
float_u32 TimeOfWeek;
|
|
||||||
u16 WeekNum;
|
|
||||||
float_u32 UtcOffset;
|
|
||||||
u08 numSVs;
|
|
||||||
|
|
||||||
struct PositionLLA PosLLA;
|
|
||||||
struct PositionECEF PosECEF;
|
|
||||||
struct VelocityECEF VelECEF;
|
|
||||||
struct VelocityENU VelENU;
|
|
||||||
struct VelocityHS VelHS;
|
|
||||||
|
|
||||||
} GpsInfoType;
|
|
||||||
|
|
||||||
// functions
|
|
||||||
void gpsInit(void);
|
|
||||||
GpsInfoType* gpsGetInfo(void);
|
|
||||||
void gpsInfoPrint(void);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,635 +0,0 @@
|
|||||||
/*! \file i2c.c \brief I2C interface using AVR Two-Wire Interface (TWI) hardware. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'i2c.c'
|
|
||||||
// Title : I2C interface using AVR Two-Wire Interface (TWI) hardware
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002-2003
|
|
||||||
// Created : 2002.06.25
|
|
||||||
// Revised : 2003.03.02
|
|
||||||
// Version : 0.9
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// Description : I2C (pronounced "eye-squared-see") is a two-wire bidirectional
|
|
||||||
// network designed for easy transfer of information between a wide variety
|
|
||||||
// of intelligent devices. Many of the Atmel AVR series processors have
|
|
||||||
// hardware support for transmitting and receiving using an I2C-type bus.
|
|
||||||
// In addition to the AVRs, there are thousands of other parts made by
|
|
||||||
// manufacturers like Philips, Maxim, National, TI, etc that use I2C as
|
|
||||||
// their primary means of communication and control. Common device types
|
|
||||||
// are A/D & D/A converters, temp sensors, intelligent battery monitors,
|
|
||||||
// MP3 decoder chips, EEPROM chips, multiplexing switches, etc.
|
|
||||||
//
|
|
||||||
// I2C uses only two wires (SDA and SCL) to communicate bidirectionally
|
|
||||||
// between devices. I2C is a multidrop network, meaning that you can have
|
|
||||||
// several devices on a single bus. Because I2C uses a 7-bit number to
|
|
||||||
// identify which device it wants to talk to, you cannot have more than
|
|
||||||
// 127 devices on a single bus.
|
|
||||||
//
|
|
||||||
// I2C ordinarily requires two 4.7K pull-up resistors to power (one each on
|
|
||||||
// SDA and SCL), but for small numbers of devices (maybe 1-4), it is enough
|
|
||||||
// to activate the internal pull-up resistors in the AVR processor. To do
|
|
||||||
// this, set the port pins, which correspond to the I2C pins SDA/SCL, high.
|
|
||||||
// For example, on the mega163, sbi(PORTC, 0); sbi(PORTC, 1);.
|
|
||||||
//
|
|
||||||
// For complete information about I2C, see the Philips Semiconductor
|
|
||||||
// website. They created I2C and have the largest family of devices that
|
|
||||||
// work with I2C.
|
|
||||||
//
|
|
||||||
// Note: Many manufacturers market I2C bus devices under a different or generic
|
|
||||||
// bus name like "Two-Wire Interface". This is because Philips still holds
|
|
||||||
// "I2C" as a trademark. For example, SMBus and SMBus devices are hardware
|
|
||||||
// compatible and closely related to I2C. They can be directly connected
|
|
||||||
// to an I2C bus along with other I2C devices are are generally accessed in
|
|
||||||
// the same way as I2C devices. SMBus is often found on modern motherboards
|
|
||||||
// for temp sensing and other low-level control tasks.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/signal.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
#include "i2c.h"
|
|
||||||
|
|
||||||
#include "rprintf.h" // include printf function library
|
|
||||||
#include "uart2.h"
|
|
||||||
|
|
||||||
// Standard I2C bit rates are:
|
|
||||||
// 100KHz for slow speed
|
|
||||||
// 400KHz for high speed
|
|
||||||
|
|
||||||
//#define I2C_DEBUG
|
|
||||||
|
|
||||||
// I2C state and address variables
|
|
||||||
static volatile eI2cStateType I2cState;
|
|
||||||
static u08 I2cDeviceAddrRW;
|
|
||||||
// send/transmit buffer (outgoing data)
|
|
||||||
static u08 I2cSendData[I2C_SEND_DATA_BUFFER_SIZE];
|
|
||||||
static u08 I2cSendDataIndex;
|
|
||||||
static u08 I2cSendDataLength;
|
|
||||||
// receive buffer (incoming data)
|
|
||||||
static u08 I2cReceiveData[I2C_RECEIVE_DATA_BUFFER_SIZE];
|
|
||||||
static u08 I2cReceiveDataIndex;
|
|
||||||
static u08 I2cReceiveDataLength;
|
|
||||||
|
|
||||||
// function pointer to i2c receive routine
|
|
||||||
//! I2cSlaveReceive is called when this processor
|
|
||||||
// is addressed as a slave for writing
|
|
||||||
static void (*i2cSlaveReceive)(u08 receiveDataLength, u08* recieveData);
|
|
||||||
//! I2cSlaveTransmit is called when this processor
|
|
||||||
// is addressed as a slave for reading
|
|
||||||
static u08 (*i2cSlaveTransmit)(u08 transmitDataLengthMax, u08* transmitData);
|
|
||||||
|
|
||||||
// functions
|
|
||||||
void i2cInit(void)
|
|
||||||
{
|
|
||||||
// set pull-up resistors on I2C bus pins
|
|
||||||
// TODO: should #ifdef these
|
|
||||||
sbi(PORTC, 0); // i2c SCL on ATmega163,323,16,32,etc
|
|
||||||
sbi(PORTC, 1); // i2c SDA on ATmega163,323,16,32,etc
|
|
||||||
sbi(PORTD, 0); // i2c SCL on ATmega128,64
|
|
||||||
sbi(PORTD, 1); // i2c SDA on ATmega128,64
|
|
||||||
|
|
||||||
// clear SlaveReceive and SlaveTransmit handler to null
|
|
||||||
i2cSlaveReceive = 0;
|
|
||||||
i2cSlaveTransmit = 0;
|
|
||||||
// set i2c bit rate to 100KHz
|
|
||||||
i2cSetBitrate(100);
|
|
||||||
// enable TWI (two-wire interface)
|
|
||||||
sbi(TWCR, TWEN);
|
|
||||||
// set state
|
|
||||||
I2cState = I2C_IDLE;
|
|
||||||
// enable TWI interrupt and slave address ACK
|
|
||||||
sbi(TWCR, TWIE);
|
|
||||||
sbi(TWCR, TWEA);
|
|
||||||
//outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
|
|
||||||
// enable interrupts
|
|
||||||
sei();
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2cSetBitrate(u16 bitrateKHz)
|
|
||||||
{
|
|
||||||
u08 bitrate_div;
|
|
||||||
// set i2c bitrate
|
|
||||||
// SCL freq = F_CPU/(16+2*TWBR))
|
|
||||||
#ifdef TWPS0
|
|
||||||
// for processors with additional bitrate division (mega128)
|
|
||||||
// SCL freq = F_CPU/(16+2*TWBR*4^TWPS)
|
|
||||||
// set TWPS to zero
|
|
||||||
cbi(TWSR, TWPS0);
|
|
||||||
cbi(TWSR, TWPS1);
|
|
||||||
#endif
|
|
||||||
// calculate bitrate division
|
|
||||||
bitrate_div = ((F_CPU/1000l)/bitrateKHz);
|
|
||||||
if(bitrate_div >= 16)
|
|
||||||
bitrate_div = (bitrate_div-16)/2;
|
|
||||||
outb(TWBR, bitrate_div);
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2cSetLocalDeviceAddr(u08 deviceAddr, u08 genCallEn)
|
|
||||||
{
|
|
||||||
// set local device address (used in slave mode only)
|
|
||||||
outb(TWAR, ((deviceAddr&0xFE) | (genCallEn?1:0)) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2cSetSlaveReceiveHandler(void (*i2cSlaveRx_func)(u08 receiveDataLength, u08* recieveData))
|
|
||||||
{
|
|
||||||
i2cSlaveReceive = i2cSlaveRx_func;
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2cSetSlaveTransmitHandler(u08 (*i2cSlaveTx_func)(u08 transmitDataLengthMax, u08* transmitData))
|
|
||||||
{
|
|
||||||
i2cSlaveTransmit = i2cSlaveTx_func;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void i2cSendStart(void)
|
|
||||||
{
|
|
||||||
// send start condition
|
|
||||||
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void i2cSendStop(void)
|
|
||||||
{
|
|
||||||
// transmit stop condition
|
|
||||||
// leave with TWEA on for slave receiving
|
|
||||||
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA)|BV(TWSTO));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void i2cWaitForComplete(void)
|
|
||||||
{
|
|
||||||
// wait for i2c interface to complete operation
|
|
||||||
while( !(inb(TWCR) & BV(TWINT)) );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void i2cSendByte(u08 data)
|
|
||||||
{
|
|
||||||
// save data to the TWDR
|
|
||||||
outb(TWDR, data);
|
|
||||||
// begin send
|
|
||||||
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void i2cReceiveByte(u08 ackFlag)
|
|
||||||
{
|
|
||||||
// begin receive over i2c
|
|
||||||
if( ackFlag )
|
|
||||||
{
|
|
||||||
// ackFlag = TRUE: ACK the recevied data
|
|
||||||
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// ackFlag = FALSE: NACK the recevied data
|
|
||||||
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u08 i2cGetReceivedByte(void)
|
|
||||||
{
|
|
||||||
// retieve received data byte from i2c TWDR
|
|
||||||
return( inb(TWDR) );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u08 i2cGetStatus(void)
|
|
||||||
{
|
|
||||||
// retieve current i2c status from i2c TWSR
|
|
||||||
return( inb(TWSR) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2cMasterSend(u08 deviceAddr, u08 length, u08* data)
|
|
||||||
{
|
|
||||||
u08 i;
|
|
||||||
// wait for interface to be ready
|
|
||||||
while(I2cState);
|
|
||||||
// set state
|
|
||||||
I2cState = I2C_MASTER_TX;
|
|
||||||
// save data
|
|
||||||
I2cDeviceAddrRW = (deviceAddr & 0xFE); // RW cleared: write operation
|
|
||||||
for(i=0; i<length; i++)
|
|
||||||
I2cSendData[i] = *data++;
|
|
||||||
I2cSendDataIndex = 0;
|
|
||||||
I2cSendDataLength = length;
|
|
||||||
// send start condition
|
|
||||||
i2cSendStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2cMasterReceive(u08 deviceAddr, u08 length, u08* data)
|
|
||||||
{
|
|
||||||
u08 i;
|
|
||||||
// wait for interface to be ready
|
|
||||||
while(I2cState);
|
|
||||||
// set state
|
|
||||||
I2cState = I2C_MASTER_RX;
|
|
||||||
// save data
|
|
||||||
I2cDeviceAddrRW = (deviceAddr|0x01); // RW set: read operation
|
|
||||||
I2cReceiveDataIndex = 0;
|
|
||||||
I2cReceiveDataLength = length;
|
|
||||||
// send start condition
|
|
||||||
i2cSendStart();
|
|
||||||
// wait for data
|
|
||||||
while(I2cState);
|
|
||||||
// return data
|
|
||||||
for(i=0; i<length; i++)
|
|
||||||
*data++ = I2cReceiveData[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 i2cMasterSendNI(u08 deviceAddr, u08 length, u08* data)
|
|
||||||
{
|
|
||||||
u08 retval = I2C_OK;
|
|
||||||
|
|
||||||
// disable TWI interrupt
|
|
||||||
cbi(TWCR, TWIE);
|
|
||||||
|
|
||||||
// send start condition
|
|
||||||
i2cSendStart();
|
|
||||||
i2cWaitForComplete();
|
|
||||||
|
|
||||||
// send device address with write
|
|
||||||
i2cSendByte( deviceAddr & 0xFE );
|
|
||||||
i2cWaitForComplete();
|
|
||||||
|
|
||||||
// check if device is present and live
|
|
||||||
if( inb(TWSR) == TW_MT_SLA_ACK)
|
|
||||||
{
|
|
||||||
// send data
|
|
||||||
while(length)
|
|
||||||
{
|
|
||||||
i2cSendByte( *data++ );
|
|
||||||
i2cWaitForComplete();
|
|
||||||
length--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// device did not ACK it's address,
|
|
||||||
// data will not be transferred
|
|
||||||
// return error
|
|
||||||
retval = I2C_ERROR_NODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
// transmit stop condition
|
|
||||||
// leave with TWEA on for slave receiving
|
|
||||||
i2cSendStop();
|
|
||||||
while( !(inb(TWCR) & BV(TWSTO)) );
|
|
||||||
|
|
||||||
// enable TWI interrupt
|
|
||||||
sbi(TWCR, TWIE);
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 i2cMasterReceiveNI(u08 deviceAddr, u08 length, u08 *data)
|
|
||||||
{
|
|
||||||
u08 retval = I2C_OK;
|
|
||||||
|
|
||||||
// disable TWI interrupt
|
|
||||||
cbi(TWCR, TWIE);
|
|
||||||
|
|
||||||
// send start condition
|
|
||||||
i2cSendStart();
|
|
||||||
i2cWaitForComplete();
|
|
||||||
|
|
||||||
// send device address with read
|
|
||||||
i2cSendByte( deviceAddr | 0x01 );
|
|
||||||
i2cWaitForComplete();
|
|
||||||
|
|
||||||
// check if device is present and live
|
|
||||||
if( inb(TWSR) == TW_MR_SLA_ACK)
|
|
||||||
{
|
|
||||||
// accept receive data and ack it
|
|
||||||
while(length > 1)
|
|
||||||
{
|
|
||||||
i2cReceiveByte(TRUE);
|
|
||||||
i2cWaitForComplete();
|
|
||||||
*data++ = i2cGetReceivedByte();
|
|
||||||
// decrement length
|
|
||||||
length--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// accept receive data and nack it (last-byte signal)
|
|
||||||
i2cReceiveByte(FALSE);
|
|
||||||
i2cWaitForComplete();
|
|
||||||
*data++ = i2cGetReceivedByte();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// device did not ACK it's address,
|
|
||||||
// data will not be transferred
|
|
||||||
// return error
|
|
||||||
retval = I2C_ERROR_NODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
// transmit stop condition
|
|
||||||
// leave with TWEA on for slave receiving
|
|
||||||
i2cSendStop();
|
|
||||||
|
|
||||||
// enable TWI interrupt
|
|
||||||
sbi(TWCR, TWIE);
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
void i2cMasterTransferNI(u08 deviceAddr, u08 sendlength, u08* senddata, u08 receivelength, u08* receivedata)
|
|
||||||
{
|
|
||||||
// disable TWI interrupt
|
|
||||||
cbi(TWCR, TWIE);
|
|
||||||
|
|
||||||
// send start condition
|
|
||||||
i2cSendStart();
|
|
||||||
i2cWaitForComplete();
|
|
||||||
|
|
||||||
// if there's data to be sent, do it
|
|
||||||
if(sendlength)
|
|
||||||
{
|
|
||||||
// send device address with write
|
|
||||||
i2cSendByte( deviceAddr & 0xFE );
|
|
||||||
i2cWaitForComplete();
|
|
||||||
|
|
||||||
// send data
|
|
||||||
while(sendlength)
|
|
||||||
{
|
|
||||||
i2cSendByte( *senddata++ );
|
|
||||||
i2cWaitForComplete();
|
|
||||||
sendlength--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there's data to be received, do it
|
|
||||||
if(receivelength)
|
|
||||||
{
|
|
||||||
// send repeated start condition
|
|
||||||
i2cSendStart();
|
|
||||||
i2cWaitForComplete();
|
|
||||||
|
|
||||||
// send device address with read
|
|
||||||
i2cSendByte( deviceAddr | 0x01 );
|
|
||||||
i2cWaitForComplete();
|
|
||||||
|
|
||||||
// accept receive data and ack it
|
|
||||||
while(receivelength > 1)
|
|
||||||
{
|
|
||||||
i2cReceiveByte(TRUE);
|
|
||||||
i2cWaitForComplete();
|
|
||||||
*receivedata++ = i2cGetReceivedByte();
|
|
||||||
// decrement length
|
|
||||||
receivelength--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// accept receive data and nack it (last-byte signal)
|
|
||||||
i2cReceiveByte(TRUE);
|
|
||||||
i2cWaitForComplete();
|
|
||||||
*receivedata++ = i2cGetReceivedByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
// transmit stop condition
|
|
||||||
// leave with TWEA on for slave receiving
|
|
||||||
i2cSendStop();
|
|
||||||
while( !(inb(TWCR) & BV(TWSTO)) );
|
|
||||||
|
|
||||||
// enable TWI interrupt
|
|
||||||
sbi(TWCR, TWIE);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
//! I2C (TWI) interrupt service routine
|
|
||||||
SIGNAL(SIG_2WIRE_SERIAL)
|
|
||||||
{
|
|
||||||
// read status bits
|
|
||||||
u08 status = inb(TWSR) & TWSR_STATUS_MASK;
|
|
||||||
|
|
||||||
switch(status)
|
|
||||||
{
|
|
||||||
// Master General
|
|
||||||
case TW_START: // 0x08: Sent start condition
|
|
||||||
case TW_REP_START: // 0x10: Sent repeated start condition
|
|
||||||
#ifdef I2C_DEBUG
|
|
||||||
rprintfInit(uart1AddToTxBuffer);
|
|
||||||
rprintf("I2C: M->START\r\n");
|
|
||||||
rprintfInit(uart1SendByte);
|
|
||||||
#endif
|
|
||||||
// send device address
|
|
||||||
i2cSendByte(I2cDeviceAddrRW);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Master Transmitter & Receiver status codes
|
|
||||||
case TW_MT_SLA_ACK: // 0x18: Slave address acknowledged
|
|
||||||
case TW_MT_DATA_ACK: // 0x28: Data acknowledged
|
|
||||||
#ifdef I2C_DEBUG
|
|
||||||
rprintfInit(uart1AddToTxBuffer);
|
|
||||||
rprintf("I2C: MT->SLA_ACK or DATA_ACK\r\n");
|
|
||||||
rprintfInit(uart1SendByte);
|
|
||||||
#endif
|
|
||||||
if(I2cSendDataIndex < I2cSendDataLength)
|
|
||||||
{
|
|
||||||
// send data
|
|
||||||
i2cSendByte( I2cSendData[I2cSendDataIndex++] );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// transmit stop condition, enable SLA ACK
|
|
||||||
i2cSendStop();
|
|
||||||
// set state
|
|
||||||
I2cState = I2C_IDLE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TW_MR_DATA_NACK: // 0x58: Data received, NACK reply issued
|
|
||||||
#ifdef I2C_DEBUG
|
|
||||||
rprintfInit(uart1AddToTxBuffer);
|
|
||||||
rprintf("I2C: MR->DATA_NACK\r\n");
|
|
||||||
rprintfInit(uart1SendByte);
|
|
||||||
#endif
|
|
||||||
// store final received data byte
|
|
||||||
I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR);
|
|
||||||
// continue to transmit STOP condition
|
|
||||||
case TW_MR_SLA_NACK: // 0x48: Slave address not acknowledged
|
|
||||||
case TW_MT_SLA_NACK: // 0x20: Slave address not acknowledged
|
|
||||||
case TW_MT_DATA_NACK: // 0x30: Data not acknowledged
|
|
||||||
#ifdef I2C_DEBUG
|
|
||||||
rprintfInit(uart1AddToTxBuffer);
|
|
||||||
rprintf("I2C: MTR->SLA_NACK or MT->DATA_NACK\r\n");
|
|
||||||
rprintfInit(uart1SendByte);
|
|
||||||
#endif
|
|
||||||
// transmit stop condition, enable SLA ACK
|
|
||||||
i2cSendStop();
|
|
||||||
// set state
|
|
||||||
I2cState = I2C_IDLE;
|
|
||||||
break;
|
|
||||||
case TW_MT_ARB_LOST: // 0x38: Bus arbitration lost
|
|
||||||
//case TW_MR_ARB_LOST: // 0x38: Bus arbitration lost
|
|
||||||
#ifdef I2C_DEBUG
|
|
||||||
rprintfInit(uart1AddToTxBuffer);
|
|
||||||
rprintf("I2C: MT->ARB_LOST\r\n");
|
|
||||||
rprintfInit(uart1SendByte);
|
|
||||||
#endif
|
|
||||||
// release bus
|
|
||||||
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
|
|
||||||
// set state
|
|
||||||
I2cState = I2C_IDLE;
|
|
||||||
// release bus and transmit start when bus is free
|
|
||||||
//outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA));
|
|
||||||
break;
|
|
||||||
case TW_MR_DATA_ACK: // 0x50: Data acknowledged
|
|
||||||
#ifdef I2C_DEBUG
|
|
||||||
rprintfInit(uart1AddToTxBuffer);
|
|
||||||
rprintf("I2C: MR->DATA_ACK\r\n");
|
|
||||||
rprintfInit(uart1SendByte);
|
|
||||||
#endif
|
|
||||||
// store received data byte
|
|
||||||
I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR);
|
|
||||||
// fall-through to see if more bytes will be received
|
|
||||||
case TW_MR_SLA_ACK: // 0x40: Slave address acknowledged
|
|
||||||
#ifdef I2C_DEBUG
|
|
||||||
rprintfInit(uart1AddToTxBuffer);
|
|
||||||
rprintf("I2C: MR->SLA_ACK\r\n");
|
|
||||||
rprintfInit(uart1SendByte);
|
|
||||||
#endif
|
|
||||||
if(I2cReceiveDataIndex < (I2cReceiveDataLength-1))
|
|
||||||
// data byte will be received, reply with ACK (more bytes in transfer)
|
|
||||||
i2cReceiveByte(TRUE);
|
|
||||||
else
|
|
||||||
// data byte will be received, reply with NACK (final byte in transfer)
|
|
||||||
i2cReceiveByte(FALSE);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Slave Receiver status codes
|
|
||||||
case TW_SR_SLA_ACK: // 0x60: own SLA+W has been received, ACK has been returned
|
|
||||||
case TW_SR_ARB_LOST_SLA_ACK: // 0x68: own SLA+W has been received, ACK has been returned
|
|
||||||
case TW_SR_GCALL_ACK: // 0x70: GCA+W has been received, ACK has been returned
|
|
||||||
case TW_SR_ARB_LOST_GCALL_ACK: // 0x78: GCA+W has been received, ACK has been returned
|
|
||||||
#ifdef I2C_DEBUG
|
|
||||||
rprintfInit(uart1AddToTxBuffer);
|
|
||||||
rprintf("I2C: SR->SLA_ACK\r\n");
|
|
||||||
rprintfInit(uart1SendByte);
|
|
||||||
#endif
|
|
||||||
// we are being addressed as slave for writing (data will be received from master)
|
|
||||||
// set state
|
|
||||||
I2cState = I2C_SLAVE_RX;
|
|
||||||
// prepare buffer
|
|
||||||
I2cReceiveDataIndex = 0;
|
|
||||||
// receive data byte and return ACK
|
|
||||||
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
|
|
||||||
break;
|
|
||||||
case TW_SR_DATA_ACK: // 0x80: data byte has been received, ACK has been returned
|
|
||||||
case TW_SR_GCALL_DATA_ACK: // 0x90: data byte has been received, ACK has been returned
|
|
||||||
#ifdef I2C_DEBUG
|
|
||||||
rprintfInit(uart1AddToTxBuffer);
|
|
||||||
rprintf("I2C: SR->DATA_ACK\r\n");
|
|
||||||
rprintfInit(uart1SendByte);
|
|
||||||
#endif
|
|
||||||
// get previously received data byte
|
|
||||||
I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR);
|
|
||||||
// check receive buffer status
|
|
||||||
if(I2cReceiveDataIndex < I2C_RECEIVE_DATA_BUFFER_SIZE)
|
|
||||||
{
|
|
||||||
// receive data byte and return ACK
|
|
||||||
i2cReceiveByte(TRUE);
|
|
||||||
//outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// receive data byte and return NACK
|
|
||||||
i2cReceiveByte(FALSE);
|
|
||||||
//outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TW_SR_DATA_NACK: // 0x88: data byte has been received, NACK has been returned
|
|
||||||
case TW_SR_GCALL_DATA_NACK: // 0x98: data byte has been received, NACK has been returned
|
|
||||||
#ifdef I2C_DEBUG
|
|
||||||
rprintfInit(uart1AddToTxBuffer);
|
|
||||||
rprintf("I2C: SR->DATA_NACK\r\n");
|
|
||||||
rprintfInit(uart1SendByte);
|
|
||||||
#endif
|
|
||||||
// receive data byte and return NACK
|
|
||||||
i2cReceiveByte(FALSE);
|
|
||||||
//outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
|
|
||||||
break;
|
|
||||||
case TW_SR_STOP: // 0xA0: STOP or REPEATED START has been received while addressed as slave
|
|
||||||
#ifdef I2C_DEBUG
|
|
||||||
rprintfInit(uart1AddToTxBuffer);
|
|
||||||
rprintf("I2C: SR->SR_STOP\r\n");
|
|
||||||
rprintfInit(uart1SendByte);
|
|
||||||
#endif
|
|
||||||
// switch to SR mode with SLA ACK
|
|
||||||
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
|
|
||||||
// i2c receive is complete, call i2cSlaveReceive
|
|
||||||
if(i2cSlaveReceive) i2cSlaveReceive(I2cReceiveDataIndex, I2cReceiveData);
|
|
||||||
// set state
|
|
||||||
I2cState = I2C_IDLE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Slave Transmitter
|
|
||||||
case TW_ST_SLA_ACK: // 0xA8: own SLA+R has been received, ACK has been returned
|
|
||||||
case TW_ST_ARB_LOST_SLA_ACK: // 0xB0: GCA+R has been received, ACK has been returned
|
|
||||||
#ifdef I2C_DEBUG
|
|
||||||
rprintfInit(uart1AddToTxBuffer);
|
|
||||||
rprintf("I2C: ST->SLA_ACK\r\n");
|
|
||||||
rprintfInit(uart1SendByte);
|
|
||||||
#endif
|
|
||||||
// we are being addressed as slave for reading (data must be transmitted back to master)
|
|
||||||
// set state
|
|
||||||
I2cState = I2C_SLAVE_TX;
|
|
||||||
// request data from application
|
|
||||||
if(i2cSlaveTransmit) I2cSendDataLength = i2cSlaveTransmit(I2C_SEND_DATA_BUFFER_SIZE, I2cSendData);
|
|
||||||
// reset data index
|
|
||||||
I2cSendDataIndex = 0;
|
|
||||||
// fall-through to transmit first data byte
|
|
||||||
case TW_ST_DATA_ACK: // 0xB8: data byte has been transmitted, ACK has been received
|
|
||||||
#ifdef I2C_DEBUG
|
|
||||||
rprintfInit(uart1AddToTxBuffer);
|
|
||||||
rprintf("I2C: ST->DATA_ACK\r\n");
|
|
||||||
rprintfInit(uart1SendByte);
|
|
||||||
#endif
|
|
||||||
// transmit data byte
|
|
||||||
outb(TWDR, I2cSendData[I2cSendDataIndex++]);
|
|
||||||
if(I2cSendDataIndex < I2cSendDataLength)
|
|
||||||
// expect ACK to data byte
|
|
||||||
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
|
|
||||||
else
|
|
||||||
// expect NACK to data byte
|
|
||||||
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
|
|
||||||
break;
|
|
||||||
case TW_ST_DATA_NACK: // 0xC0: data byte has been transmitted, NACK has been received
|
|
||||||
case TW_ST_LAST_DATA: // 0xC8:
|
|
||||||
#ifdef I2C_DEBUG
|
|
||||||
rprintfInit(uart1AddToTxBuffer);
|
|
||||||
rprintf("I2C: ST->DATA_NACK or LAST_DATA\r\n");
|
|
||||||
rprintfInit(uart1SendByte);
|
|
||||||
#endif
|
|
||||||
// all done
|
|
||||||
// switch to open slave
|
|
||||||
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
|
|
||||||
// set state
|
|
||||||
I2cState = I2C_IDLE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Misc
|
|
||||||
case TW_NO_INFO: // 0xF8: No relevant state information
|
|
||||||
// do nothing
|
|
||||||
#ifdef I2C_DEBUG
|
|
||||||
rprintfInit(uart1AddToTxBuffer);
|
|
||||||
rprintf("I2C: NO_INFO\r\n");
|
|
||||||
rprintfInit(uart1SendByte);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case TW_BUS_ERROR: // 0x00: Bus error due to illegal start or stop condition
|
|
||||||
#ifdef I2C_DEBUG
|
|
||||||
rprintfInit(uart1AddToTxBuffer);
|
|
||||||
rprintf("I2C: BUS_ERROR\r\n");
|
|
||||||
rprintfInit(uart1SendByte);
|
|
||||||
#endif
|
|
||||||
// reset internal hardware and release bus
|
|
||||||
outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTO)|BV(TWEA));
|
|
||||||
// set state
|
|
||||||
I2cState = I2C_IDLE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eI2cStateType i2cGetState(void)
|
|
||||||
{
|
|
||||||
return I2cState;
|
|
||||||
}
|
|
@ -1,129 +0,0 @@
|
|||||||
/*! \file i2c.h \brief I2C interface using AVR Two-Wire Interface (TWI) hardware. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'i2c.h'
|
|
||||||
// Title : I2C interface using AVR Two-Wire Interface (TWI) hardware
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002-2003
|
|
||||||
// Created : 2002.06.25
|
|
||||||
// Revised : 2003.03.03
|
|
||||||
// Version : 0.9
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef I2C_H
|
|
||||||
#define I2C_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
// include project-specific configuration
|
|
||||||
#include "i2cconf.h"
|
|
||||||
|
|
||||||
// TWSR values (not bits)
|
|
||||||
// (taken from avr-libc twi.h - thank you Marek Michalkiewicz)
|
|
||||||
// Master
|
|
||||||
#define TW_START 0x08
|
|
||||||
#define TW_REP_START 0x10
|
|
||||||
// Master Transmitter
|
|
||||||
#define TW_MT_SLA_ACK 0x18
|
|
||||||
#define TW_MT_SLA_NACK 0x20
|
|
||||||
#define TW_MT_DATA_ACK 0x28
|
|
||||||
#define TW_MT_DATA_NACK 0x30
|
|
||||||
#define TW_MT_ARB_LOST 0x38
|
|
||||||
// Master Receiver
|
|
||||||
#define TW_MR_ARB_LOST 0x38
|
|
||||||
#define TW_MR_SLA_ACK 0x40
|
|
||||||
#define TW_MR_SLA_NACK 0x48
|
|
||||||
#define TW_MR_DATA_ACK 0x50
|
|
||||||
#define TW_MR_DATA_NACK 0x58
|
|
||||||
// Slave Transmitter
|
|
||||||
#define TW_ST_SLA_ACK 0xA8
|
|
||||||
#define TW_ST_ARB_LOST_SLA_ACK 0xB0
|
|
||||||
#define TW_ST_DATA_ACK 0xB8
|
|
||||||
#define TW_ST_DATA_NACK 0xC0
|
|
||||||
#define TW_ST_LAST_DATA 0xC8
|
|
||||||
// Slave Receiver
|
|
||||||
#define TW_SR_SLA_ACK 0x60
|
|
||||||
#define TW_SR_ARB_LOST_SLA_ACK 0x68
|
|
||||||
#define TW_SR_GCALL_ACK 0x70
|
|
||||||
#define TW_SR_ARB_LOST_GCALL_ACK 0x78
|
|
||||||
#define TW_SR_DATA_ACK 0x80
|
|
||||||
#define TW_SR_DATA_NACK 0x88
|
|
||||||
#define TW_SR_GCALL_DATA_ACK 0x90
|
|
||||||
#define TW_SR_GCALL_DATA_NACK 0x98
|
|
||||||
#define TW_SR_STOP 0xA0
|
|
||||||
// Misc
|
|
||||||
#define TW_NO_INFO 0xF8
|
|
||||||
#define TW_BUS_ERROR 0x00
|
|
||||||
|
|
||||||
// defines and constants
|
|
||||||
#define TWCR_CMD_MASK 0x0F
|
|
||||||
#define TWSR_STATUS_MASK 0xF8
|
|
||||||
|
|
||||||
// return values
|
|
||||||
#define I2C_OK 0x00
|
|
||||||
#define I2C_ERROR_NODEV 0x01
|
|
||||||
|
|
||||||
// types
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
I2C_IDLE = 0, I2C_BUSY = 1,
|
|
||||||
I2C_MASTER_TX = 2, I2C_MASTER_RX = 3,
|
|
||||||
I2C_SLAVE_TX = 4, I2C_SLAVE_RX = 5
|
|
||||||
} eI2cStateType;
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
//! Initialize I2C (TWI) interface
|
|
||||||
void i2cInit(void);
|
|
||||||
|
|
||||||
//! Set the I2C transaction bitrate (in KHz)
|
|
||||||
void i2cSetBitrate(u16 bitrateKHz);
|
|
||||||
|
|
||||||
// I2C setup and configurations commands
|
|
||||||
//! Set the local (AVR processor's) I2C device address
|
|
||||||
void i2cSetLocalDeviceAddr(u08 deviceAddr, u08 genCallEn);
|
|
||||||
|
|
||||||
//! Set the user function which handles receiving (incoming) data as a slave
|
|
||||||
void i2cSetSlaveReceiveHandler(void (*i2cSlaveRx_func)(u08 receiveDataLength, u08* recieveData));
|
|
||||||
//! Set the user function which handles transmitting (outgoing) data as a slave
|
|
||||||
void i2cSetSlaveTransmitHandler(u08 (*i2cSlaveTx_func)(u08 transmitDataLengthMax, u08* transmitData));
|
|
||||||
|
|
||||||
// Low-level I2C transaction commands
|
|
||||||
//! Send an I2C start condition in Master mode
|
|
||||||
void i2cSendStart(void);
|
|
||||||
//! Send an I2C stop condition in Master mode
|
|
||||||
void i2cSendStop(void);
|
|
||||||
//! Wait for current I2C operation to complete
|
|
||||||
void i2cWaitForComplete(void);
|
|
||||||
//! Send an (address|R/W) combination or a data byte over I2C
|
|
||||||
void i2cSendByte(u08 data);
|
|
||||||
//! Receive a data byte over I2C
|
|
||||||
// ackFlag = TRUE if recevied data should be ACK'ed
|
|
||||||
// ackFlag = FALSE if recevied data should be NACK'ed
|
|
||||||
void i2cReceiveByte(u08 ackFlag);
|
|
||||||
//! Pick up the data that was received with i2cReceiveByte()
|
|
||||||
u08 i2cGetReceivedByte(void);
|
|
||||||
//! Get current I2c bus status from TWSR
|
|
||||||
u08 i2cGetStatus(void);
|
|
||||||
|
|
||||||
// high-level I2C transaction commands
|
|
||||||
|
|
||||||
//! send I2C data to a device on the bus
|
|
||||||
void i2cMasterSend(u08 deviceAddr, u08 length, u08 *data);
|
|
||||||
//! receive I2C data from a device on the bus
|
|
||||||
void i2cMasterReceive(u08 deviceAddr, u08 length, u08* data);
|
|
||||||
|
|
||||||
//! send I2C data to a device on the bus (non-interrupt based)
|
|
||||||
u08 i2cMasterSendNI(u08 deviceAddr, u08 length, u08* data);
|
|
||||||
//! receive I2C data from a device on the bus (non-interrupt based)
|
|
||||||
u08 i2cMasterReceiveNI(u08 deviceAddr, u08 length, u08 *data);
|
|
||||||
|
|
||||||
//! Get the current high-level state of the I2C interface
|
|
||||||
eI2cStateType i2cGetState(void);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,60 +0,0 @@
|
|||||||
/*! \file i2ceeprom.c \brief Interface for standard I2C EEPROM memories. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'i2ceeprom.c'
|
|
||||||
// Title : Interface for standard I2C EEPROM memories
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2003
|
|
||||||
// Created : 2003.04.23
|
|
||||||
// Revised : 2003.04.23
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/signal.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
#include "i2c.h"
|
|
||||||
#include "i2ceeprom.h"
|
|
||||||
|
|
||||||
// Standard I2C bit rates are:
|
|
||||||
// 100KHz for slow speed
|
|
||||||
// 400KHz for high speed
|
|
||||||
|
|
||||||
// functions
|
|
||||||
void i2ceepromInit(void)
|
|
||||||
{
|
|
||||||
// although there is no code here
|
|
||||||
// don't forget to initialize the I2C interface itself
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 i2ceepromReadByte(u08 i2cAddr, u32 memAddr)
|
|
||||||
{
|
|
||||||
u08 packet[2];
|
|
||||||
// prepare address
|
|
||||||
packet[0] = (memAddr>>8);
|
|
||||||
packet[1] = (memAddr&0x00FF);
|
|
||||||
// send memory address we wish to access to the memory chip
|
|
||||||
i2cMasterSendNI(i2cAddr, 2, packet);
|
|
||||||
// retrieve the data at this memory address
|
|
||||||
i2cMasterReceiveNI(i2cAddr, 1, packet);
|
|
||||||
// return data
|
|
||||||
return packet[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2ceepromWriteByte(u08 i2cAddr, u32 memAddr, u08 data)
|
|
||||||
{
|
|
||||||
u08 packet[3];
|
|
||||||
// prepare address + data
|
|
||||||
packet[0] = (memAddr>>8);
|
|
||||||
packet[1] = (memAddr&0x00FF);
|
|
||||||
packet[2] = data;
|
|
||||||
// send memory address we wish to access to the memory chip
|
|
||||||
// along with the data we wish to write
|
|
||||||
i2cMasterSendNI(i2cAddr, 3, packet);
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
/*! \file i2ceeprom.h \brief Interface for standard I2C EEPROM memories. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'i2ceeprom.h'
|
|
||||||
// Title : Interface for standard I2C EEPROM memories
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2003
|
|
||||||
// Created : 2003.04.23
|
|
||||||
// Revised : 2003.04.23
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef I2CEEPROM_H
|
|
||||||
#define I2CEEPROM_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
//! Initialize I2C EEPROM interface
|
|
||||||
void i2ceepromInit(void);
|
|
||||||
|
|
||||||
//! In the I2C EEPROM at [i2cAddr], read a byte from memory location [memAddr]
|
|
||||||
u08 i2ceepromReadByte(u08 i2cAddr, u32 memAddr);
|
|
||||||
|
|
||||||
//! In the I2C EEPROM at [i2cAddr], write a byte [data] to the memory location [memAddr]
|
|
||||||
void i2ceepromWriteByte(u08 i2cAddr, u32 memAddr, u08 data);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,176 +0,0 @@
|
|||||||
/*! \file i2csw.c \brief Software-driven I2C interface using port pins. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'i2csw.c'
|
|
||||||
// Title : Software-driven I2C interface using port pins
|
|
||||||
// Author : Pascal Stang
|
|
||||||
// Created : 11/22/2000
|
|
||||||
// Revised : 5/2/2002
|
|
||||||
// Version : 1.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
|
|
||||||
#include "i2csw.h"
|
|
||||||
|
|
||||||
// Standard I2C bit rates are:
|
|
||||||
// 100KHz for slow speed
|
|
||||||
// 400KHz for high speed
|
|
||||||
|
|
||||||
//#define QDEL delay(5) // i2c quarter-bit delay
|
|
||||||
//#define HDEL delay(10) // i2c half-bit delay
|
|
||||||
|
|
||||||
// i2c quarter-bit delay
|
|
||||||
#define QDEL asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop");
|
|
||||||
// i2c half-bit delay
|
|
||||||
#define HDEL asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop");
|
|
||||||
|
|
||||||
#define I2C_SDL_LO cbi( SDAPORT, SDA)
|
|
||||||
#define I2C_SDL_HI sbi( SDAPORT, SDA)
|
|
||||||
|
|
||||||
#define I2C_SCL_LO cbi( SCLPORT, SCL);
|
|
||||||
#define I2C_SCL_HI sbi( SCLPORT, SCL);
|
|
||||||
|
|
||||||
#define I2C_SCL_TOGGLE HDEL; I2C_SCL_HI; HDEL; I2C_SCL_LO;
|
|
||||||
#define I2C_START I2C_SDL_LO; QDEL; I2C_SCL_LO;
|
|
||||||
#define I2C_STOP HDEL; I2C_SCL_HI; QDEL; I2C_SDL_HI; HDEL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
void i2ct(void)
|
|
||||||
{
|
|
||||||
HDEL; I2C_SCL_HI; HDEL; I2C_SCL_LO;
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2cstart(void)
|
|
||||||
{
|
|
||||||
I2C_SDL_LO; QDEL; I2C_SCL_LO;
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2cstop(void)
|
|
||||||
{
|
|
||||||
HDEL; I2C_SCL_HI; QDEL; I2C_SDL_HI; HDEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define I2C_SCL_TOGGLE i2ct();
|
|
||||||
#define I2C_START i2cstart();
|
|
||||||
#define I2C_STOP i2cstop();
|
|
||||||
*/
|
|
||||||
|
|
||||||
UINT i2cPutbyte(u08 b)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i=7;i>=0;i--)
|
|
||||||
{
|
|
||||||
if ( b & (1<<i) )
|
|
||||||
I2C_SDL_HI;
|
|
||||||
else
|
|
||||||
I2C_SDL_LO; // address bit
|
|
||||||
I2C_SCL_TOGGLE; // clock HI, delay, then LO
|
|
||||||
}
|
|
||||||
|
|
||||||
I2C_SDL_HI; // leave SDL HI
|
|
||||||
// added
|
|
||||||
cbi(SDADDR, SDA); // change direction to input on SDA line (may not be needed)
|
|
||||||
HDEL;
|
|
||||||
I2C_SCL_HI; // clock back up
|
|
||||||
b = inb(SDAPIN) & (1<<SDA); // get the ACK bit
|
|
||||||
|
|
||||||
HDEL;
|
|
||||||
I2C_SCL_LO; // not really ??
|
|
||||||
sbi(SDADDR, SDA); // change direction back to output
|
|
||||||
HDEL;
|
|
||||||
return (b == 0); // return ACK value
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
u08 i2cGetbyte(UINT last)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
u08 c,b = 0;
|
|
||||||
|
|
||||||
I2C_SDL_HI; // make sure pullups are ativated
|
|
||||||
cbi(SDADDR, SDA); // change direction to input on SDA line (may not be needed)
|
|
||||||
|
|
||||||
for(i=7;i>=0;i--)
|
|
||||||
{
|
|
||||||
HDEL;
|
|
||||||
I2C_SCL_HI; // clock HI
|
|
||||||
c = inb(SDAPIN) & (1<<SDA);
|
|
||||||
b <<= 1;
|
|
||||||
if(c) b |= 1;
|
|
||||||
HDEL;
|
|
||||||
I2C_SCL_LO; // clock LO
|
|
||||||
}
|
|
||||||
|
|
||||||
sbi(SDADDR, SDA); // change direction to output on SDA line
|
|
||||||
|
|
||||||
if (last)
|
|
||||||
I2C_SDL_HI; // set NAK
|
|
||||||
else
|
|
||||||
I2C_SDL_LO; // set ACK
|
|
||||||
|
|
||||||
I2C_SCL_TOGGLE; // clock pulse
|
|
||||||
I2C_SDL_HI; // leave with SDL HI
|
|
||||||
return b; // return received byte
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//************************
|
|
||||||
//* I2C public functions *
|
|
||||||
//************************
|
|
||||||
|
|
||||||
//! Initialize I2C communication
|
|
||||||
void i2cInit(void)
|
|
||||||
{
|
|
||||||
sbi( SDADDR, SDA); // set SDA as output
|
|
||||||
sbi( SCLDDR, SCL); // set SCL as output
|
|
||||||
I2C_SDL_HI; // set I/O state and pull-ups
|
|
||||||
I2C_SCL_HI; // set I/O state and pull-ups
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Send a byte sequence on the I2C bus
|
|
||||||
void i2cSend(u08 device, u08 subAddr, u08 length, u08 *data)
|
|
||||||
{
|
|
||||||
I2C_START; // do start transition
|
|
||||||
i2cPutbyte(device); // send DEVICE address
|
|
||||||
i2cPutbyte(subAddr); // and the subaddress
|
|
||||||
|
|
||||||
// send the data
|
|
||||||
while (length--)
|
|
||||||
i2cPutbyte(*data++);
|
|
||||||
|
|
||||||
I2C_SDL_LO; // clear data line and
|
|
||||||
I2C_STOP; // send STOP transition
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Retrieve a byte sequence on the I2C bus
|
|
||||||
void i2cReceive(u08 device, u08 subAddr, u08 length, u08 *data)
|
|
||||||
{
|
|
||||||
int j = length;
|
|
||||||
u08 *p = data;
|
|
||||||
|
|
||||||
I2C_START; // do start transition
|
|
||||||
i2cPutbyte(device); // send DEVICE address
|
|
||||||
i2cPutbyte(subAddr); // and the subaddress
|
|
||||||
HDEL;
|
|
||||||
I2C_SCL_HI; // do a repeated START
|
|
||||||
I2C_START; // transition
|
|
||||||
|
|
||||||
i2cPutbyte(device | READ); // resend DEVICE, with READ bit set
|
|
||||||
|
|
||||||
// receive data bytes
|
|
||||||
while (j--)
|
|
||||||
*p++ = i2cGetbyte(j == 0);
|
|
||||||
|
|
||||||
I2C_SDL_LO; // clear data line and
|
|
||||||
I2C_STOP; // send STOP transition
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
|||||||
/*! \file i2csw.h \brief software-driven I2C interface using port pins. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'i2csw.h'
|
|
||||||
// Title : software-driven I2C interface using port pins
|
|
||||||
// Author : Pascal Stang
|
|
||||||
// Created : 11/22/2000
|
|
||||||
// Revised : 5/2/2002
|
|
||||||
// Version : 1.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef I2CSW_H
|
|
||||||
#define I2CSW_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
// include project-dependent settings
|
|
||||||
#include "i2cswconf.h"
|
|
||||||
|
|
||||||
// defines and constants
|
|
||||||
#define READ 0x01 // I2C READ bit
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
// initialize I2C interface pins
|
|
||||||
void i2cInit(void);
|
|
||||||
|
|
||||||
// send I2C data to <device> register <sub>
|
|
||||||
void i2cSend(BYTE device, BYTE sub, BYTE length, BYTE *data);
|
|
||||||
|
|
||||||
// receive I2C data from <device> register <sub>
|
|
||||||
void i2cReceive(BYTE device, BYTE sub, BYTE length, BYTE *data);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,134 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Procyon AVRlib - C-Language Function Library for Atmel AVR Processors</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<!--#config timefmt="%A %B %d, %Y" -->
|
|
||||||
<h1 align="center"><font color="#990000"><b><font color="#0066CC">Procyon AVRlib</font></b></font><font size="4" face="Arial" color="#990000"><b><br>
|
|
||||||
</b></font><font size="4" color="#990000"><b>C-Language Function Library for
|
|
||||||
Atmel AVR Processors</b></font></h1>
|
|
||||||
|
|
||||||
<center>
|
|
||||||
Written by Pascal Stang | Updated:
|
|
||||||
<!--#echo var="LAST_MODIFIED" -->
|
|
||||||
</center>
|
|
||||||
<hr>
|
|
||||||
<ul>
|
|
||||||
<li><b>AVRlib is a library of easy-to-use C functions for a variety of common
|
|
||||||
and uncommon tasks using AVR processors. </b></li>
|
|
||||||
<li>The goal of AVRlib is to allow programmers to work quickly towards their
|
|
||||||
end goal by reducing the time needed to write basic support functions and
|
|
||||||
code. </li>
|
|
||||||
<li> Most AVRlib header (*.h) files have lengthy descriptions of how to use
|
|
||||||
the supplied library functions. All code (*.c) files are heavily commented
|
|
||||||
with additional information. </li>
|
|
||||||
<li> Documentation is still being improved and refined on many libraries. When
|
|
||||||
getting familiar with a library, look first at the HTML docs and any example
|
|
||||||
code that is available in the examples directory. Then look inside the *.h
|
|
||||||
and *conf.h files, and then the *.c file for that library for more details
|
|
||||||
and documentation.</li>
|
|
||||||
<li> Significant example code is included in <i>avrlib.zip.</i> The example
|
|
||||||
code is heavily commented and strives to illustrate how to use various AVRlib
|
|
||||||
function libraries.</li>
|
|
||||||
<li><font color="#FF0000"><strong>Download AVRlib (with docs and code examples)</strong>
|
|
||||||
</font>
|
|
||||||
<ul>
|
|
||||||
<li><a href="avrlib.zip">AVRlib (zip file, 1MB, <!--#flastmod virtual="avrlib.zip"-->)</a></li>
|
|
||||||
<li><a href="avrlib_setup.exe">AVRlib (win32 installer package, 1MB,
|
|
||||||
<!--#flastmod virtual="avrlib.zip"-->
|
|
||||||
)</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a href="docs/html/index.html">On-line HTML Documentation</a></li>
|
|
||||||
<li> <a href="release_notes.html">Release Notes</a></li>
|
|
||||||
<li> <a href="install.html">AVRlib Install Guide</a> for manual installation
|
|
||||||
of zip file</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<div align="center">
|
|
||||||
<h3><font color="#0066CC"><b>Procyon AVRlib Overview</b></font></h3>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<table border="1" width="100%">
|
|
||||||
<tr>
|
|
||||||
<td width="50%" bgcolor="#3C2D74"><font color="#FFFFFF"><b>General</b></font></td>
|
|
||||||
<td width="50%" bgcolor="#3C2D74"><font color="#FFFFFF"><b>AVR Built-In Peripheral
|
|
||||||
Drivers </b></font></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td width="50%">
|
|
||||||
<ul>
|
|
||||||
<li>Byte Buffering (circular)</li>
|
|
||||||
<li>Bit Buffering (linear)</li>
|
|
||||||
<li>Printf and other formatted print functions</li>
|
|
||||||
<li>VT100 Terminal Output</li>
|
|
||||||
<li>Command Line Interface</li>
|
|
||||||
<li>FAT16/32 File System (support is read-only for now)</li>
|
|
||||||
<li>STX/ETX Packet Protocol</li>
|
|
||||||
<li>Fixed-Point Math Library (basic operations only)</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
<td width="50%">
|
|
||||||
<ul>
|
|
||||||
<li>Timers (with PWM, interrupt management)</li>
|
|
||||||
<li>UART (interrupt driven)</li>
|
|
||||||
<li>A/D Converter</li>
|
|
||||||
<li>I2C Master/Slave (interrupt and non-intr)</li>
|
|
||||||
<li>SPI Interface</li>
|
|
||||||
<li>External Interrupts</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td width="50%" bgcolor="#3C2D74"><font color="#FFFFFF"><b> External Hardware
|
|
||||||
Device Drivers</b></font></td>
|
|
||||||
<td width="50%" bgcolor="#3C2D74"><font color="#FFFFFF"><b>AVR Software-Emulated Devices</b></font></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td width="50%">
|
|
||||||
<ul>
|
|
||||||
<li>Character LCD Modules (HD44780-based)</li>
|
|
||||||
<li>I2C EEPROM Memories</li>
|
|
||||||
<li>SPI EEPROM Memories</li>
|
|
||||||
<li>MMC/SD Card Interface (SPI mode)</li>
|
|
||||||
<li>LIS3L02 ST Accelerometer</li>
|
|
||||||
<li>IDE/ATA Interface (for hard disks and CF cards)</li>
|
|
||||||
<li>Quadrature Encoders</li>
|
|
||||||
<li>RC-Servos (up to 8 channels)</li>
|
|
||||||
<li>STA013 MP3 Decoder Chip</li>
|
|
||||||
<li>GPS Receivers (via serial port)
|
|
||||||
<ul>
|
|
||||||
<li>NMEA-0813 Protocol</li>
|
|
||||||
<li>Trimble TSIP Protocol</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li>Graphic LCD Modules
|
|
||||||
<ul>
|
|
||||||
<li>KS0108/HD61202 Controller</li>
|
|
||||||
<li>T6963 Controller</li>
|
|
||||||
<li>LCD Fonts and Symbols</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
<td width="50%"> <ul>
|
|
||||||
<li>I2c Master (Bit-Bang)</li>
|
|
||||||
<li>UART (software-based, timer interrupt driven)</li>
|
|
||||||
<li>Pulse Output (timer-based, variable frequency)</li>
|
|
||||||
<li>Intel-type Memory Bus (Address & Data Buses + nRD,nWR)</li>
|
|
||||||
</ul>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<hr>
|
|
||||||
<center>
|
|
||||||
Written by Pascal Stang | Updated:
|
|
||||||
<!--#echo var="LAST_MODIFIED" -->
|
|
||||||
</center>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,154 +0,0 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>SCU Robotic Systems Laboratory - Installing Procyon AVRlib</title>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<!--#config timefmt="%a %b %d, %Y" -->
|
|
||||||
<h1>Installing Procyon AVRlib</h1>
|
|
||||||
<h2>Sections</h2>
|
|
||||||
<ol>
|
|
||||||
<li><a href="#1">Overview</a></li>
|
|
||||||
<li><a href="#2">Downloading</a></li>
|
|
||||||
<li><a href="#3">Installing</a></li>
|
|
||||||
<li><a href="#4">Testing</a></li>
|
|
||||||
</ol>
|
|
||||||
<center>Written by Pascal Stang | Updated:
|
|
||||||
<!--#echo var="LAST_MODIFIED" -->
|
|
||||||
</center>
|
|
||||||
<hr>
|
|
||||||
<h3><a name="1"></a>1. Overview</h3>
|
|
||||||
<blockquote>
|
|
||||||
<p>Procyon AVRlib is an open-source collection of C-language function libraries
|
|
||||||
for the Atmel AVR series processors. The goal of AVRlib is to provide the
|
|
||||||
programmer with a code base which performs the most often needed tasks in
|
|
||||||
embedded system programming. Hopefully, this will allow the programmer to
|
|
||||||
focus on high-level operation of their code rather than get bogged down in
|
|
||||||
the details of low-level code.</p>
|
|
||||||
<p>In short, AVRlib is a bunch of functions that do things commonly needed in
|
|
||||||
embedded systems. Despite the learning curve of getting started, for most
|
|
||||||
projects, using AVRlib will shorten the time spent programming and/or improve
|
|
||||||
the quality or functionality of the final product.</p>
|
|
||||||
<p>AVRlib functions are available for a wide variety of tasks and purposes.
|
|
||||||
In general, AVRlib tries to address the following kinds of needs:</p>
|
|
||||||
<ul>
|
|
||||||
<li>Functions which control or interface to AVR processor hardware (like timers,
|
|
||||||
uarts, the a2d converter, etc)</li>
|
|
||||||
<li>Functions which interface to or drive devices often used in embedded systems
|
|
||||||
(like LCDs, hard disks, gps units, etc)</li>
|
|
||||||
<li>Functions which create higher-level functionality from processor resources
|
|
||||||
(like pulse generation, software uarts, software i2c bus, etc)</li>
|
|
||||||
</ul>
|
|
||||||
<p>For a partial list of currently available function libraries see the <a href="index.html">AVRlib
|
|
||||||
Main Page</a>.</p>
|
|
||||||
</blockquote>
|
|
||||||
<h3><a name="2"></a>2. Downloading</h3>
|
|
||||||
<blockquote>
|
|
||||||
<p>AVRlib is currently available as individual files, or a complete zip file.
|
|
||||||
Both are available from the <a href="index.html">AVRlib Main Page</a>.</p>
|
|
||||||
<p><strong><font color="#FF0000">Downloading the complete <a href="avrlib.zip">avrlib.zip</a>
|
|
||||||
file is highly recommended as documentation and code examples are included
|
|
||||||
in the zip.</font></strong></p>
|
|
||||||
</blockquote>
|
|
||||||
<h3><a name="3"></a>3. Installing</h3>
|
|
||||||
<blockquote>
|
|
||||||
<p><strong><font color="#FF0000">This installation for AVRlib assumes you have
|
|
||||||
already installed the AVR-GCC or WinAVR compiler and successfully tested it.</font></strong></p>
|
|
||||||
<p>You can install AVRlib anywhere you like, however, it's suggested that you
|
|
||||||
install it in a directory alongside your own AVR code projects. Create or
|
|
||||||
choose a top-level directory to hold both AVRlib and the project folders which
|
|
||||||
you will create to hold the code for each individual project you work on.
|
|
||||||
The directory you choose should not contain spaces in its name or path. Some
|
|
||||||
examples are: </p>
|
|
||||||
<pre>
|
|
||||||
c:\Code\AVR <font color="#009900">(GOOD)</font>
|
|
||||||
c:\My Code <font color="#FF0000">(NOT RECOMMENDED - HAS SPACES IN PATH)</font>
|
|
||||||
</pre>
|
|
||||||
<p>From the download step you should have an <strong>avrlib.zip</strong> file.
|
|
||||||
Unzip this file into the code directory you chose above. Be sure to preserve
|
|
||||||
the internal directory structure of the zip file when you unzip it. Afterward,
|
|
||||||
you can delete avrlib.zip but you may want to keep it for later re-installs
|
|
||||||
or as a backup.</p>
|
|
||||||
<p>You should now have an <strong>avrlib</strong> directory where you installed
|
|
||||||
AVRlib. If you have some time, get familiar with what's inside some of the
|
|
||||||
directories. Your directories should look something like this:</p>
|
|
||||||
<pre>
|
|
||||||
c:\Code\AVR\avrlib <font color="#0000FF"><-- AVRlib header and code files</font>
|
|
||||||
c:\Code\AVR\avrlib\conf <font color="#0000FF"><-- AVRlib template configuration files</font>
|
|
||||||
c:\Code\AVR\avrlib\docs <font color="#0000FF"><-- AVRlib documentation</font>
|
|
||||||
c:\Code\AVR\avrlib\examples <font color="#0000FF"><-- AVRlib example applications</font>
|
|
||||||
c:\Code\AVR\avrlib\make <font color="#0000FF"><-- AVRlib makefile include (avrproj_make file in here)</font></pre>
|
|
||||||
<p>Finally, you need to create an environment variable <strong>AVRLIB</strong>
|
|
||||||
which points to the directory where you "installed" or unzipped
|
|
||||||
the AVRlib files so the compiler can find them. An example might be:</p>
|
|
||||||
<pre>AVRLIB = c:/code/avr/avrlib <font color="#0000FF"><-- change to actual AVRlib install directory</font>
|
|
||||||
</pre>
|
|
||||||
<p>If you are unsure how to set environment variables on your system, look at
|
|
||||||
the WinAVR/AVR-GCC installation guide elsewhere on this site or consult the
|
|
||||||
web.</p>
|
|
||||||
<p>AVRlib installation is complete!</p>
|
|
||||||
</blockquote>
|
|
||||||
<h3><a name="4"></a>4. Testing</h3>
|
|
||||||
<blockquote>
|
|
||||||
<p>There are a few simple steps you can take to verify that AVRlib is properly
|
|
||||||
installed:<br>
|
|
||||||
<font color="#FF0000"><strong>(This assumes you have previously installed
|
|
||||||
and tested the AVR-GCC or WinAVR compiler)</strong></font></p>
|
|
||||||
<ul>
|
|
||||||
<li>Open a Command Prompt (find it in your <strong>Start Menu</strong> or
|
|
||||||
select <strong>Run</strong>, and run <strong>cmd.exe</strong>) </li>
|
|
||||||
<li>Change directories to the location where you installed AVRlib. For example:<br>
|
|
||||||
<strong>cd c:\Code\AVR\AVRlib</strong></li>
|
|
||||||
<li>Go into the examples directory. <strong>cd examples</strong></li>
|
|
||||||
<li>Pick an example to try compiling such as rprintf and change to that directory.
|
|
||||||
<strong>cd rprintf</strong></li>
|
|
||||||
<li>Type <strong>make clean</strong> at the prompt</li>
|
|
||||||
<li>Type <strong>make</strong></li>
|
|
||||||
<li>If your output looked like this then you just compiled your first AVRlib
|
|
||||||
program:
|
|
||||||
<pre>
|
|
||||||
C:\Code\AVR\avrlib\examples\rprintf>make
|
|
||||||
avr-gcc -c -g -Os -Wall -Wstrict-prototypes -Ic:/code/avr/avrlib -Wa,-ahlms=rpri
|
|
||||||
ntftest.lst -mmcu=atmega323 -I. rprintftest.c -o rprintftest.o
|
|
||||||
avr-gcc -c -g -Os -Wall -Wstrict-prototypes -Ic:/code/avr/avrlib -Wa,-ahlms=c:/c
|
|
||||||
ode/avr/avrlib/buffer.lst -mmcu=atmega323 -I. c:/code/avr/avrlib/buffer.c -o c:/
|
|
||||||
code/avr/avrlib/buffer.o
|
|
||||||
avr-gcc -c -g -Os -Wall -Wstrict-prototypes -Ic:/code/avr/avrlib -Wa,-ahlms=c:/c
|
|
||||||
ode/avr/avrlib/uart.lst -mmcu=atmega323 -I. c:/code/avr/avrlib/uart.c -o c:/code
|
|
||||||
/avr/avrlib/uart.o
|
|
||||||
avr-gcc -c -g -Os -Wall -Wstrict-prototypes -Ic:/code/avr/avrlib -Wa,-ahlms=c:/c
|
|
||||||
ode/avr/avrlib/rprintf.lst -mmcu=atmega323 -I. c:/code/avr/avrlib/rprintf.c -o c
|
|
||||||
:/code/avr/avrlib/rprintf.o
|
|
||||||
avr-gcc -c -g -Os -Wall -Wstrict-prototypes -Ic:/code/avr/avrlib -Wa,-ahlms=c:/c
|
|
||||||
ode/avr/avrlib/timer.lst -mmcu=atmega323 -I. c:/code/avr/avrlib/timer.c -o c:/co
|
|
||||||
de/avr/avrlib/timer.o
|
|
||||||
avr-gcc -c -g -Os -Wall -Wstrict-prototypes -Ic:/code/avr/avrlib -Wa,-ahlms=c:/c
|
|
||||||
ode/avr/avrlib/vt100.lst -mmcu=atmega323 -I. c:/code/avr/avrlib/vt100.c -o c:/co
|
|
||||||
de/avr/avrlib/vt100.o
|
|
||||||
avr-gcc c:/code/avr/avrlib/buffer.o c:/code/avr/avrlib/uart.o c:/code/avr/avrli
|
|
||||||
b/rprintf.o c:/code/avr/avrlib/timer.o c:/code/avr/avrlib/vt100.o rprintftest.o
|
|
||||||
-Wl,-Map=rprintftest.map,--cref -mmcu=atmega323 -o rprintftest.elf
|
|
||||||
avr-objcopy -O ihex -R .eeprom rprintftest.elf rprintftest.hex
|
|
||||||
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section
|
|
||||||
-lma .eeprom=0 -O ihex rprintftest.elf rprintftest.eep
|
|
||||||
avr-size rprintftest.elf
|
|
||||||
text data bss dec hex filename
|
|
||||||
9596 0 192 9788 263c rprintftest.elf
|
|
||||||
Errors: none
|
|
||||||
rm c:/code/avr/avrlib/vt100.o c:/code/avr/avrlib/rprintf.o c:/code/avr/avrlib/ua
|
|
||||||
rt.o c:/code/avr/avrlib/timer.o c:/code/avr/avrlib/buffer.o
|
|
||||||
|
|
||||||
C:\Code\AVR\avrlib\examples\rprintf>
|
|
||||||
</pre>
|
|
||||||
</li>
|
|
||||||
<strong>AVRlib is ready to use!</strong>
|
|
||||||
</ul>
|
|
||||||
</blockquote>
|
|
||||||
<hr>
|
|
||||||
<center>Written by Pascal Stang | Updated:
|
|
||||||
<!--#echo var="LAST_MODIFIED" -->
|
|
||||||
</center>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,381 +0,0 @@
|
|||||||
/*! \file ks0108.c \brief Graphic LCD driver for HD61202/KS0108 displays. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'ks0108.c'
|
|
||||||
// Title : Graphic LCD driver for HD61202/KS0108 displays
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2001-2003
|
|
||||||
// Date : 10/19/2002
|
|
||||||
// Revised : 5/5/2003
|
|
||||||
// Version : 0.5
|
|
||||||
// Target MCU : Atmel AVR
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
// AVR specific includes
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include "ks0108.h"
|
|
||||||
|
|
||||||
// global variables
|
|
||||||
GrLcdStateType GrLcdState;
|
|
||||||
|
|
||||||
/*************************************************************/
|
|
||||||
/********************** LOCAL FUNCTIONS **********************/
|
|
||||||
/*************************************************************/
|
|
||||||
|
|
||||||
void glcdInitHW(void)
|
|
||||||
{
|
|
||||||
// initialize I/O ports
|
|
||||||
// if I/O interface is in use
|
|
||||||
#ifdef GLCD_PORT_INTERFACE
|
|
||||||
|
|
||||||
//TODO: make setup of chip select lines contingent on how
|
|
||||||
// many controllers are actually in the display
|
|
||||||
|
|
||||||
// initialize LCD control lines levels
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_RS);
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS0);
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS1);
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS2);
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS3);
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_RESET);
|
|
||||||
// initialize LCD control port to output
|
|
||||||
sbi(GLCD_CTRL_DDR, GLCD_CTRL_RS);
|
|
||||||
sbi(GLCD_CTRL_DDR, GLCD_CTRL_RW);
|
|
||||||
sbi(GLCD_CTRL_DDR, GLCD_CTRL_E);
|
|
||||||
sbi(GLCD_CTRL_DDR, GLCD_CTRL_CS0);
|
|
||||||
sbi(GLCD_CTRL_DDR, GLCD_CTRL_CS1);
|
|
||||||
sbi(GLCD_CTRL_DDR, GLCD_CTRL_CS2);
|
|
||||||
sbi(GLCD_CTRL_DDR, GLCD_CTRL_CS3);
|
|
||||||
sbi(GLCD_CTRL_DDR, GLCD_CTRL_RESET);
|
|
||||||
// initialize LCD data
|
|
||||||
outb(GLCD_DATA_PORT, 0x00);
|
|
||||||
// initialize LCD data port to output
|
|
||||||
outb(GLCD_DATA_DDR, 0xFF);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void glcdControllerSelect(u08 controller)
|
|
||||||
{
|
|
||||||
#ifdef GLCD_PORT_INTERFACE
|
|
||||||
//TODO: make control of chip select lines contingent on how
|
|
||||||
// many controllers are actually in the display
|
|
||||||
|
|
||||||
// unselect all controllers
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS0);
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS1);
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS2);
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_CS3);
|
|
||||||
|
|
||||||
// select requested controller
|
|
||||||
switch(controller)
|
|
||||||
{
|
|
||||||
case 0: sbi(GLCD_CTRL_PORT, GLCD_CTRL_CS0); break;
|
|
||||||
case 1: sbi(GLCD_CTRL_PORT, GLCD_CTRL_CS1); break;
|
|
||||||
case 2: sbi(GLCD_CTRL_PORT, GLCD_CTRL_CS2); break;
|
|
||||||
case 3: sbi(GLCD_CTRL_PORT, GLCD_CTRL_CS3); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void glcdBusyWait(u08 controller)
|
|
||||||
{
|
|
||||||
#ifdef GLCD_PORT_INTERFACE
|
|
||||||
cli();
|
|
||||||
// wait until LCD busy bit goes to zero
|
|
||||||
// select the controller chip
|
|
||||||
glcdControllerSelect(controller);
|
|
||||||
// do a read from control register
|
|
||||||
outb(GLCD_DATA_PORT, 0xFF);
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_RS);
|
|
||||||
outb(GLCD_DATA_DDR, 0x00);
|
|
||||||
sbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
|
|
||||||
sbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
while(inb(GLCD_DATA_PIN) & GLCD_STATUS_BUSY)
|
|
||||||
{
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
sbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
}
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
|
|
||||||
outb(GLCD_DATA_DDR, 0xFF);
|
|
||||||
sei();
|
|
||||||
#else
|
|
||||||
// sbi(MCUCR, SRW); // enable RAM waitstate
|
|
||||||
// wait until LCD busy bit goes to zero
|
|
||||||
while(*(volatile unsigned char *)
|
|
||||||
(GLCD_CONTROLLER0_CTRL_ADDR + GLCD_CONTROLLER_ADDR_OFFSET*controller) & GLCD_STATUS_BUSY);
|
|
||||||
// cbi(MCUCR, SRW); // disable RAM waitstate
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void glcdControlWrite(u08 controller, u08 data)
|
|
||||||
{
|
|
||||||
#ifdef GLCD_PORT_INTERFACE
|
|
||||||
cli();
|
|
||||||
glcdBusyWait(controller); // wait until LCD not busy
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_RS);
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
|
|
||||||
sbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
|
|
||||||
outb(GLCD_DATA_DDR, 0xFF);
|
|
||||||
outb(GLCD_DATA_PORT, data);
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
|
|
||||||
sei();
|
|
||||||
#else
|
|
||||||
//sbi(MCUCR, SRW); // enable RAM waitstate
|
|
||||||
glcdBusyWait(controller); // wait until LCD not busy
|
|
||||||
*(volatile unsigned char *) (GLCD_CONTROLLER0_CTRL_ADDR + GLCD_CONTROLLER_ADDR_OFFSET*controller) = data;
|
|
||||||
//cbi(MCUCR, SRW); // disable RAM waitstate
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 glcdControlRead(u08 controller)
|
|
||||||
{
|
|
||||||
register u08 data;
|
|
||||||
#ifdef GLCD_PORT_INTERFACE
|
|
||||||
cli();
|
|
||||||
glcdBusyWait(controller); // wait until LCD not busy
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_RS);
|
|
||||||
outb(GLCD_DATA_DDR, 0x00);
|
|
||||||
sbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
|
|
||||||
sbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
data = inb(GLCD_DATA_PIN);
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
|
|
||||||
outb(GLCD_DATA_DDR, 0xFF);
|
|
||||||
sei();
|
|
||||||
#else
|
|
||||||
//sbi(MCUCR, SRW); // enable RAM waitstate
|
|
||||||
glcdBusyWait(controller); // wait until LCD not busy
|
|
||||||
data = *(volatile unsigned char *) (GLCD_CONTROLLER0_CTRL_ADDR + GLCD_CONTROLLER_ADDR_OFFSET*controller);
|
|
||||||
//cbi(MCUCR, SRW); // disable RAM waitstate
|
|
||||||
#endif
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void glcdDataWrite(u08 data)
|
|
||||||
{
|
|
||||||
register u08 controller = (GrLcdState.lcdXAddr/GLCD_CONTROLLER_XPIXELS);
|
|
||||||
#ifdef GLCD_PORT_INTERFACE
|
|
||||||
cli();
|
|
||||||
glcdBusyWait(controller); // wait until LCD not busy
|
|
||||||
sbi(GLCD_CTRL_PORT, GLCD_CTRL_RS);
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
|
|
||||||
sbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
|
|
||||||
outb(GLCD_DATA_DDR, 0xFF);
|
|
||||||
outb(GLCD_DATA_PORT, data);
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
|
|
||||||
sei();
|
|
||||||
#else
|
|
||||||
//sbi(MCUCR, SRW); // enable RAM waitstate
|
|
||||||
glcdBusyWait(controller); // wait until LCD not busy
|
|
||||||
*(volatile unsigned char *) (GLCD_CONTROLLER0_CTRL_ADDR + GLCD_CONTROLLER_ADDR_OFFSET*controller) = data;
|
|
||||||
//cbi(MCUCR, SRW); // disable RAM waitstate
|
|
||||||
#endif
|
|
||||||
// increment our local address counter
|
|
||||||
GrLcdState.ctrlr[controller].xAddr++;
|
|
||||||
GrLcdState.lcdXAddr++;
|
|
||||||
if(GrLcdState.lcdXAddr >= GLCD_XPIXELS)
|
|
||||||
{
|
|
||||||
GrLcdState.lcdYAddr++;
|
|
||||||
glcdSetYAddress(GrLcdState.lcdYAddr);
|
|
||||||
glcdSetXAddress(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 glcdDataRead(void)
|
|
||||||
{
|
|
||||||
register u08 data;
|
|
||||||
register u08 controller = (GrLcdState.lcdXAddr/GLCD_CONTROLLER_XPIXELS);
|
|
||||||
#ifdef GLCD_PORT_INTERFACE
|
|
||||||
cli();
|
|
||||||
glcdBusyWait(controller); // wait until LCD not busy
|
|
||||||
sbi(GLCD_CTRL_PORT, GLCD_CTRL_RS);
|
|
||||||
outb(GLCD_DATA_DDR, 0x00);
|
|
||||||
sbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
|
|
||||||
sbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
asm volatile ("nop"); asm volatile ("nop");
|
|
||||||
data = inb(GLCD_DATA_PIN);
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_E);
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_RW);
|
|
||||||
sei();
|
|
||||||
#else
|
|
||||||
//sbi(MCUCR, SRW); // enable RAM waitstate
|
|
||||||
glcdBusyWait(controller); // wait until LCD not busy
|
|
||||||
data = *(volatile unsigned char *) (GLCD_CONTROLLER0_CTRL_ADDR + GLCD_CONTROLLER_ADDR_OFFSET*controller);
|
|
||||||
//cbi(MCUCR, SRW); // disable RAM waitstate
|
|
||||||
#endif
|
|
||||||
// increment our local address counter
|
|
||||||
GrLcdState.ctrlr[controller].xAddr++;
|
|
||||||
GrLcdState.lcdXAddr++;
|
|
||||||
if(GrLcdState.lcdXAddr >= GLCD_XPIXELS)
|
|
||||||
{
|
|
||||||
GrLcdState.lcdYAddr++;
|
|
||||||
glcdSetYAddress(GrLcdState.lcdYAddr);
|
|
||||||
glcdSetXAddress(0);
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void glcdReset(u08 resetState)
|
|
||||||
{
|
|
||||||
// reset lcd if argument is true
|
|
||||||
// run lcd if argument is false
|
|
||||||
#ifdef GLCD_PORT_INTERFACE
|
|
||||||
if(resetState)
|
|
||||||
cbi(GLCD_CTRL_PORT, GLCD_CTRL_RESET);
|
|
||||||
else
|
|
||||||
sbi(GLCD_CTRL_PORT, GLCD_CTRL_RESET);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void glcdSetXAddress(u08 xAddr)
|
|
||||||
{
|
|
||||||
u08 i;
|
|
||||||
// record address change locally
|
|
||||||
GrLcdState.lcdXAddr = xAddr;
|
|
||||||
|
|
||||||
// clear y (col) address on all controllers
|
|
||||||
for(i=0; i<GLCD_NUM_CONTROLLERS; i++)
|
|
||||||
{
|
|
||||||
glcdControlWrite(i, GLCD_SET_Y_ADDR | 0x00);
|
|
||||||
GrLcdState.ctrlr[i].xAddr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set y (col) address on destination controller
|
|
||||||
glcdControlWrite((GrLcdState.lcdXAddr/GLCD_CONTROLLER_XPIXELS),
|
|
||||||
GLCD_SET_Y_ADDR | (GrLcdState.lcdXAddr & 0x3F));
|
|
||||||
}
|
|
||||||
|
|
||||||
void glcdSetYAddress(u08 yAddr)
|
|
||||||
{
|
|
||||||
u08 i;
|
|
||||||
// record address change locally
|
|
||||||
GrLcdState.lcdYAddr = yAddr;
|
|
||||||
// set page address for all controllers
|
|
||||||
for(i=0; i<GLCD_NUM_CONTROLLERS; i++)
|
|
||||||
{
|
|
||||||
glcdControlWrite(i, GLCD_SET_PAGE | yAddr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*************************************************************/
|
|
||||||
/********************* PUBLIC FUNCTIONS **********************/
|
|
||||||
/*************************************************************/
|
|
||||||
|
|
||||||
void glcdInit()
|
|
||||||
{
|
|
||||||
u08 i;
|
|
||||||
// initialize hardware
|
|
||||||
glcdInitHW();
|
|
||||||
// bring lcd out of reset
|
|
||||||
glcdReset(FALSE);
|
|
||||||
// Turn on LCD
|
|
||||||
for(i=0; i<GLCD_NUM_CONTROLLERS; i++)
|
|
||||||
{
|
|
||||||
glcdControlWrite(i, GLCD_ON_CTRL | GLCD_ON_DISPLAY);
|
|
||||||
}
|
|
||||||
// clear lcd
|
|
||||||
glcdClearScreen();
|
|
||||||
// initialize positions
|
|
||||||
glcdHome();
|
|
||||||
}
|
|
||||||
|
|
||||||
void glcdHome(void)
|
|
||||||
{
|
|
||||||
u08 i;
|
|
||||||
// initialize addresses/positions
|
|
||||||
glcdStartLine(0);
|
|
||||||
glcdSetAddress(0,0);
|
|
||||||
// initialize local data structures
|
|
||||||
for(i=0; i<GLCD_NUM_CONTROLLERS; i++)
|
|
||||||
{
|
|
||||||
GrLcdState.ctrlr[i].xAddr = 0;
|
|
||||||
GrLcdState.ctrlr[i].yAddr = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void glcdClearScreen(void)
|
|
||||||
{
|
|
||||||
u08 pageAddr;
|
|
||||||
u08 xAddr;
|
|
||||||
|
|
||||||
// clear LCD
|
|
||||||
// loop through all pages
|
|
||||||
for(pageAddr=0; pageAddr<(GLCD_YPIXELS>>3); pageAddr++)
|
|
||||||
{
|
|
||||||
// set page address
|
|
||||||
glcdSetAddress(0, pageAddr);
|
|
||||||
// clear all lines of this page of display memory
|
|
||||||
for(xAddr=0; xAddr<GLCD_XPIXELS; xAddr++)
|
|
||||||
{
|
|
||||||
glcdDataWrite(0x00);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void glcdStartLine(u08 start)
|
|
||||||
{
|
|
||||||
glcdControlWrite(0, GLCD_START_LINE | start);
|
|
||||||
glcdControlWrite(1, GLCD_START_LINE | start);
|
|
||||||
}
|
|
||||||
|
|
||||||
void glcdSetAddress(u08 x, u08 yLine)
|
|
||||||
{
|
|
||||||
// set addresses
|
|
||||||
glcdSetYAddress(yLine);
|
|
||||||
glcdSetXAddress(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
void glcdGotoChar(u08 line, u08 col)
|
|
||||||
{
|
|
||||||
glcdSetAddress(col*6, line);
|
|
||||||
}
|
|
||||||
|
|
||||||
void glcdDelay(u16 p) // 1-8us ...2-13us ...5-31us
|
|
||||||
{ // 10-60us ...50-290us
|
|
||||||
unsigned int i; // 100-580us ...500-2,9ms
|
|
||||||
unsigned char j; // 1000-5,8ms ...5000-29ms
|
|
||||||
// 10000-56ms ...30000-170ms
|
|
||||||
// 50000-295ms...60000-345ms
|
|
||||||
// for (i = 0; i < p; i++) for (j = 0; j < 10; j++) asm volatile ("nop");
|
|
||||||
for (i = 0; i < p; i++) for (j = 0; j < 10; j++);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Higher level functionality has been moved to the API-layer glcd.c/glcd.h
|
|
@ -1,86 +0,0 @@
|
|||||||
/*! \file ks0108.h \brief Graphic LCD driver for HD61202/KS0108 displays. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'ks0108.h'
|
|
||||||
// Title : Graphic LCD driver for HD61202/KS0108 displays
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2001-2003
|
|
||||||
// Date : 10/19/2002
|
|
||||||
// Revised : 5/1/2003
|
|
||||||
// Version : 0.5
|
|
||||||
// Target MCU : Atmel AVR
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef KS0108_H
|
|
||||||
#define KS0108_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
#include "ks0108conf.h"
|
|
||||||
|
|
||||||
// HD61202/KS0108 command set
|
|
||||||
#define GLCD_ON_CTRL 0x3E // 0011111X: lcd on/off control
|
|
||||||
#define GLCD_ON_DISPLAY 0x01 // DB0: turn display on
|
|
||||||
|
|
||||||
#define GLCD_START_LINE 0xC0 // 11XXXXXX: set lcd start line
|
|
||||||
|
|
||||||
#define GLCD_SET_PAGE 0xB8 // 10111XXX: set lcd page (X) address
|
|
||||||
#define GLCD_SET_Y_ADDR 0x40 // 01YYYYYY: set lcd Y address
|
|
||||||
|
|
||||||
#define GLCD_STATUS_BUSY 0x80 // (1)->LCD IS BUSY
|
|
||||||
#define GLCD_STATUS_ONOFF 0x20 // (0)->LCD IS ON
|
|
||||||
#define GLCD_STATUS_RESET 0x10 // (1)->LCD IS RESET
|
|
||||||
|
|
||||||
// determine the number of controllers
|
|
||||||
// (make sure we round up for partial use of more than one controller)
|
|
||||||
#define GLCD_NUM_CONTROLLERS ((GLCD_XPIXELS+GLCD_CONTROLLER_XPIXELS-1)/GLCD_CONTROLLER_XPIXELS)
|
|
||||||
|
|
||||||
// typedefs/structures
|
|
||||||
typedef struct struct_GrLcdCtrlrStateType
|
|
||||||
{
|
|
||||||
unsigned char xAddr;
|
|
||||||
unsigned char yAddr;
|
|
||||||
} GrLcdCtrlrStateType;
|
|
||||||
|
|
||||||
typedef struct struct_GrLcdStateType
|
|
||||||
{
|
|
||||||
unsigned char lcdXAddr;
|
|
||||||
unsigned char lcdYAddr;
|
|
||||||
GrLcdCtrlrStateType ctrlr[GLCD_NUM_CONTROLLERS];
|
|
||||||
} GrLcdStateType;
|
|
||||||
|
|
||||||
// function prototypes
|
|
||||||
void glcdInitHW(void);
|
|
||||||
void glcdBusyWait(u08 controller);
|
|
||||||
void glcdControlWrite(u08 controller, u08 data);
|
|
||||||
u08 glcdControlRead(u08 controller);
|
|
||||||
void glcdDataWrite(u08 data);
|
|
||||||
u08 glcdDataRead(void);
|
|
||||||
void glcdSetXAddress(u08 xAddr);
|
|
||||||
void glcdSetYAddress(u08 yAddr);
|
|
||||||
|
|
||||||
|
|
||||||
//! Initialize the display, clear it, and prepare it for access
|
|
||||||
void glcdInit(void);
|
|
||||||
//! Clear the display
|
|
||||||
void glcdClearScreen(void);
|
|
||||||
//! Set display memory access point back to upper,left corner
|
|
||||||
void glcdHome(void);
|
|
||||||
//! Set display memory access point to row [line] and column [col] assuming 5x7 font
|
|
||||||
void glcdGotoChar(u08 line, u08 col);
|
|
||||||
//! Set display memory access point to [x] horizontal pixel and [y] vertical line
|
|
||||||
void glcdSetAddress(u08 x, u08 yLine);
|
|
||||||
//! Set display memory access point to row [line] and column [col] assuming 5x7 font
|
|
||||||
void glcdStartLine(u08 start);
|
|
||||||
//! Generic delay routine for timed glcd access
|
|
||||||
void glcdDelay(u16 p);
|
|
||||||
#endif
|
|
@ -1,469 +0,0 @@
|
|||||||
/*! \file lcd.c \brief Character LCD driver for HD44780/SED1278 displays. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'lcd.c'
|
|
||||||
// Title : Character LCD driver for HD44780/SED1278 displays
|
|
||||||
// (usable in mem-mapped, or I/O mode)
|
|
||||||
// Author : Pascal Stang
|
|
||||||
// Created : 11/22/2000
|
|
||||||
// Revised : 4/30/2002
|
|
||||||
// Version : 1.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include "timer.h"
|
|
||||||
|
|
||||||
#include "lcd.h"
|
|
||||||
|
|
||||||
// custom LCD characters
|
|
||||||
unsigned char __attribute__ ((progmem)) LcdCustomChar[] =
|
|
||||||
{
|
|
||||||
0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, // 0. 0/5 full progress block
|
|
||||||
0x00, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x1F, 0x00, // 1. 1/5 full progress block
|
|
||||||
0x00, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, // 2. 2/5 full progress block
|
|
||||||
0x00, 0x1F, 0x1C, 0x1C, 0x1C, 0x1C, 0x1F, 0x00, // 3. 3/5 full progress block
|
|
||||||
0x00, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x00, // 4. 4/5 full progress block
|
|
||||||
0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, // 5. 5/5 full progress block
|
|
||||||
0x03, 0x07, 0x0F, 0x1F, 0x0F, 0x07, 0x03, 0x00, // 6. rewind arrow
|
|
||||||
0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, // 7. stop block
|
|
||||||
0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, // 8. pause bars
|
|
||||||
0x18, 0x1C, 0x1E, 0x1F, 0x1E, 0x1C, 0x18, 0x00, // 9. fast-forward arrow
|
|
||||||
0x00, 0x04, 0x04, 0x0E, 0x0E, 0x1F, 0x1F, 0x00, // 10. scroll up arrow
|
|
||||||
0x00, 0x1F, 0x1F, 0x0E, 0x0E, 0x04, 0x04, 0x00, // 11. scroll down arrow
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 12. blank character
|
|
||||||
0x00, 0x0E, 0x19, 0x15, 0x13, 0x0E, 0x00, 0x00, // 13. animated play icon frame 0
|
|
||||||
0x00, 0x0E, 0x15, 0x15, 0x15, 0x0E, 0x00, 0x00, // 14. animated play icon frame 1
|
|
||||||
0x00, 0x0E, 0x13, 0x15, 0x19, 0x0E, 0x00, 0x00, // 15. animated play icon frame 2
|
|
||||||
0x00, 0x0E, 0x11, 0x1F, 0x11, 0x0E, 0x00, 0x00, // 16. animated play icon frame 3
|
|
||||||
};
|
|
||||||
|
|
||||||
/*************************************************************/
|
|
||||||
/********************** LOCAL FUNCTIONS **********************/
|
|
||||||
/*************************************************************/
|
|
||||||
|
|
||||||
void lcdInitHW(void)
|
|
||||||
{
|
|
||||||
// initialize I/O ports
|
|
||||||
// if I/O interface is in use
|
|
||||||
#ifdef LCD_PORT_INTERFACE
|
|
||||||
// initialize LCD control lines
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_RS);
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_RW);
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_E);
|
|
||||||
// initialize LCD control lines to output
|
|
||||||
sbi(LCD_CTRL_DDR, LCD_CTRL_RS);
|
|
||||||
sbi(LCD_CTRL_DDR, LCD_CTRL_RW);
|
|
||||||
sbi(LCD_CTRL_DDR, LCD_CTRL_E);
|
|
||||||
// initialize LCD data port to input
|
|
||||||
// initialize LCD data lines to pull-up
|
|
||||||
#ifdef LCD_DATA_4BIT
|
|
||||||
outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F); // set data I/O lines to input (4bit)
|
|
||||||
outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0); // set pull-ups to on (4bit)
|
|
||||||
#else
|
|
||||||
outb(LCD_DATA_DDR, 0x00); // set data I/O lines to input (8bit)
|
|
||||||
outb(LCD_DATA_POUT, 0xFF); // set pull-ups to on (8bit)
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
// enable external memory bus if not already enabled
|
|
||||||
sbi(MCUCR, SRE); // enable bus interface
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void lcdBusyWait(void)
|
|
||||||
{
|
|
||||||
// wait until LCD busy bit goes to zero
|
|
||||||
// do a read from control register
|
|
||||||
#ifdef LCD_PORT_INTERFACE
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_RS); // set RS to "control"
|
|
||||||
#ifdef LCD_DATA_4BIT
|
|
||||||
outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F); // set data I/O lines to input (4bit)
|
|
||||||
outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0); // set pull-ups to on (4bit)
|
|
||||||
#else
|
|
||||||
outb(LCD_DATA_DDR, 0x00); // set data I/O lines to input (8bit)
|
|
||||||
outb(LCD_DATA_POUT, 0xFF); // set pull-ups to on (8bit)
|
|
||||||
#endif
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_RW); // set R/W to "read"
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
while(inb(LCD_DATA_PIN) & 1<<LCD_BUSY)
|
|
||||||
{
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
#ifdef LCD_DATA_4BIT // do an extra clock for 4 bit reads
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
|
|
||||||
// leave data lines in input mode so they can be most easily used for other purposes
|
|
||||||
#else
|
|
||||||
// memory bus read
|
|
||||||
// sbi(MCUCR, SRW); // enable RAM waitstate
|
|
||||||
// wait until LCD busy bit goes to zero
|
|
||||||
while( (*((volatile unsigned char *) (LCD_CTRL_ADDR))) & (1<<LCD_BUSY) );
|
|
||||||
// cbi(MCUCR, SRW); // disable RAM waitstate
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void lcdControlWrite(u08 data)
|
|
||||||
{
|
|
||||||
// write the control byte to the display controller
|
|
||||||
#ifdef LCD_PORT_INTERFACE
|
|
||||||
lcdBusyWait(); // wait until LCD not busy
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_RS); // set RS to "control"
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_RW); // set R/W to "write"
|
|
||||||
#ifdef LCD_DATA_4BIT
|
|
||||||
// 4 bit write
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
|
|
||||||
outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)|0xF0); // set data I/O lines to output (4bit)
|
|
||||||
outb(LCD_DATA_POUT, (inb(LCD_DATA_POUT)&0x0F) | (data&0xF0) ); // output data, high 4 bits
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
|
|
||||||
outb(LCD_DATA_POUT, (inb(LCD_DATA_POUT)&0x0F) | (data<<4) ); // output data, low 4 bits
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
|
|
||||||
#else
|
|
||||||
// 8 bit write
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
|
|
||||||
outb(LCD_DATA_DDR, 0xFF); // set data I/O lines to output (8bit)
|
|
||||||
outb(LCD_DATA_POUT, data); // output data, 8bits
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
|
|
||||||
#endif
|
|
||||||
// leave data lines in input mode so they can be most easily used for other purposes
|
|
||||||
#ifdef LCD_DATA_4BIT
|
|
||||||
outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F); // set data I/O lines to input (4bit)
|
|
||||||
outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0); // set pull-ups to on (4bit)
|
|
||||||
#else
|
|
||||||
outb(LCD_DATA_DDR, 0x00); // set data I/O lines to input (8bit)
|
|
||||||
outb(LCD_DATA_POUT, 0xFF); // set pull-ups to on (8bit)
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
// memory bus write
|
|
||||||
//sbi(MCUCR, SRW); // enable RAM waitstate
|
|
||||||
lcdBusyWait(); // wait until LCD not busy
|
|
||||||
*((volatile unsigned char *) (LCD_CTRL_ADDR)) = data;
|
|
||||||
//cbi(MCUCR, SRW); // disable RAM waitstate
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 lcdControlRead(void)
|
|
||||||
{
|
|
||||||
// read the control byte from the display controller
|
|
||||||
register u08 data;
|
|
||||||
#ifdef LCD_PORT_INTERFACE
|
|
||||||
lcdBusyWait(); // wait until LCD not busy
|
|
||||||
#ifdef LCD_DATA_4BIT
|
|
||||||
outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F); // set data I/O lines to input (4bit)
|
|
||||||
outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0); // set pull-ups to on (4bit)
|
|
||||||
#else
|
|
||||||
outb(LCD_DATA_DDR, 0x00); // set data I/O lines to input (8bit)
|
|
||||||
outb(LCD_DATA_POUT, 0xFF); // set pull-ups to on (8bit)
|
|
||||||
#endif
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_RS); // set RS to "control"
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_RW); // set R/W to "read"
|
|
||||||
#ifdef LCD_DATA_4BIT
|
|
||||||
// 4 bit read
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
data = inb(LCD_DATA_PIN)&0xF0; // input data, high 4 bits
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
data |= inb(LCD_DATA_PIN)>>4; // input data, low 4 bits
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
|
|
||||||
#else
|
|
||||||
// 8 bit read
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
data = inb(LCD_DATA_PIN); // input data, 8bits
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
|
|
||||||
#endif
|
|
||||||
// leave data lines in input mode so they can be most easily used for other purposes
|
|
||||||
#else
|
|
||||||
//sbi(MCUCR, SRW); // enable RAM waitstate
|
|
||||||
lcdBusyWait(); // wait until LCD not busy
|
|
||||||
data = *((volatile unsigned char *) (LCD_CTRL_ADDR));
|
|
||||||
//cbi(MCUCR, SRW); // disable RAM waitstate
|
|
||||||
#endif
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void lcdDataWrite(u08 data)
|
|
||||||
{
|
|
||||||
// write a data byte to the display
|
|
||||||
#ifdef LCD_PORT_INTERFACE
|
|
||||||
lcdBusyWait(); // wait until LCD not busy
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_RS); // set RS to "data"
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_RW); // set R/W to "write"
|
|
||||||
#ifdef LCD_DATA_4BIT
|
|
||||||
// 4 bit write
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
|
|
||||||
outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)|0xF0); // set data I/O lines to output (4bit)
|
|
||||||
outb(LCD_DATA_POUT, (inb(LCD_DATA_POUT)&0x0F) | (data&0xF0) ); // output data, high 4 bits
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
|
|
||||||
outb(LCD_DATA_POUT, (inb(LCD_DATA_POUT)&0x0F) | (data<<4) ); // output data, low 4 bits
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
|
|
||||||
#else
|
|
||||||
// 8 bit write
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
|
|
||||||
outb(LCD_DATA_DDR, 0xFF); // set data I/O lines to output (8bit)
|
|
||||||
outb(LCD_DATA_POUT, data); // output data, 8bits
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
|
|
||||||
#endif
|
|
||||||
// leave data lines in input mode so they can be most easily used for other purposes
|
|
||||||
#ifdef LCD_DATA_4BIT
|
|
||||||
outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F); // set data I/O lines to input (4bit)
|
|
||||||
outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0); // set pull-ups to on (4bit)
|
|
||||||
#else
|
|
||||||
outb(LCD_DATA_DDR, 0x00); // set data I/O lines to input (8bit)
|
|
||||||
outb(LCD_DATA_POUT, 0xFF); // set pull-ups to on (8bit)
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
// memory bus write
|
|
||||||
//sbi(MCUCR, SRW); // enable RAM waitstate
|
|
||||||
lcdBusyWait(); // wait until LCD not busy
|
|
||||||
*((volatile unsigned char *) (LCD_DATA_ADDR)) = data;
|
|
||||||
//cbi(MCUCR, SRW); // disable RAM waitstate
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 lcdDataRead(void)
|
|
||||||
{
|
|
||||||
// read a data byte from the display
|
|
||||||
register u08 data;
|
|
||||||
#ifdef LCD_PORT_INTERFACE
|
|
||||||
lcdBusyWait(); // wait until LCD not busy
|
|
||||||
#ifdef LCD_DATA_4BIT
|
|
||||||
outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F); // set data I/O lines to input (4bit)
|
|
||||||
outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0); // set pull-ups to on (4bit)
|
|
||||||
#else
|
|
||||||
outb(LCD_DATA_DDR, 0x00); // set data I/O lines to input (8bit)
|
|
||||||
outb(LCD_DATA_POUT, 0xFF); // set pull-ups to on (8bit)
|
|
||||||
#endif
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_RS); // set RS to "data"
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_RW); // set R/W to "read"
|
|
||||||
#ifdef LCD_DATA_4BIT
|
|
||||||
// 4 bit read
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
data = inb(LCD_DATA_PIN)&0xF0; // input data, high 4 bits
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
data |= inb(LCD_DATA_PIN)>>4; // input data, low 4 bits
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
|
|
||||||
#else
|
|
||||||
// 8 bit read
|
|
||||||
sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
LCD_DELAY; // wait
|
|
||||||
data = inb(LCD_DATA_PIN); // input data, 8bits
|
|
||||||
cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
|
|
||||||
#endif
|
|
||||||
// leave data lines in input mode so they can be most easily used for other purposes
|
|
||||||
#else
|
|
||||||
// memory bus read
|
|
||||||
//sbi(MCUCR, SRW); // enable RAM waitstate
|
|
||||||
lcdBusyWait(); // wait until LCD not busy
|
|
||||||
data = *((volatile unsigned char *) (LCD_DATA_ADDR));
|
|
||||||
//cbi(MCUCR, SRW); // disable RAM waitstate
|
|
||||||
#endif
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************/
|
|
||||||
/********************* PUBLIC FUNCTIONS **********************/
|
|
||||||
/*************************************************************/
|
|
||||||
|
|
||||||
void lcdInit()
|
|
||||||
{
|
|
||||||
// initialize hardware
|
|
||||||
lcdInitHW();
|
|
||||||
// LCD function set
|
|
||||||
lcdControlWrite(LCD_FUNCTION_DEFAULT);
|
|
||||||
// clear LCD
|
|
||||||
lcdControlWrite(1<<LCD_CLR);
|
|
||||||
delay(60000); // wait 60ms
|
|
||||||
// set entry mode
|
|
||||||
lcdControlWrite(1<<LCD_ENTRY_MODE | 1<<LCD_ENTRY_INC);
|
|
||||||
// set display to on
|
|
||||||
//lcdControlWrite(1<<LCD_ON_CTRL | 1<<LCD_ON_DISPLAY | 1<<LCD_ON_BLINK);
|
|
||||||
lcdControlWrite(1<<LCD_ON_CTRL | 1<<LCD_ON_DISPLAY );
|
|
||||||
// move cursor to home
|
|
||||||
lcdControlWrite(1<<LCD_HOME);
|
|
||||||
// set data address to 0
|
|
||||||
lcdControlWrite(1<<LCD_DDRAM | 0x00);
|
|
||||||
|
|
||||||
// load the first 8 custom characters
|
|
||||||
lcdLoadCustomChar((u08*)LcdCustomChar,0,0);
|
|
||||||
lcdLoadCustomChar((u08*)LcdCustomChar,1,1);
|
|
||||||
lcdLoadCustomChar((u08*)LcdCustomChar,2,2);
|
|
||||||
lcdLoadCustomChar((u08*)LcdCustomChar,3,3);
|
|
||||||
lcdLoadCustomChar((u08*)LcdCustomChar,4,4);
|
|
||||||
lcdLoadCustomChar((u08*)LcdCustomChar,5,5);
|
|
||||||
lcdLoadCustomChar((u08*)LcdCustomChar,6,6);
|
|
||||||
lcdLoadCustomChar((u08*)LcdCustomChar,7,7);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lcdHome(void)
|
|
||||||
{
|
|
||||||
// move cursor to home
|
|
||||||
lcdControlWrite(1<<LCD_HOME);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lcdClear(void)
|
|
||||||
{
|
|
||||||
// clear LCD
|
|
||||||
lcdControlWrite(1<<LCD_CLR);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lcdGotoXY(u08 x, u08 y)
|
|
||||||
{
|
|
||||||
register u08 DDRAMAddr;
|
|
||||||
|
|
||||||
// remap lines into proper order
|
|
||||||
switch(y)
|
|
||||||
{
|
|
||||||
case 0: DDRAMAddr = LCD_LINE0_DDRAMADDR+x; break;
|
|
||||||
case 1: DDRAMAddr = LCD_LINE1_DDRAMADDR+x; break;
|
|
||||||
case 2: DDRAMAddr = LCD_LINE2_DDRAMADDR+x; break;
|
|
||||||
case 3: DDRAMAddr = LCD_LINE3_DDRAMADDR+x; break;
|
|
||||||
default: DDRAMAddr = LCD_LINE0_DDRAMADDR+x;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set data address
|
|
||||||
lcdControlWrite(1<<LCD_DDRAM | DDRAMAddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void lcdLoadCustomChar(u08* lcdCustomCharArray, u08 romCharNum, u08 lcdCharNum)
|
|
||||||
{
|
|
||||||
register u08 i;
|
|
||||||
u08 saveDDRAMAddr;
|
|
||||||
|
|
||||||
// backup the current cursor position
|
|
||||||
saveDDRAMAddr = lcdControlRead() & 0x7F;
|
|
||||||
|
|
||||||
// multiply the character index by 8
|
|
||||||
lcdCharNum = (lcdCharNum<<3); // each character occupies 8 bytes
|
|
||||||
romCharNum = (romCharNum<<3); // each character occupies 8 bytes
|
|
||||||
|
|
||||||
// copy the 8 bytes into CG (character generator) RAM
|
|
||||||
for(i=0; i<8; i++)
|
|
||||||
{
|
|
||||||
// set CG RAM address
|
|
||||||
lcdControlWrite((1<<LCD_CGRAM) | (lcdCharNum+i));
|
|
||||||
// write character data
|
|
||||||
lcdDataWrite( pgm_read_byte(lcdCustomCharArray+romCharNum+i) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// restore the previous cursor position
|
|
||||||
lcdControlWrite(1<<LCD_DDRAM | saveDDRAMAddr);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void lcdPrintData(char* data, u08 nBytes)
|
|
||||||
{
|
|
||||||
register u08 i;
|
|
||||||
|
|
||||||
// check to make sure we have a good pointer
|
|
||||||
if (!data) return;
|
|
||||||
|
|
||||||
// print data
|
|
||||||
for(i=0; i<nBytes; i++)
|
|
||||||
{
|
|
||||||
lcdDataWrite(data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void lcdProgressBar(u16 progress, u16 maxprogress, u08 length)
|
|
||||||
{
|
|
||||||
u08 i;
|
|
||||||
u32 pixelprogress;
|
|
||||||
u08 c;
|
|
||||||
|
|
||||||
// draw a progress bar displaying (progress / maxprogress)
|
|
||||||
// starting from the current cursor position
|
|
||||||
// with a total length of "length" characters
|
|
||||||
// ***note, LCD chars 0-5 must be programmed as the bar characters
|
|
||||||
// char 0 = empty ... char 5 = full
|
|
||||||
|
|
||||||
// total pixel length of bargraph equals length*PROGRESSPIXELS_PER_CHAR;
|
|
||||||
// pixel length of bar itself is
|
|
||||||
pixelprogress = ((progress*(length*PROGRESSPIXELS_PER_CHAR))/maxprogress);
|
|
||||||
|
|
||||||
// print exactly "length" characters
|
|
||||||
for(i=0; i<length; i++)
|
|
||||||
{
|
|
||||||
// check if this is a full block, or partial or empty
|
|
||||||
// (u16) cast is needed to avoid sign comparison warning
|
|
||||||
if( ((i*(u16)PROGRESSPIXELS_PER_CHAR)+5) > pixelprogress )
|
|
||||||
{
|
|
||||||
// this is a partial or empty block
|
|
||||||
if( ((i*(u16)PROGRESSPIXELS_PER_CHAR)) > pixelprogress )
|
|
||||||
{
|
|
||||||
// this is an empty block
|
|
||||||
// use space character?
|
|
||||||
c = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// this is a partial block
|
|
||||||
c = pixelprogress % PROGRESSPIXELS_PER_CHAR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// this is a full block
|
|
||||||
c = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
// write character to display
|
|
||||||
lcdDataWrite(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,139 +0,0 @@
|
|||||||
/*! \file lcd.h \brief Character LCD driver for HD44780/SED1278 displays. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'lcd.h'
|
|
||||||
// Title : Character LCD driver for HD44780/SED1278 displays
|
|
||||||
// (usable in mem-mapped, or I/O mode)
|
|
||||||
// Author : Pascal Stang
|
|
||||||
// Created : 11/22/2000
|
|
||||||
// Revised : 4/30/2002
|
|
||||||
// Version : 1.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef LCD_H
|
|
||||||
#define LCD_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
// include project-dependent configurations
|
|
||||||
#include "lcdconf.h"
|
|
||||||
|
|
||||||
// HD44780 LCD controller command set (do not modify these)
|
|
||||||
// writing:
|
|
||||||
#define LCD_CLR 0 // DB0: clear display
|
|
||||||
#define LCD_HOME 1 // DB1: return to home position
|
|
||||||
#define LCD_ENTRY_MODE 2 // DB2: set entry mode
|
|
||||||
#define LCD_ENTRY_INC 1 // DB1: increment
|
|
||||||
#define LCD_ENTRY_SHIFT 0 // DB2: shift
|
|
||||||
#define LCD_ON_CTRL 3 // DB3: turn lcd/cursor on
|
|
||||||
#define LCD_ON_DISPLAY 2 // DB2: turn display on
|
|
||||||
#define LCD_ON_CURSOR 1 // DB1: turn cursor on
|
|
||||||
#define LCD_ON_BLINK 0 // DB0: blinking cursor
|
|
||||||
#define LCD_MOVE 4 // DB4: move cursor/display
|
|
||||||
#define LCD_MOVE_DISP 3 // DB3: move display (0-> move cursor)
|
|
||||||
#define LCD_MOVE_RIGHT 2 // DB2: move right (0-> left)
|
|
||||||
#define LCD_FUNCTION 5 // DB5: function set
|
|
||||||
#define LCD_FUNCTION_8BIT 4 // DB4: set 8BIT mode (0->4BIT mode)
|
|
||||||
#define LCD_FUNCTION_2LINES 3 // DB3: two lines (0->one line)
|
|
||||||
#define LCD_FUNCTION_10DOTS 2 // DB2: 5x10 font (0->5x7 font)
|
|
||||||
#define LCD_CGRAM 6 // DB6: set CG RAM address
|
|
||||||
#define LCD_DDRAM 7 // DB7: set DD RAM address
|
|
||||||
// reading:
|
|
||||||
#define LCD_BUSY 7 // DB7: LCD is busy
|
|
||||||
|
|
||||||
// Default LCD setup
|
|
||||||
// this default setup is loaded on LCD initialization
|
|
||||||
#ifdef LCD_DATA_4BIT
|
|
||||||
#define LCD_FDEF_1 (0<<LCD_FUNCTION_8BIT)
|
|
||||||
#else
|
|
||||||
#define LCD_FDEF_1 (1<<LCD_FUNCTION_8BIT)
|
|
||||||
#endif
|
|
||||||
#define LCD_FDEF_2 (1<<LCD_FUNCTION_2LINES)
|
|
||||||
#define LCD_FUNCTION_DEFAULT ((1<<LCD_FUNCTION) | LCD_FDEF_1 | LCD_FDEF_2)
|
|
||||||
#define LCD_MODE_DEFAULT ((1<<LCD_ENTRY_MODE) | (1<<LCD_ENTRY_INC))
|
|
||||||
|
|
||||||
// custom LCD characters
|
|
||||||
extern unsigned char __attribute__ ((progmem)) LcdCustomChar[];
|
|
||||||
#define LCDCHAR_PROGRESS05 0 // 0/5 full progress block
|
|
||||||
#define LCDCHAR_PROGRESS15 1 // 1/5 full progress block
|
|
||||||
#define LCDCHAR_PROGRESS25 2 // 2/5 full progress block
|
|
||||||
#define LCDCHAR_PROGRESS35 3 // 3/5 full progress block
|
|
||||||
#define LCDCHAR_PROGRESS45 4 // 4/5 full progress block
|
|
||||||
#define LCDCHAR_PROGRESS55 5 // 5/5 full progress block
|
|
||||||
#define LCDCHAR_REWINDARROW 6 // rewind arrow
|
|
||||||
#define LCDCHAR_STOPBLOCK 7 // stop block
|
|
||||||
#define LCDCHAR_PAUSEBARS 8 // pause bars
|
|
||||||
#define LCDCHAR_FORWARDARROW 9 // fast-forward arrow
|
|
||||||
#define LCDCHAR_SCROLLUPARROW 10 // scroll up arrow
|
|
||||||
#define LCDCHAR_SCROLLDNARROW 11 // scroll down arrow
|
|
||||||
#define LCDCHAR_BLANK 12 // scroll down arrow
|
|
||||||
#define LCDCHAR_ANIPLAYICON0 13 // animated play icon frame 0
|
|
||||||
#define LCDCHAR_ANIPLAYICON1 14 // animated play icon frame 1
|
|
||||||
#define LCDCHAR_ANIPLAYICON2 15 // animated play icon frame 2
|
|
||||||
#define LCDCHAR_ANIPLAYICON3 16 // animated play icon frame 3
|
|
||||||
|
|
||||||
// progress bar defines
|
|
||||||
#define PROGRESSPIXELS_PER_CHAR 6
|
|
||||||
|
|
||||||
|
|
||||||
// ****** Low-level functions ******
|
|
||||||
// the following functions are the only ones which deal with the CPU
|
|
||||||
// memory or port pins directly. If you decide to use a fundamentally
|
|
||||||
// different hardware interface to your LCD, only these functions need
|
|
||||||
// to be changed, after which all the high-level functions will
|
|
||||||
// work again.
|
|
||||||
|
|
||||||
// initializes I/O pins connected to LCD
|
|
||||||
void lcdInitHW(void);
|
|
||||||
// waits until LCD is not busy
|
|
||||||
void lcdBusyWait(void);
|
|
||||||
// writes a control command to the LCD
|
|
||||||
void lcdControlWrite(u08 data);
|
|
||||||
// read the control status from the LCD
|
|
||||||
u08 lcdControlRead(void);
|
|
||||||
// writes a data byte to the LCD screen at the current position
|
|
||||||
void lcdDataWrite(u08 data);
|
|
||||||
// reads the data byte on the LCD screen at the current position
|
|
||||||
u08 lcdDataRead(void);
|
|
||||||
|
|
||||||
|
|
||||||
// ****** High-levlel functions ******
|
|
||||||
// these functions provide the high-level control of the LCD
|
|
||||||
// such as clearing the display, setting cursor positions,
|
|
||||||
// displaying text and special characters
|
|
||||||
|
|
||||||
// initializes the LCD display (gets it ready for use)
|
|
||||||
void lcdInit(void);
|
|
||||||
|
|
||||||
// moves the cursor/position to Home (upper left corner)
|
|
||||||
void lcdHome(void);
|
|
||||||
|
|
||||||
// clears the LCD display
|
|
||||||
void lcdClear(void);
|
|
||||||
|
|
||||||
// moves the cursor/position to the row,col requested
|
|
||||||
// ** this may not be accurate for all displays
|
|
||||||
void lcdGotoXY(u08 row, u08 col);
|
|
||||||
|
|
||||||
// loads a special user-defined character into the LCD
|
|
||||||
// <lcdCustomCharArray> is a pointer to a ROM array containing custom characters
|
|
||||||
// <romCharNum> is the index of the character to load from lcdCustomCharArray
|
|
||||||
// <lcdCharNum> is the RAM location in the LCD (legal value: 0-7)
|
|
||||||
void lcdLoadCustomChar(u08* lcdCustomCharArray, u08 romCharNum, u08 lcdCharNum);
|
|
||||||
|
|
||||||
// prints a series of bytes/characters to the display
|
|
||||||
void lcdPrintData(char* data, u08 nBytes);
|
|
||||||
|
|
||||||
// displays a horizontal progress bar at the current cursor location
|
|
||||||
// <progress> is the value the bargraph should indicate
|
|
||||||
// <maxprogress> is the value at the end of the bargraph
|
|
||||||
// <length> is the number of LCD characters that the bargraph should cover
|
|
||||||
void lcdProgressBar(u16 progress, u16 maxprogress, u08 length);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,111 +0,0 @@
|
|||||||
/*! \file lis3l02.c \brief ST LIS3L02 3-axis I2C Accelerometer Library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'lis3l02.c'
|
|
||||||
// Title : ST LIS3L02 3-axis I2C Accelerometer Library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2004
|
|
||||||
// Created : 2004.10.23
|
|
||||||
// Revised : 2004.12.14
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/signal.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include "i2c.h"
|
|
||||||
#include "lis3l02.h"
|
|
||||||
|
|
||||||
#include "rprintf.h"
|
|
||||||
#include "timer.h"
|
|
||||||
|
|
||||||
// global variables
|
|
||||||
|
|
||||||
// Functions
|
|
||||||
u08 lis3l02Init(void)
|
|
||||||
{
|
|
||||||
// reset LIS3L02 chip
|
|
||||||
return lis3l02Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 lis3l02Reset(void)
|
|
||||||
{
|
|
||||||
// turn on device and enable X,Y,Z
|
|
||||||
lis3l02WriteReg(LIS3L02_REG_CTRLREG1,
|
|
||||||
LIS3L02_CTRLREG1_XEN |
|
|
||||||
LIS3L02_CTRLREG1_YEN |
|
|
||||||
LIS3L02_CTRLREG1_ZEN |
|
|
||||||
LIS3L02_CTRLREG1_PD0);
|
|
||||||
|
|
||||||
// scale and justification options
|
|
||||||
lis3l02WriteReg(LIS3L02_REG_CTRLREG2,
|
|
||||||
LIS3L02_CTRLREG2_BOOT |
|
|
||||||
LIS3L02_CTRLREG2_DAS );
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 lis3l02ReadReg(u08 reg)
|
|
||||||
{
|
|
||||||
u08 data;
|
|
||||||
u08 i2cStat;
|
|
||||||
|
|
||||||
// set register
|
|
||||||
i2cStat = i2cMasterSendNI(LIS3L02_I2C_ADDR, 1, ®);
|
|
||||||
if(i2cStat == I2C_ERROR_NODEV)
|
|
||||||
{
|
|
||||||
rprintf("No I2C Device\r\n");
|
|
||||||
return i2cStat;
|
|
||||||
}
|
|
||||||
// read register
|
|
||||||
i2cStat = i2cMasterReceiveNI(LIS3L02_I2C_ADDR, 1, &data);
|
|
||||||
|
|
||||||
//rprintf("READ: Reg=0x%x Data=0x%x\r\n", reg, data);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 lis3l02WriteReg(u08 reg, u08 data)
|
|
||||||
{
|
|
||||||
u08 packet[2];
|
|
||||||
u08 i2cStat;
|
|
||||||
|
|
||||||
// prepare packet
|
|
||||||
packet[0] = reg;
|
|
||||||
packet[1] = data;
|
|
||||||
// write register
|
|
||||||
i2cStat = i2cMasterSendNI(LIS3L02_I2C_ADDR, 2, packet);
|
|
||||||
if(i2cStat == I2C_ERROR_NODEV)
|
|
||||||
{
|
|
||||||
rprintf("No I2C Device\r\n");
|
|
||||||
return i2cStat;
|
|
||||||
}
|
|
||||||
|
|
||||||
//rprintf("WRITE: Reg=0x%x Data=0x%x\r\n", reg, data);
|
|
||||||
|
|
||||||
return (i2cStat == I2C_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
s16 lis3l02GetAccel(u08 chxyz)
|
|
||||||
{
|
|
||||||
s16 value;
|
|
||||||
|
|
||||||
value = lis3l02ReadReg(LIS3L02_REG_OUTXL + (chxyz<<1));
|
|
||||||
value |= lis3l02ReadReg(LIS3L02_REG_OUTXH + (chxyz<<1))<<8;
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,113 +0,0 @@
|
|||||||
/*! \file lis3l02.h \brief ST LIS3L02 3-axis I2C Accelerometer Library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'lis3l02.h'
|
|
||||||
// Title : ST LIS3L02 3-axis I2C Accelerometer Library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2004
|
|
||||||
// Created : 2004.10.23
|
|
||||||
// Revised : 2004.12.14
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef LIS3L02_H
|
|
||||||
#define LIS3L02_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
// constants/macros/typdefs
|
|
||||||
#define LIS3L02_I2C_ADDR 0x3A //< Base I2C address of LIS3L02 device
|
|
||||||
|
|
||||||
// LIS3L02 register address defines
|
|
||||||
#define LIS3L02_REG_OFFSETX 0x16 //< LIS3L02 X-axis digital offset trim
|
|
||||||
#define LIS3L02_REG_OFFSETY 0x17 //< LIS3L02 Y-axis digital offset trim
|
|
||||||
#define LIS3L02_REG_OFFSETZ 0x18 //< LIS3L02 Z-axis digital offset trim
|
|
||||||
#define LIS3L02_REG_GAINX 0x19 //< LIS3L02 X-axis digital gain trim
|
|
||||||
#define LIS3L02_REG_GAINY 0x1A //< LIS3L02 Y-axis digital gain trim
|
|
||||||
#define LIS3L02_REG_GAINZ 0x1B //< LIS3L02 Z-axis digital gain trim
|
|
||||||
#define LIS3L02_REG_CTRLREG1 0x20 //< LIS3L02 interface/operation control
|
|
||||||
#define LIS3L02_REG_CTRLREG2 0x21 //< LIS3L02 interface/operation control
|
|
||||||
#define LIS3L02_REG_WAKEUPCFG 0x23 //< LIS3L02 interrupt/wakeup config
|
|
||||||
#define LIS3L02_REG_WAKEUPSRC 0x24 //< LIS3L02 interrupt/wakeup source indicator
|
|
||||||
#define LIS3L02_REG_WAKEUPACK 0x25 //< LIS3L02 wakeup source clear
|
|
||||||
#define LIS3L02_REG_STATUS 0x27 //< LIS3L02 Accelerometer Status
|
|
||||||
#define LIS3L02_REG_OUTXL 0x28 //< LIS3L02 Accelerometer X Output Low-byte
|
|
||||||
#define LIS3L02_REG_OUTXH 0x29 //< LIS3L02 Accelerometer X Output High-byte
|
|
||||||
#define LIS3L02_REG_OUTYL 0x2A //< LIS3L02 Accelerometer Y Output Low-byte
|
|
||||||
#define LIS3L02_REG_OUTYH 0x2B //< LIS3L02 Accelerometer Y Output High-byte
|
|
||||||
#define LIS3L02_REG_OUTZL 0x2C //< LIS3L02 Accelerometer Z Output Low-byte
|
|
||||||
#define LIS3L02_REG_OUTZH 0x2D //< LIS3L02 Accelerometer Z Output High-byte
|
|
||||||
#define LIS3L02_REG_THSL 0x2E //< LIS3L02 Accelerometer Threshold Low-byte
|
|
||||||
#define LIS3L02_REG_THSH 0x2F //< LIS3L02 Accelerometer Threshold High-byte
|
|
||||||
#define LIS3L02_REG_MULTIREAD 0x80 //< LIS3L02 Mutliple Read Bit
|
|
||||||
|
|
||||||
// LIS3L02 control register 1 bit defines
|
|
||||||
#define LIS3L02_CTRLREG1_XEN 0x01 //< LIS3L02 CtrlReg1 X-axis Enable
|
|
||||||
#define LIS3L02_CTRLREG1_YEN 0x02 //< LIS3L02 CtrlReg1 Y-axis Enable
|
|
||||||
#define LIS3L02_CTRLREG1_ZEN 0x04 //< LIS3L02 CtrlReg1 Z-axis Enable
|
|
||||||
#define LIS3L02_CTRLREG1_ST 0x08 //< LIS3L02 CtrlReg1 Self-Test Enable
|
|
||||||
#define LIS3L02_CTRLREG1_DF0 0x10 //< LIS3L02 CtrlReg1 Decimation Factor 0
|
|
||||||
#define LIS3L02_CTRLREG1_DF1 0x20 //< LIS3L02 CtrlReg1 Decimation Factor 0
|
|
||||||
#define LIS3L02_CTRLREG1_PD0 0x40 //< LIS3L02 CtrlReg1 Power-down Control 0
|
|
||||||
#define LIS3L02_CTRLREG1_PD1 0x80 //< LIS3L02 CtrlReg1 Power-down Control 1
|
|
||||||
|
|
||||||
// LIS3L02 control register 2 bit defines
|
|
||||||
#define LIS3L02_CTRLREG2_DAS 0x01 //< LIS3L02 CtrlReg2 Data Alignment Selection
|
|
||||||
#define LIS3L02_CTRLREG2_SIM 0x02 //< LIS3L02 CtrlReg2 SPI Mode Select
|
|
||||||
#define LIS3L02_CTRLREG2_DRDY 0x04 //< LIS3L02 CtrlReg2 Enable Data-Ready generation
|
|
||||||
#define LIS3L02_CTRLREG2_IEN 0x08 //< LIS3L02 CtrlReg2 Interrupt Enable
|
|
||||||
#define LIS3L02_CTRLREG2_BOOT 0x10 //< LIS3L02 CtrlReg2 Reboot from memory
|
|
||||||
#define LIS3L02_CTRLREG2_FS 0x80 //< LIS3L02 CtrlReg2 Full-scale Select (0=2g, 1=6g)
|
|
||||||
|
|
||||||
// LIS3L02 WAKEUPCFG register bit defines
|
|
||||||
#define LIS3L02_WAKEUPCFG_MXL 0x01 //< LIS3L02 WAKEUPCFG Mask X Low Interrupt
|
|
||||||
#define LIS3L02_WAKEUPCFG_MXH 0x02 //< LIS3L02 WAKEUPCFG Mask X High Interrupt
|
|
||||||
#define LIS3L02_WAKEUPCFG_MYL 0x04 //< LIS3L02 WAKEUPCFG Mask Y Low Interrupt
|
|
||||||
#define LIS3L02_WAKEUPCFG_MYH 0x08 //< LIS3L02 WAKEUPCFG Mask Y High Interrupt
|
|
||||||
#define LIS3L02_WAKEUPCFG_MZL 0x10 //< LIS3L02 WAKEUPCFG Mask Z Low Interrupt
|
|
||||||
#define LIS3L02_WAKEUPCFG_MZH 0x20 //< LIS3L02 WAKEUPCFG Mask Z High Interrupt
|
|
||||||
#define LIS3L02_WAKEUPCFG_LIR 0x40 //< LIS3L02 WAKEUPCFG Latch Intr Request
|
|
||||||
|
|
||||||
// LIS3L02 WAKEUPSRC register bit defines
|
|
||||||
#define LIS3L02_WAKEUPSRC_XL 0x01 //< LIS3L02 WAKEUPSRC X Low Interrupt
|
|
||||||
#define LIS3L02_WAKEUPSRC_XH 0x02 //< LIS3L02 WAKEUPSRC X High Interrupt
|
|
||||||
#define LIS3L02_WAKEUPSRC_YL 0x04 //< LIS3L02 WAKEUPSRC Y Low Interrupt
|
|
||||||
#define LIS3L02_WAKEUPSRC_YH 0x08 //< LIS3L02 WAKEUPSRC Y High Interrupt
|
|
||||||
#define LIS3L02_WAKEUPSRC_ZL 0x10 //< LIS3L02 WAKEUPSRC Z Low Interrupt
|
|
||||||
#define LIS3L02_WAKEUPSRC_ZH 0x20 //< LIS3L02 WAKEUPSRC Z High Interrupt
|
|
||||||
#define LIS3L02_WAKEUPSRC_IA 0x40 //< LIS3L02 WAKEUPSRC Interrupt Active
|
|
||||||
|
|
||||||
// LIS3L02 WAKEUPSRC register bit defines
|
|
||||||
#define LIS3L02_STATUS_XDA 0x01 //< LIS3L02 STATUS X New Data Available
|
|
||||||
#define LIS3L02_STATUS_YDA 0x02 //< LIS3L02 STATUS Y New Data Available
|
|
||||||
#define LIS3L02_STATUS_ZDA 0x04 //< LIS3L02 STATUS Z New Data Available
|
|
||||||
#define LIS3L02_STATUS_ZYXDA 0x08 //< LIS3L02 STATUS XYZ New Data Available
|
|
||||||
#define LIS3L02_STATUS_XOR 0x10 //< LIS3L02 STATUS X-axis Data Overrun
|
|
||||||
#define LIS3L02_STATUS_YOR 0x20 //< LIS3L02 STATUS Y-axis Data Overrun
|
|
||||||
#define LIS3L02_STATUS_ZOR 0x40 //< LIS3L02 STATUS Z-axis Data Overrun
|
|
||||||
#define LIS3L02_STATUS_ZYXOR 0x80 //< LIS3L02 STATUS XYZ-axis Data Overrun
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
//! Initialize the LIS3L02 chip
|
|
||||||
// returns:
|
|
||||||
// 0 if successful
|
|
||||||
// non-zero if unsuccessful (chip not present)
|
|
||||||
u08 lis3l02Init(void);
|
|
||||||
u08 lis3l02Reset(void);
|
|
||||||
|
|
||||||
u08 lis3l02ReadReg(u08 reg);
|
|
||||||
u08 lis3l02WriteReg(u08 reg, u08 data);
|
|
||||||
|
|
||||||
s16 lis3l02GetAccel(u08 chxyz);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,113 +0,0 @@
|
|||||||
#----------------------------------------------------------------------------------
|
|
||||||
# ARM-GCC standard Makefile
|
|
||||||
# This makefile is to be used by including it from a project-specific makefile
|
|
||||||
# which defines the source files and compiler/linker options
|
|
||||||
#
|
|
||||||
# Written by Pascal Stang
|
|
||||||
# Based on Volker Oth's AVR makefiles of jan.2000
|
|
||||||
# ---------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
###### BLOCK 1) define some variables based on the AVR base path in $(AVR) #######
|
|
||||||
|
|
||||||
CC = avr-gcc
|
|
||||||
AS = avr-gcc -x assembler-with-cpp
|
|
||||||
RM = rm -f
|
|
||||||
RN = mv
|
|
||||||
CP = cp
|
|
||||||
BIN = avr-objcopy
|
|
||||||
SIZE = avr-size
|
|
||||||
INCDIR = .
|
|
||||||
# LIBDIR = $(AVR)/avr/lib
|
|
||||||
# SHELL = $(AVR)/bin/sh.exe
|
|
||||||
|
|
||||||
|
|
||||||
###### BLOCK 2) output format can be srec, ihex (avrobj is always created) #######
|
|
||||||
|
|
||||||
FORMAT = ihex
|
|
||||||
|
|
||||||
|
|
||||||
###### BLOCK 3) define all project specific object files ######
|
|
||||||
|
|
||||||
SRC += $(addprefix $(AVRLIB)/,$(AVRLIB_SRC))
|
|
||||||
OBJ = $(ASRC:.s=.o) $(SRC:.c=.o)
|
|
||||||
CPFLAGS += -mmcu=$(MCU)
|
|
||||||
ASFLAGS += -mmcu=$(MCU)
|
|
||||||
LDFLAGS += -mmcu=$(MCU)
|
|
||||||
|
|
||||||
###### BLOCK 4) this defines the aims of the make process ######
|
|
||||||
|
|
||||||
#all: $(TRG).obj $(TRG).elf $(TRG).hex $(TRG).cof $(TRG).eep $(TRG).ok
|
|
||||||
all: $(TRG).elf $(TRG).cof $(TRG).hex $(TRG).eep $(TRG).ok
|
|
||||||
|
|
||||||
|
|
||||||
###### BLOCK 5) compile: instructions to create assembler and/or object files from C source ######
|
|
||||||
|
|
||||||
%.o : %.c
|
|
||||||
$(CC) -c $(CPFLAGS) -I$(INCDIR) $< -o $@
|
|
||||||
|
|
||||||
%.s : %.c
|
|
||||||
$(CC) -S $(CPFLAGS) -I$(INCDIR) $< -o $@
|
|
||||||
|
|
||||||
|
|
||||||
###### BLOCK 6) assemble: instructions to create object file from assembler files ######
|
|
||||||
|
|
||||||
%.o : %.s
|
|
||||||
$(AS) -c $(ASFLAGS) -I$(INCDIR) $< -o $@
|
|
||||||
|
|
||||||
|
|
||||||
###### BLOCK 7) link: instructions to create elf output file from object files ######
|
|
||||||
%.elf: $(OBJ)
|
|
||||||
$(CC) $(OBJ) $(LIB) $(LDFLAGS) -o $@
|
|
||||||
|
|
||||||
###### BLOCK 8) create avrobj file from elf output file ######
|
|
||||||
|
|
||||||
#%.obj: %.elf
|
|
||||||
# $(BIN) -O avrobj -R .eeprom $< $@
|
|
||||||
|
|
||||||
|
|
||||||
###### BLOCK 9) create bin (.hex and .eep) files from elf output file ######
|
|
||||||
|
|
||||||
%.hex: %.elf
|
|
||||||
$(BIN) -O $(FORMAT) -R .eeprom $< $@
|
|
||||||
|
|
||||||
%.eep: %.elf
|
|
||||||
$(BIN) -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O $(FORMAT) $< $@
|
|
||||||
|
|
||||||
%.cof: %.elf
|
|
||||||
$(BIN) --debugging -O coff-ext-avr \
|
|
||||||
--change-section-address .data-0x800000 \
|
|
||||||
--change-section-address .bss-0x800000 \
|
|
||||||
--change-section-address .noinit-0x800000 \
|
|
||||||
--change-section-address .eeprom-0x810000 \
|
|
||||||
$< $@
|
|
||||||
|
|
||||||
|
|
||||||
###### BLOCK 10) If all other steps compile ok then echo "Errors: none" ######
|
|
||||||
|
|
||||||
%ok:
|
|
||||||
$(SIZE) $(TRG).elf
|
|
||||||
@echo "Errors: none"
|
|
||||||
|
|
||||||
|
|
||||||
###### BLOCK 11) make instruction to delete created files ######
|
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) $(OBJ)
|
|
||||||
$(RM) $(SRC:.c=.s)
|
|
||||||
$(RM) $(SRC:.c=.lst)
|
|
||||||
$(RM) $(TRG).map
|
|
||||||
$(RM) $(TRG).elf
|
|
||||||
$(RM) $(TRG).cof
|
|
||||||
$(RM) $(TRG).obj
|
|
||||||
$(RM) $(TRG).a90
|
|
||||||
$(RM) $(TRG).hex
|
|
||||||
$(RM) $(TRG).sym
|
|
||||||
$(RM) $(TRG).eep
|
|
||||||
$(RM) $(TRG).hex
|
|
||||||
$(RM) *.bak
|
|
||||||
$(RM) *.log
|
|
||||||
@echo "Errors: none"
|
|
||||||
|
|
||||||
size:
|
|
||||||
$(SIZE) $(TRG).elf
|
|
||||||
|
|
@ -1,111 +0,0 @@
|
|||||||
#----------------------------------------------------------------------------------
|
|
||||||
# GCC-AVR standard Makefile part 3
|
|
||||||
# Based on Volker Oth's makefiles of jan.2000
|
|
||||||
# Modified and merged by AVRfreaks.net for smoother integration with AVR Studio,
|
|
||||||
# and easier comprehension for the average user (nov.2001). Minor errors corrected.
|
|
||||||
# ---------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
###### BLOCK 1) define some variables based on the AVR base path in $(AVR) #######
|
|
||||||
|
|
||||||
CC = avr-gcc
|
|
||||||
AS = avr-gcc -x assembler-with-cpp
|
|
||||||
RM = rm -f
|
|
||||||
RN = mv
|
|
||||||
CP = cp
|
|
||||||
BIN = avr-objcopy
|
|
||||||
SIZE = avr-size
|
|
||||||
INCDIR = .
|
|
||||||
# LIBDIR = $(AVR)/avr/lib
|
|
||||||
# SHELL = $(AVR)/bin/sh.exe
|
|
||||||
|
|
||||||
|
|
||||||
###### BLOCK 2) output format can be srec, ihex (avrobj is always created) #######
|
|
||||||
|
|
||||||
FORMAT = ihex
|
|
||||||
|
|
||||||
|
|
||||||
###### BLOCK 3) define all project specific object files ######
|
|
||||||
|
|
||||||
SRC += $(AVRLIBSRC)
|
|
||||||
OBJ = $(ASRC:.s=.o) $(SRC:.c=.o)
|
|
||||||
CPFLAGS += -mmcu=$(MCU)
|
|
||||||
ASFLAGS += -mmcu=$(MCU)
|
|
||||||
LDFLAGS += -mmcu=$(MCU)
|
|
||||||
|
|
||||||
###### BLOCK 4) this defines the aims of the make process ######
|
|
||||||
|
|
||||||
#all: $(TRG).obj $(TRG).elf $(TRG).hex $(TRG).cof $(TRG).eep $(TRG).ok
|
|
||||||
all: $(TRG).elf $(TRG).cof $(TRG).hex $(TRG).eep $(TRG).ok
|
|
||||||
|
|
||||||
|
|
||||||
###### BLOCK 5) compile: instructions to create assembler and/or object files from C source ######
|
|
||||||
|
|
||||||
%.o : %.c
|
|
||||||
$(CC) -c $(CPFLAGS) -I$(INCDIR) $< -o $@
|
|
||||||
|
|
||||||
%.s : %.c
|
|
||||||
$(CC) -S $(CPFLAGS) -I$(INCDIR) $< -o $@
|
|
||||||
|
|
||||||
|
|
||||||
###### BLOCK 6) assemble: instructions to create object file from assembler files ######
|
|
||||||
|
|
||||||
%.o : %.s
|
|
||||||
$(AS) -c $(ASFLAGS) -I$(INCDIR) $< -o $@
|
|
||||||
|
|
||||||
|
|
||||||
###### BLOCK 7) link: instructions to create elf output file from object files ######
|
|
||||||
%.elf: $(OBJ)
|
|
||||||
$(CC) $(OBJ) $(LIB) $(LDFLAGS) -o $@
|
|
||||||
|
|
||||||
###### BLOCK 8) create avrobj file from elf output file ######
|
|
||||||
|
|
||||||
#%.obj: %.elf
|
|
||||||
# $(BIN) -O avrobj -R .eeprom $< $@
|
|
||||||
|
|
||||||
|
|
||||||
###### BLOCK 9) create bin (.hex and .eep) files from elf output file ######
|
|
||||||
|
|
||||||
%.hex: %.elf
|
|
||||||
$(BIN) -O $(FORMAT) -R .eeprom $< $@
|
|
||||||
|
|
||||||
%.eep: %.elf
|
|
||||||
$(BIN) -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O $(FORMAT) $< $@
|
|
||||||
|
|
||||||
%.cof: %.elf
|
|
||||||
$(BIN) --debugging -O coff-ext-avr \
|
|
||||||
--change-section-address .data-0x800000 \
|
|
||||||
--change-section-address .bss-0x800000 \
|
|
||||||
--change-section-address .noinit-0x800000 \
|
|
||||||
--change-section-address .eeprom-0x810000 \
|
|
||||||
$< $@
|
|
||||||
|
|
||||||
|
|
||||||
###### BLOCK 10) If all other steps compile ok then echo "Errors: none" ######
|
|
||||||
|
|
||||||
%ok:
|
|
||||||
$(SIZE) $(TRG).elf
|
|
||||||
@echo "Errors: none"
|
|
||||||
|
|
||||||
|
|
||||||
###### BLOCK 11) make instruction to delete created files ######
|
|
||||||
|
|
||||||
clean:
|
|
||||||
$(RM) $(OBJ)
|
|
||||||
$(RM) $(SRC:.c=.s)
|
|
||||||
$(RM) $(SRC:.c=.lst)
|
|
||||||
$(RM) $(TRG).map
|
|
||||||
$(RM) $(TRG).elf
|
|
||||||
$(RM) $(TRG).cof
|
|
||||||
$(RM) $(TRG).obj
|
|
||||||
$(RM) $(TRG).a90
|
|
||||||
$(RM) $(TRG).hex
|
|
||||||
$(RM) $(TRG).sym
|
|
||||||
$(RM) $(TRG).eep
|
|
||||||
$(RM) $(TRG).hex
|
|
||||||
$(RM) *.bak
|
|
||||||
$(RM) *.log
|
|
||||||
@echo "Errors: none"
|
|
||||||
|
|
||||||
size:
|
|
||||||
$(SIZE) $(TRG).elf
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
|||||||
|
|
||||||
The "avrproj_make" file in this directory is an important part of the
|
|
||||||
compiling process for all AVRLib example code. Unless you are familiar with
|
|
||||||
writing your own makefiles, it is highly suggested that you use this file
|
|
||||||
to help compile your own code projects too.
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
To make "avrproj_make" work, you must have the following two environment
|
|
||||||
variables defined with appropriate values:
|
|
||||||
|
|
||||||
AVR = [path to WinAVR/AVR-GCC install directory]
|
|
||||||
AVRLIB = [path to AVRLib install directory]
|
|
||||||
|
|
||||||
For example, if you installed WinAVR in C:\WinAVR, then you should set:
|
|
||||||
|
|
||||||
AVR = c:\WinAVR
|
|
||||||
|
|
||||||
If you installed/unzipped AVRLib in c:\code\avr\avrlib, then set:
|
|
||||||
|
|
||||||
AVRLib = c:\code\avr\avrlib
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
If you are unsure how to set environment variables on your system, check the
|
|
||||||
installation guides on hubbard.engr.scu.edu/embedded or consult the web.
|
|
@ -1,175 +0,0 @@
|
|||||||
/*! \file megaio.c \brief MegaIO Control/Access function library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'megaio.c'
|
|
||||||
// Title : MegaIO Control/Access function library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2004
|
|
||||||
// Created : 5/18/2004
|
|
||||||
// Revised : 5/18/2004
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#include "buffer.h" // include buffer support
|
|
||||||
#include "i2c.h" // include I2C functions
|
|
||||||
#include "megaio/megaioreg.h" // include MegaIO register definitions
|
|
||||||
|
|
||||||
#include "megaio.h"
|
|
||||||
|
|
||||||
// MegaIO local receive buffer size
|
|
||||||
#define MEGAIO_UART_RX_BUFFER_SIZE 0x80
|
|
||||||
// MegaIO local receive buffer data array
|
|
||||||
static char megaioUartRxData[MEGAIO_UART_RX_BUFFER_SIZE];
|
|
||||||
// MegaIO local receive buffer
|
|
||||||
cBuffer megaioUartRxBuffer;
|
|
||||||
|
|
||||||
//! initialize the MegaIO interface
|
|
||||||
u08 megaioInit(void)
|
|
||||||
{
|
|
||||||
// initialize the UART receive buffer
|
|
||||||
bufferInit(&megaioUartRxBuffer, megaioUartRxData, MEGAIO_UART_RX_BUFFER_SIZE);
|
|
||||||
// initialize i2c interface
|
|
||||||
i2cInit();
|
|
||||||
i2cSetBitrate(30);
|
|
||||||
// check for presence of megaio chip
|
|
||||||
if( megaioReadReg(MEGAIOREG_IDSTRING, 1) == 'M' )
|
|
||||||
{
|
|
||||||
// megaio responded correctly
|
|
||||||
// initialization succeeded
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// megaio responded incorrectly
|
|
||||||
// initialization failed
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//! write an 8-32 bit number to a MegaIO register
|
|
||||||
void megaioWriteReg(unsigned char regnum, unsigned char nbytes, unsigned long data)
|
|
||||||
{
|
|
||||||
u08 packet[5];
|
|
||||||
|
|
||||||
// construct I2c data packet
|
|
||||||
// first byte is register address
|
|
||||||
// following bytes are the data that will be written to that register
|
|
||||||
packet[0] = regnum;
|
|
||||||
packet[1] = data;
|
|
||||||
packet[2] = data>>8;
|
|
||||||
packet[3] = data>>16;
|
|
||||||
packet[4] = data>>24;
|
|
||||||
// send 2 bytes (register and data) to MegaIO
|
|
||||||
i2cMasterSend(MEGAIO_I2C_ADDR, 1+nbytes, packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! read an 8-32 bit number from a MegaIO register
|
|
||||||
unsigned long megaioReadReg(unsigned char regnum, unsigned char nbytes)
|
|
||||||
{
|
|
||||||
unsigned long data = 0;
|
|
||||||
|
|
||||||
// first select the register by writing 1 byte (register)
|
|
||||||
i2cMasterSend(MEGAIO_I2C_ADDR, 1, ®num);
|
|
||||||
// then read n byte(s) from the selected MegaIO register
|
|
||||||
i2cMasterReceive(MEGAIO_I2C_ADDR, nbytes, (u08*)&data);
|
|
||||||
// return the results
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! set the baudrate of the megaio serial port
|
|
||||||
void megaioSetBaudRate(u32 baudrate)
|
|
||||||
{
|
|
||||||
megaioWriteReg(MEGAIOREG_UARTBAUD, 4, baudrate);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! send a byte out the megaio serial port
|
|
||||||
void megaioSendByte(u08 data)
|
|
||||||
{
|
|
||||||
megaioWriteReg(MEGAIOREG_UARTDATA, 1, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! get a byte from the megaio serial port
|
|
||||||
int megaioGetByte(void)
|
|
||||||
{
|
|
||||||
u08 data;
|
|
||||||
|
|
||||||
// check the number of bytes in the megaio receive buffer
|
|
||||||
if( megaioReadReg(MEGAIOREG_UARTRXBUFBYTES, 1) )
|
|
||||||
{
|
|
||||||
// one or more bytes are available
|
|
||||||
// get first byte
|
|
||||||
data = megaioReadReg(MEGAIOREG_UARTDATA, 1);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// no bytes were available
|
|
||||||
// (no bytes have arrived and are waiting to be read)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//! returns the receive buffer structure
|
|
||||||
cBuffer* megaioGetRxBuffer(void)
|
|
||||||
{
|
|
||||||
u08 nbytes;
|
|
||||||
// get the number of bytes waiting in the MegaIO buffer
|
|
||||||
nbytes = megaioReadReg(MEGAIOREG_UARTRXBUFBYTES, 1);
|
|
||||||
// get all available bytes from the MegaIO chip
|
|
||||||
// and add them to the receive buffer
|
|
||||||
while(megaioReadReg(MEGAIOREG_UARTRXBUFBYTES, 1))
|
|
||||||
{
|
|
||||||
bufferAddToEnd(&megaioUartRxBuffer, megaioReadReg(MEGAIOREG_UARTDATA, 1));
|
|
||||||
nbytes--;
|
|
||||||
}
|
|
||||||
// return rx buffer pointer
|
|
||||||
return &megaioUartRxBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! turn on megaio PWM and set for bitRes resolution
|
|
||||||
void megaioPWMInit(u08 bitRes)
|
|
||||||
{
|
|
||||||
megaioWriteReg(MEGAIOREG_PWM1CTRL, 1, bitRes);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! turn off megaio PWM
|
|
||||||
void megaioPWMOff(void)
|
|
||||||
{
|
|
||||||
megaioWriteReg(MEGAIOREG_PWM1CTRL, 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! set megaio PWM1A duty cycle
|
|
||||||
void megaioPWMASet(u16 pwmDuty)
|
|
||||||
{
|
|
||||||
megaioWriteReg(MEGAIOREG_PWM1ADUTY, 2, pwmDuty);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! set megaio PWM1B duty cycle
|
|
||||||
void megaioPWMBSet(u16 pwmDuty)
|
|
||||||
{
|
|
||||||
megaioWriteReg(MEGAIOREG_PWM1BDUTY, 2, pwmDuty);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! set megaio prescaler division rate
|
|
||||||
void megaioSetPrescaler(u08 prescaleDiv)
|
|
||||||
{
|
|
||||||
megaioWriteReg(MEGAIOREG_PWM1FREQ, 1, prescaleDiv);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! do A/D conversion on channel [ch] and return result
|
|
||||||
u16 megaioA2DConvert(u08 ch)
|
|
||||||
{
|
|
||||||
// set channel
|
|
||||||
megaioWriteReg(MEGAIOREG_ADCCHSEL, 1, ch);
|
|
||||||
// start single conversion
|
|
||||||
megaioWriteReg(MEGAIOREG_ADCCTRL, 1, 0x01);
|
|
||||||
// wait for conversion to be complete
|
|
||||||
while( megaioReadReg(MEGAIOREG_ADCCTRL, 1) );
|
|
||||||
// get result and return it
|
|
||||||
return megaioReadReg(MEGAIOREG_ADCRESULT, 2);
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
/*! \file megaio.h \brief MegaIO Control/Access function library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'megaio.h'
|
|
||||||
// Title : MegaIO Control/Access function library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2004
|
|
||||||
// Created : 5/18/2004
|
|
||||||
// Revised : 5/18/2004
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef MEGAIO_H
|
|
||||||
#define MEGAIO_H
|
|
||||||
|
|
||||||
#include "megaio/megaioreg.h" // include MegaIO register definitions
|
|
||||||
|
|
||||||
// defines
|
|
||||||
|
|
||||||
// function prototypes
|
|
||||||
|
|
||||||
//! initialize the MegaIO interface
|
|
||||||
u08 megaioInit(void);
|
|
||||||
//! write an 8-32 bit number to a MegaIO register
|
|
||||||
void megaioWriteReg(unsigned char regnum, unsigned char nbytes, unsigned long data);
|
|
||||||
//! read an 8-32 bit number from a MegaIO register
|
|
||||||
unsigned long megaioReadReg(unsigned char regnum, unsigned char nbytes);
|
|
||||||
|
|
||||||
//! set the baudrate of the MegaIO serial port
|
|
||||||
void megaioSetBaudRate(u32 baudrate);
|
|
||||||
//! send a byte out the MegaIO serial port
|
|
||||||
void megaioSendByte(u08 data);
|
|
||||||
//! get a byte from the MegaIO serial port
|
|
||||||
int megaioGetByte(void);
|
|
||||||
//! get a complete receive buffer with data from MegaIO serial port
|
|
||||||
cBuffer* megaioGetRxBuffer(void);
|
|
||||||
|
|
||||||
//! turn on MegaIO PWM and set for bitRes resolution
|
|
||||||
void megaioPWMInit(u08 bitRes);
|
|
||||||
//! turn off MegaIO PWM
|
|
||||||
void megaioPWMOff(void);
|
|
||||||
//! set MegaIO PWM1A duty cycle
|
|
||||||
void megaioPWMASet(u16 pwmDuty);
|
|
||||||
//! set MegaIO PWM1B duty cycle
|
|
||||||
void megaioPWMBSet(u16 pwmDuty);
|
|
||||||
//! set MegaIO prescaler division rate
|
|
||||||
void megaioSetPrescaler(u08 prescaleDiv);
|
|
||||||
|
|
||||||
//! do A/D conversion on channel [ch] and return result
|
|
||||||
u16 megaioA2DConvert(u08 ch);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,88 +0,0 @@
|
|||||||
/*! \file megaioreg.h \brief MegaIO register definitions. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'megaioreg.h'
|
|
||||||
// Title : MegaIO register definitions
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2003
|
|
||||||
// Created : 2003.07.16
|
|
||||||
// Revised : 2003.07.17
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef MEGAIOREG_H
|
|
||||||
#define MEGAIOREG_H
|
|
||||||
|
|
||||||
// define MEGAIO I2C address
|
|
||||||
#define MEGAIO_I2C_ADDR 0x4C
|
|
||||||
|
|
||||||
// define MEGAIO registers
|
|
||||||
// General Registers
|
|
||||||
#define MEGAIOREG_IDSTRING 0x00
|
|
||||||
|
|
||||||
// UART Registers
|
|
||||||
#define MEGAIOREG_UARTDATA 0x10
|
|
||||||
#define MEGAIOREG_UARTBAUD 0x14
|
|
||||||
#define MEGAIOREG_UARTBAUDSEL 0x15
|
|
||||||
#define MEGAIOREG_UARTRXBUFBYTES 0x18
|
|
||||||
#define MEGAIOREG_UARTTXBUFBYTES 0x19
|
|
||||||
|
|
||||||
// PWM Registers
|
|
||||||
#define MEGAIOREG_PWM1CTRL 0x20
|
|
||||||
#define MEGAIOREG_PWM1FREQ 0x21
|
|
||||||
#define MEGAIOREG_PWM1ADUTY 0x24
|
|
||||||
#define MEGAIOREG_PWM1BDUTY 0x25
|
|
||||||
|
|
||||||
// A/D Converter Registers
|
|
||||||
#define MEGAIOREG_ADCCTRL 0x30
|
|
||||||
#define MEGAIOREG_ADCCHSEL 0x31
|
|
||||||
#define MEGAIOREG_ADCRESULT 0x32
|
|
||||||
|
|
||||||
// PORT Access Registers
|
|
||||||
#define MEGAIOREG_PORTA 0x40
|
|
||||||
#define MEGAIOREG_DDRA 0x41
|
|
||||||
#define MEGAIOREG_PINA 0x42
|
|
||||||
#define MEGAIOREG_PORTB 0x43
|
|
||||||
#define MEGAIOREG_DDRB 0x44
|
|
||||||
#define MEGAIOREG_PINB 0x45
|
|
||||||
#define MEGAIOREG_PORTC 0x46
|
|
||||||
#define MEGAIOREG_DDRC 0x47
|
|
||||||
#define MEGAIOREG_PINC 0x48
|
|
||||||
#define MEGAIOREG_PORTD 0x49
|
|
||||||
#define MEGAIOREG_DDRD 0x4A
|
|
||||||
#define MEGAIOREG_PIND 0x4B
|
|
||||||
#define MEGAIOREG_PORTE 0x4C
|
|
||||||
#define MEGAIOREG_DDRE 0x4D
|
|
||||||
#define MEGAIOREG_PINE 0x4E
|
|
||||||
#define MEGAIOREG_PORTF 0x4F
|
|
||||||
#define MEGAIOREG_DDRF 0x50
|
|
||||||
#define MEGAIOREG_PINF 0x51
|
|
||||||
|
|
||||||
// Direct Access Registers
|
|
||||||
#define MEGAIOREG_DIRECTIO 0x80
|
|
||||||
#define MEGAIOREG_DIRECTMEM 0x81
|
|
||||||
|
|
||||||
// define MEGAIO register values
|
|
||||||
#define UARTBAUDSEL_300 0x00
|
|
||||||
#define UARTBAUDSEL_600 0x01
|
|
||||||
#define UARTBAUDSEL_1200 0x02
|
|
||||||
#define UARTBAUDSEL_2400 0x03
|
|
||||||
#define UARTBAUDSEL_4800 0x04
|
|
||||||
#define UARTBAUDSEL_9600 0x05
|
|
||||||
#define UARTBAUDSEL_19200 0x06
|
|
||||||
#define UARTBAUDSEL_38400 0x07
|
|
||||||
#define UARTBAUDSEL_115200 0x08
|
|
||||||
|
|
||||||
#define PWM1FREQ_STOP 0x00
|
|
||||||
#define PWM1FREQ_MAX 0x01
|
|
||||||
#define PWM1FREQ_DIV8 0x02
|
|
||||||
#define PWM1FREQ_DIV64 0x03
|
|
||||||
#define PWM1FREQ_DIV256 0x04
|
|
||||||
#define PWM1FREQ_DIV1024 0x05
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,211 +0,0 @@
|
|||||||
/*! \file mmc.c \brief MultiMedia and SD Flash Card Interface. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'mmc.c'
|
|
||||||
// Title : MultiMedia and SD Flash Card Interface
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2004
|
|
||||||
// Created : 2004.09.22
|
|
||||||
// Revised : 2004.09.22
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
//----- Include Files ---------------------------------------------------------
|
|
||||||
#include <avr/io.h> // include I/O definitions (port names, pin names, etc)
|
|
||||||
#include <avr/signal.h> // include "signal" names (interrupt names)
|
|
||||||
#include <avr/interrupt.h> // include interrupt support
|
|
||||||
|
|
||||||
#include "global.h" // include our global settings
|
|
||||||
#include "spi.h" // include spi bus support
|
|
||||||
|
|
||||||
#include "rprintf.h"
|
|
||||||
|
|
||||||
#include "mmc.h"
|
|
||||||
|
|
||||||
// include project-specific hardware configuration
|
|
||||||
#include "mmcconf.h"
|
|
||||||
|
|
||||||
// Global variables
|
|
||||||
|
|
||||||
// Functions
|
|
||||||
|
|
||||||
void mmcInit(void)
|
|
||||||
{
|
|
||||||
// initialize SPI interface
|
|
||||||
spiInit();
|
|
||||||
// release chip select
|
|
||||||
sbi(MMC_CS_DDR, MMC_CS_PIN);
|
|
||||||
sbi(MMC_CS_PORT,MMC_CS_PIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 mmcReset(void)
|
|
||||||
{
|
|
||||||
u08 retry;
|
|
||||||
u08 r1=0;
|
|
||||||
|
|
||||||
retry = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// send dummy bytes with CS high before accessing
|
|
||||||
spiTransferByte(0xFF);
|
|
||||||
spiTransferByte(0xFF);
|
|
||||||
spiTransferByte(0xFF);
|
|
||||||
spiTransferByte(0xFF);
|
|
||||||
// resetting card, go to SPI mode
|
|
||||||
r1 = mmcSendCommand(MMC_GO_IDLE_STATE, 0);
|
|
||||||
#ifdef MMC_DEBUG
|
|
||||||
rprintf("MMC_GO_IDLE_STATE: R1=0x%x\r\n", r1);
|
|
||||||
#endif
|
|
||||||
// do retry counter
|
|
||||||
retry++;
|
|
||||||
if(retry>10) return -1;
|
|
||||||
} while(r1 != 0x01);
|
|
||||||
|
|
||||||
// TODO: check card parameters for voltage compliance
|
|
||||||
// before issuing initialize command
|
|
||||||
|
|
||||||
retry = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// initializing card for operation
|
|
||||||
r1 = mmcSendCommand(MMC_SEND_OP_COND, 0);
|
|
||||||
#ifdef MMC_DEBUG
|
|
||||||
rprintf("MMC_SEND_OP_COND: R1=0x%x\r\n", r1);
|
|
||||||
#endif
|
|
||||||
// do retry counter
|
|
||||||
retry++;
|
|
||||||
if(retry>100) return -1;
|
|
||||||
} while(r1);
|
|
||||||
|
|
||||||
// turn off CRC checking to simplify communication
|
|
||||||
r1 = mmcSendCommand(MMC_CRC_ON_OFF, 0);
|
|
||||||
#ifdef MMC_DEBUG
|
|
||||||
rprintf("MMC_CRC_ON_OFF: R1=0x%x\r\n", r1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// set block length to 512 bytes
|
|
||||||
r1 = mmcSendCommand(MMC_SET_BLOCKLEN, 512);
|
|
||||||
#ifdef MMC_DEBUG
|
|
||||||
rprintf("MMC_SET_BLOCKLEN: R1=0x%x\r\n", r1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// return success
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 mmcSendCommand(u08 cmd, u32 arg)
|
|
||||||
{
|
|
||||||
u08 r1;
|
|
||||||
|
|
||||||
// assert chip select
|
|
||||||
cbi(MMC_CS_PORT,MMC_CS_PIN);
|
|
||||||
// issue the command
|
|
||||||
r1 = mmcCommand(cmd, arg);
|
|
||||||
// release chip select
|
|
||||||
sbi(MMC_CS_PORT,MMC_CS_PIN);
|
|
||||||
|
|
||||||
return r1;
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 mmcRead(u32 sector, u08* buffer)
|
|
||||||
{
|
|
||||||
u08 r1;
|
|
||||||
u16 i;
|
|
||||||
|
|
||||||
// assert chip select
|
|
||||||
cbi(MMC_CS_PORT,MMC_CS_PIN);
|
|
||||||
// issue command
|
|
||||||
r1 = mmcCommand(MMC_READ_SINGLE_BLOCK, sector<<9);
|
|
||||||
#ifdef MMC_DEBUG
|
|
||||||
rprintf("MMC Read Block R1=0x%x\r\n", r1);
|
|
||||||
#endif
|
|
||||||
// check for valid response
|
|
||||||
if(r1 != 0x00)
|
|
||||||
return r1;
|
|
||||||
// wait for block start
|
|
||||||
while(spiTransferByte(0xFF) != MMC_STARTBLOCK_READ);
|
|
||||||
// read in data
|
|
||||||
for(i=0; i<0x200; i++)
|
|
||||||
{
|
|
||||||
*buffer++ = spiTransferByte(0xFF);
|
|
||||||
}
|
|
||||||
// read 16-bit CRC
|
|
||||||
spiTransferByte(0xFF);
|
|
||||||
spiTransferByte(0xFF);
|
|
||||||
// release chip select
|
|
||||||
sbi(MMC_CS_PORT,MMC_CS_PIN);
|
|
||||||
// return success
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 mmcWrite(u32 sector, u08* buffer)
|
|
||||||
{
|
|
||||||
u08 r1;
|
|
||||||
u16 i;
|
|
||||||
|
|
||||||
// assert chip select
|
|
||||||
cbi(MMC_CS_PORT,MMC_CS_PIN);
|
|
||||||
// issue command
|
|
||||||
r1 = mmcCommand(MMC_WRITE_BLOCK, sector<<9);
|
|
||||||
#ifdef MMC_DEBUG
|
|
||||||
rprintf("MMC Write Block R1=0x%x\r\n", r1);
|
|
||||||
#endif
|
|
||||||
// check for valid response
|
|
||||||
if(r1 != 0x00)
|
|
||||||
return r1;
|
|
||||||
// send dummy
|
|
||||||
spiTransferByte(0xFF);
|
|
||||||
// send data start token
|
|
||||||
spiTransferByte(MMC_STARTBLOCK_WRITE);
|
|
||||||
// write data
|
|
||||||
for(i=0; i<0x200; i++)
|
|
||||||
{
|
|
||||||
spiTransferByte(*buffer++);
|
|
||||||
}
|
|
||||||
// write 16-bit CRC (dummy values)
|
|
||||||
spiTransferByte(0xFF);
|
|
||||||
spiTransferByte(0xFF);
|
|
||||||
// read data response token
|
|
||||||
r1 = spiTransferByte(0xFF);
|
|
||||||
if( (r1&MMC_DR_MASK) != MMC_DR_ACCEPT)
|
|
||||||
return r1;
|
|
||||||
#ifdef MMC_DEBUG
|
|
||||||
rprintf("Data Response Token=0x%x\r\n", r1);
|
|
||||||
#endif
|
|
||||||
// wait until card not busy
|
|
||||||
while(!spiTransferByte(0xFF));
|
|
||||||
// release chip select
|
|
||||||
sbi(MMC_CS_PORT,MMC_CS_PIN);
|
|
||||||
// return success
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 mmcCommand(u08 cmd, u32 arg)
|
|
||||||
{
|
|
||||||
u08 r1;
|
|
||||||
u08 retry=0;
|
|
||||||
// send command
|
|
||||||
spiTransferByte(cmd | 0x40);
|
|
||||||
spiTransferByte(arg>>24);
|
|
||||||
spiTransferByte(arg>>16);
|
|
||||||
spiTransferByte(arg>>8);
|
|
||||||
spiTransferByte(arg);
|
|
||||||
spiTransferByte(0x95); // crc valid only for MMC_GO_IDLE_STATE
|
|
||||||
// end command
|
|
||||||
// wait for response
|
|
||||||
// if more than 8 retries, card has timed-out
|
|
||||||
// return the received 0xFF
|
|
||||||
while((r1 = spiTransferByte(0xFF)) == 0xFF)
|
|
||||||
if(retry++ > 8) break;
|
|
||||||
// return response
|
|
||||||
return r1;
|
|
||||||
}
|
|
@ -1,125 +0,0 @@
|
|||||||
/*! \file mmc.h \brief MultiMedia and SD Flash Card Interface. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'mmc.h'
|
|
||||||
// Title : MultiMedia and SD Flash Card Interface
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2004
|
|
||||||
// Created : 2004.09.22
|
|
||||||
// Revised : 2004.09.22
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// Description : This library offers some simple function which can be used
|
|
||||||
// to read and write data on a MultiMedia or SecureDigital (SD) Flash
|
|
||||||
// Card. Although MM and SD Cards are designed to operate with their own
|
|
||||||
// special bus wiring and protocols, both types of cards also provide a
|
|
||||||
// simple SPI-like interface mode which is exceptionally useful when
|
|
||||||
// attempting to use the cards in embedded systems.
|
|
||||||
//
|
|
||||||
// To work with this library, the card must be wired to the SPI port of
|
|
||||||
// the Atmel microcontroller as described below.
|
|
||||||
// _________________
|
|
||||||
// / 1 2 3 4 5 6 78 | <- view of MMC/SD card looking at contacts
|
|
||||||
// / 9 | Pins 8 and 9 are present only on SD cards
|
|
||||||
// | MMC/SD Card |
|
|
||||||
// /\/\/\/\/\/\/\/\/\/
|
|
||||||
//
|
|
||||||
// 1 - CS (chip select) - wire to any available I/O pin(*)
|
|
||||||
// 2 - DIN (data in, card<-host) - wire to SPI MOSI pin
|
|
||||||
// 3 - VSS (ground) - wire to ground
|
|
||||||
// 4 - VDD (power, 3.3V only?) - wire to power (MIGHT BE 3.3V ONLY!)
|
|
||||||
// 5 - SCLK (data clock) - wire to SPI SCK pin
|
|
||||||
// 6 - VSS (ground) - wire to ground
|
|
||||||
// 7 - DOUT (data out, card->host) - wire to SPI MISO pin
|
|
||||||
//
|
|
||||||
// (*) you must define this chip select I/O pin in mmcconf.h
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef MMC_H
|
|
||||||
#define MMC_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
// constants/macros/typdefs
|
|
||||||
// MMC commands (taken from sandisk MMC reference)
|
|
||||||
#define MMC_GO_IDLE_STATE 0
|
|
||||||
#define MMC_SEND_OP_COND 1
|
|
||||||
#define MMC_SEND_CSD 9
|
|
||||||
#define MMC_SEND_CID 10
|
|
||||||
#define MMC_SEND_STATUS 13
|
|
||||||
#define MMC_SET_BLOCKLEN 16
|
|
||||||
#define MMC_READ_SINGLE_BLOCK 17
|
|
||||||
#define MMC_WRITE_BLOCK 24
|
|
||||||
#define MMC_PROGRAM_CSD 27
|
|
||||||
#define MMC_SET_WRITE_PROT 28
|
|
||||||
#define MMC_CLR_WRITE_PROT 29
|
|
||||||
#define MMC_SEND_WRITE_PROT 30
|
|
||||||
#define MMC_TAG_SECTOR_START 32
|
|
||||||
#define MMC_TAG_SECTOR_END 33
|
|
||||||
#define MMC_UNTAG_SECTOR 34
|
|
||||||
#define MMC_TAG_ERASE_GROUP_START 35
|
|
||||||
#define MMC_TAG_ERARE_GROUP_END 36
|
|
||||||
#define MMC_UNTAG_ERASE_GROUP 37
|
|
||||||
#define MMC_ERASE 38
|
|
||||||
#define MMC_CRC_ON_OFF 59
|
|
||||||
// R1 Response bit-defines
|
|
||||||
#define MMC_R1_BUSY 0x80
|
|
||||||
#define MMC_R1_PARAMETER 0x40
|
|
||||||
#define MMC_R1_ADDRESS 0x20
|
|
||||||
#define MMC_R1_ERASE_SEQ 0x10
|
|
||||||
#define MMC_R1_COM_CRC 0x08
|
|
||||||
#define MMC_R1_ILLEGAL_COM 0x04
|
|
||||||
#define MMC_R1_ERASE_RESET 0x02
|
|
||||||
#define MMC_R1_IDLE_STATE 0x01
|
|
||||||
// Data Start tokens
|
|
||||||
#define MMC_STARTBLOCK_READ 0xFE
|
|
||||||
#define MMC_STARTBLOCK_WRITE 0xFE
|
|
||||||
#define MMC_STARTBLOCK_MWRITE 0xFC
|
|
||||||
// Data Stop tokens
|
|
||||||
#define MMC_STOPTRAN_WRITE 0xFD
|
|
||||||
// Data Error Token values
|
|
||||||
#define MMC_DE_MASK 0x1F
|
|
||||||
#define MMC_DE_ERROR 0x01
|
|
||||||
#define MMC_DE_CC_ERROR 0x02
|
|
||||||
#define MMC_DE_ECC_FAIL 0x04
|
|
||||||
#define MMC_DE_OUT_OF_RANGE 0x04
|
|
||||||
#define MMC_DE_CARD_LOCKED 0x04
|
|
||||||
// Data Response Token values
|
|
||||||
#define MMC_DR_MASK 0x1F
|
|
||||||
#define MMC_DR_ACCEPT 0x05
|
|
||||||
#define MMC_DR_REJECT_CRC 0x0B
|
|
||||||
#define MMC_DR_REJECT_WRITE_ERROR 0x0D
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
//! Initialize hardware interface
|
|
||||||
void mmcInit(void);
|
|
||||||
|
|
||||||
//! Initialize the card and prepare it for use
|
|
||||||
// returns zero if successful
|
|
||||||
u08 mmcReset(void);
|
|
||||||
|
|
||||||
//! Send card an MMC command
|
|
||||||
// returns R1 result code
|
|
||||||
u08 mmcSendCommand(u08 cmd, u32 arg);
|
|
||||||
|
|
||||||
//! Read 512-byte sector from card to buffer
|
|
||||||
// returns zero if successful
|
|
||||||
u08 mmcRead(u32 sector, u08* buffer);
|
|
||||||
//! Write 512-byte sector from buffer to card
|
|
||||||
// returns zero if successful
|
|
||||||
u08 mmcWrite(u32 sector, u08* buffer);
|
|
||||||
|
|
||||||
//! internal command function
|
|
||||||
u08 mmcCommand(u08 cmd, u32 arg);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,260 +0,0 @@
|
|||||||
/*! \file nmea.c \brief NMEA protocol function library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'nmea.c'
|
|
||||||
// Title : NMEA protocol function library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002
|
|
||||||
// Created : 2002.08.27
|
|
||||||
// Revised : 2002.08.27
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/signal.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#endif
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include "buffer.h"
|
|
||||||
#include "rprintf.h"
|
|
||||||
#include "gps.h"
|
|
||||||
|
|
||||||
#include "nmea.h"
|
|
||||||
|
|
||||||
// Program ROM constants
|
|
||||||
|
|
||||||
// Global variables
|
|
||||||
extern GpsInfoType GpsInfo;
|
|
||||||
u08 NmeaPacket[NMEA_BUFFERSIZE];
|
|
||||||
|
|
||||||
void nmeaInit(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
u08* nmeaGetPacketBuffer(void)
|
|
||||||
{
|
|
||||||
return NmeaPacket;
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 nmeaProcess(cBuffer* rxBuffer)
|
|
||||||
{
|
|
||||||
u08 foundpacket = NMEA_NODATA;
|
|
||||||
u08 startFlag = FALSE;
|
|
||||||
//u08 data;
|
|
||||||
u16 i,j;
|
|
||||||
|
|
||||||
// process the receive buffer
|
|
||||||
// go through buffer looking for packets
|
|
||||||
while(rxBuffer->datalength)
|
|
||||||
{
|
|
||||||
// look for a start of NMEA packet
|
|
||||||
if(bufferGetAtIndex(rxBuffer,0) == '$')
|
|
||||||
{
|
|
||||||
// found start
|
|
||||||
startFlag = TRUE;
|
|
||||||
// when start is found, we leave it intact in the receive buffer
|
|
||||||
// in case the full NMEA string is not completely received. The
|
|
||||||
// start will be detected in the next nmeaProcess iteration.
|
|
||||||
|
|
||||||
// done looking for start
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
bufferGetFromFront(rxBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we detected a start, look for end of packet
|
|
||||||
if(startFlag)
|
|
||||||
{
|
|
||||||
for(i=1; i<(rxBuffer->datalength)-1; i++)
|
|
||||||
{
|
|
||||||
// check for end of NMEA packet <CR><LF>
|
|
||||||
if((bufferGetAtIndex(rxBuffer,i) == '\r') && (bufferGetAtIndex(rxBuffer,i+1) == '\n'))
|
|
||||||
{
|
|
||||||
// have a packet end
|
|
||||||
// dump initial '$'
|
|
||||||
bufferGetFromFront(rxBuffer);
|
|
||||||
// copy packet to NmeaPacket
|
|
||||||
for(j=0; j<(i-1); j++)
|
|
||||||
{
|
|
||||||
// although NMEA strings should be 80 characters or less,
|
|
||||||
// receive buffer errors can generate erroneous packets.
|
|
||||||
// Protect against packet buffer overflow
|
|
||||||
if(j<(NMEA_BUFFERSIZE-1))
|
|
||||||
NmeaPacket[j] = bufferGetFromFront(rxBuffer);
|
|
||||||
else
|
|
||||||
bufferGetFromFront(rxBuffer);
|
|
||||||
}
|
|
||||||
// null terminate it
|
|
||||||
NmeaPacket[j] = 0;
|
|
||||||
// dump <CR><LF> from rxBuffer
|
|
||||||
bufferGetFromFront(rxBuffer);
|
|
||||||
bufferGetFromFront(rxBuffer);
|
|
||||||
|
|
||||||
#ifdef NMEA_DEBUG_PKT
|
|
||||||
rprintf("Rx NMEA packet type: ");
|
|
||||||
rprintfStrLen(NmeaPacket, 0, 5);
|
|
||||||
rprintfStrLen(NmeaPacket, 5, (i-1)-5);
|
|
||||||
rprintfCRLF();
|
|
||||||
#endif
|
|
||||||
// found a packet
|
|
||||||
// done with this processing session
|
|
||||||
foundpacket = NMEA_UNKNOWN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(foundpacket)
|
|
||||||
{
|
|
||||||
// check message type and process appropriately
|
|
||||||
if(!strncmp(NmeaPacket, "GPGGA", 5))
|
|
||||||
{
|
|
||||||
// process packet of this type
|
|
||||||
nmeaProcessGPGGA(NmeaPacket);
|
|
||||||
// report packet type
|
|
||||||
foundpacket = NMEA_GPGGA;
|
|
||||||
}
|
|
||||||
else if(!strncmp(NmeaPacket, "GPVTG", 5))
|
|
||||||
{
|
|
||||||
// process packet of this type
|
|
||||||
nmeaProcessGPVTG(NmeaPacket);
|
|
||||||
// report packet type
|
|
||||||
foundpacket = NMEA_GPVTG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(rxBuffer->datalength >= rxBuffer->size)
|
|
||||||
{
|
|
||||||
// if we found no packet, and the buffer is full
|
|
||||||
// we're logjammed, flush entire buffer
|
|
||||||
bufferFlush(rxBuffer);
|
|
||||||
}
|
|
||||||
return foundpacket;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nmeaProcessGPGGA(u08* packet)
|
|
||||||
{
|
|
||||||
u08 i;
|
|
||||||
char* endptr;
|
|
||||||
double degrees, minutesfrac;
|
|
||||||
|
|
||||||
#ifdef NMEA_DEBUG_GGA
|
|
||||||
rprintf("NMEA: ");
|
|
||||||
rprintfStr(packet);
|
|
||||||
rprintfCRLF();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// start parsing just after "GPGGA,"
|
|
||||||
i = 6;
|
|
||||||
// attempt to reject empty packets right away
|
|
||||||
if(packet[i]==',' && packet[i+1]==',')
|
|
||||||
return;
|
|
||||||
|
|
||||||
// get UTC time [hhmmss.sss]
|
|
||||||
GpsInfo.PosLLA.TimeOfFix.f = strtod(&packet[i], &endptr);
|
|
||||||
while(packet[i++] != ','); // next field: latitude
|
|
||||||
|
|
||||||
// get latitude [ddmm.mmmmm]
|
|
||||||
GpsInfo.PosLLA.lat.f = strtod(&packet[i], &endptr);
|
|
||||||
// convert to pure degrees [dd.dddd] format
|
|
||||||
minutesfrac = modf(GpsInfo.PosLLA.lat.f/100, °rees);
|
|
||||||
GpsInfo.PosLLA.lat.f = degrees + (minutesfrac*100)/60;
|
|
||||||
// convert to radians
|
|
||||||
GpsInfo.PosLLA.lat.f *= (M_PI/180);
|
|
||||||
while(packet[i++] != ','); // next field: N/S indicator
|
|
||||||
|
|
||||||
// correct latitute for N/S
|
|
||||||
if(packet[i] == 'S') GpsInfo.PosLLA.lat.f = -GpsInfo.PosLLA.lat.f;
|
|
||||||
while(packet[i++] != ','); // next field: longitude
|
|
||||||
|
|
||||||
// get longitude [ddmm.mmmmm]
|
|
||||||
GpsInfo.PosLLA.lon.f = strtod(&packet[i], &endptr);
|
|
||||||
// convert to pure degrees [dd.dddd] format
|
|
||||||
minutesfrac = modf(GpsInfo.PosLLA.lon.f/100, °rees);
|
|
||||||
GpsInfo.PosLLA.lon.f = degrees + (minutesfrac*100)/60;
|
|
||||||
// convert to radians
|
|
||||||
GpsInfo.PosLLA.lon.f *= (M_PI/180);
|
|
||||||
while(packet[i++] != ','); // next field: E/W indicator
|
|
||||||
|
|
||||||
// correct latitute for E/W
|
|
||||||
if(packet[i] == 'W') GpsInfo.PosLLA.lon.f = -GpsInfo.PosLLA.lon.f;
|
|
||||||
while(packet[i++] != ','); // next field: position fix status
|
|
||||||
|
|
||||||
// position fix status
|
|
||||||
// 0 = Invalid, 1 = Valid SPS, 2 = Valid DGPS, 3 = Valid PPS
|
|
||||||
// check for good position fix
|
|
||||||
if( (packet[i] != '0') && (packet[i] != ',') )
|
|
||||||
GpsInfo.PosLLA.updates++;
|
|
||||||
while(packet[i++] != ','); // next field: satellites used
|
|
||||||
|
|
||||||
// get number of satellites used in GPS solution
|
|
||||||
GpsInfo.numSVs = atoi(&packet[i]);
|
|
||||||
while(packet[i++] != ','); // next field: HDOP (horizontal dilution of precision)
|
|
||||||
while(packet[i++] != ','); // next field: altitude
|
|
||||||
|
|
||||||
// get altitude (in meters)
|
|
||||||
GpsInfo.PosLLA.alt.f = strtod(&packet[i], &endptr);
|
|
||||||
|
|
||||||
while(packet[i++] != ','); // next field: altitude units, always 'M'
|
|
||||||
while(packet[i++] != ','); // next field: geoid seperation
|
|
||||||
while(packet[i++] != ','); // next field: seperation units
|
|
||||||
while(packet[i++] != ','); // next field: DGPS age
|
|
||||||
while(packet[i++] != ','); // next field: DGPS station ID
|
|
||||||
while(packet[i++] != '*'); // next field: checksum
|
|
||||||
}
|
|
||||||
|
|
||||||
void nmeaProcessGPVTG(u08* packet)
|
|
||||||
{
|
|
||||||
u08 i;
|
|
||||||
char* endptr;
|
|
||||||
|
|
||||||
#ifdef NMEA_DEBUG_VTG
|
|
||||||
rprintf("NMEA: ");
|
|
||||||
rprintfStr(packet);
|
|
||||||
rprintfCRLF();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// start parsing just after "GPVTG,"
|
|
||||||
i = 6;
|
|
||||||
// attempt to reject empty packets right away
|
|
||||||
if(packet[i]==',' && packet[i+1]==',')
|
|
||||||
return;
|
|
||||||
|
|
||||||
// get course (true north ref) in degrees [ddd.dd]
|
|
||||||
GpsInfo.VelHS.heading.f = strtod(&packet[i], &endptr);
|
|
||||||
while(packet[i++] != ','); // next field: 'T'
|
|
||||||
while(packet[i++] != ','); // next field: course (magnetic north)
|
|
||||||
|
|
||||||
// get course (magnetic north ref) in degrees [ddd.dd]
|
|
||||||
//GpsInfo.VelHS.heading.f = strtod(&packet[i], &endptr);
|
|
||||||
while(packet[i++] != ','); // next field: 'M'
|
|
||||||
while(packet[i++] != ','); // next field: speed (knots)
|
|
||||||
|
|
||||||
// get speed in knots
|
|
||||||
//GpsInfo.VelHS.speed.f = strtod(&packet[i], &endptr);
|
|
||||||
while(packet[i++] != ','); // next field: 'N'
|
|
||||||
while(packet[i++] != ','); // next field: speed (km/h)
|
|
||||||
|
|
||||||
// get speed in km/h
|
|
||||||
GpsInfo.VelHS.speed.f = strtod(&packet[i], &endptr);
|
|
||||||
while(packet[i++] != ','); // next field: 'K'
|
|
||||||
while(packet[i++] != '*'); // next field: checksum
|
|
||||||
|
|
||||||
GpsInfo.VelHS.updates++;
|
|
||||||
}
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
|||||||
/*! \file nmea.h \brief NMEA protocol function library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'nmea.h'
|
|
||||||
// Title : NMEA protocol function library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002
|
|
||||||
// Created : 2002.08.27
|
|
||||||
// Revised : 2002.08.27
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef NMEA_H
|
|
||||||
#define NMEA_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include "buffer.h"
|
|
||||||
|
|
||||||
// constants/macros/typdefs
|
|
||||||
#define NMEA_BUFFERSIZE 80
|
|
||||||
|
|
||||||
// Message Codes
|
|
||||||
#define NMEA_NODATA 0 // No data. Packet not available, bad, or not decoded
|
|
||||||
#define NMEA_GPGGA 1 // Global Positioning System Fix Data
|
|
||||||
#define NMEA_GPVTG 2 // Course over ground and ground speed
|
|
||||||
#define NMEA_GPGLL 3 // Geographic position - latitude/longitude
|
|
||||||
#define NMEA_GPGSV 4 // GPS satellites in view
|
|
||||||
#define NMEA_GPGSA 5 // GPS DOP and active satellites
|
|
||||||
#define NMEA_GPRMC 6 // Recommended minimum specific GPS data
|
|
||||||
#define NMEA_UNKNOWN 0xFF// Packet received but not known
|
|
||||||
|
|
||||||
// Debugging
|
|
||||||
//#define NMEA_DEBUG_PKT ///< define to enable debug of all NMEA messages
|
|
||||||
//#define NMEA_DEBUG_GGA ///< define to enable debug of GGA messages
|
|
||||||
//#define NMEA_DEBUG_VTG ///< define to enable debug of VTG messages
|
|
||||||
|
|
||||||
// functions
|
|
||||||
void nmeaInit(void);
|
|
||||||
u08* nmeaGetPacketBuffer(void);
|
|
||||||
u08 nmeaProcess(cBuffer* rxBuffer);
|
|
||||||
void nmeaProcessGPGGA(u08* packet);
|
|
||||||
void nmeaProcessGPVTG(u08* packet);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,98 +0,0 @@
|
|||||||
/*! \file port128.h \brief Additional include for Mega128 to define individual port pins. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'port128.h'
|
|
||||||
// Title : Additional include for Mega128 to define individual port pins
|
|
||||||
// Author : Pascal Stang
|
|
||||||
// Created : 11/18/2002
|
|
||||||
// Revised : 11/18/2002
|
|
||||||
// Version : 1.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// Description : This include file contains additional port and pin defines
|
|
||||||
// to help make code transparently compatible with the mega128. As in
|
|
||||||
// the other AVR processors, using defines like PD2 to denote PORTD, pin2
|
|
||||||
// is not absolutely necessary but enhances readability. The mega128 io.h
|
|
||||||
// no longer defines individual pins of ports (like PD2 or PA5, for
|
|
||||||
// example). Instead, port pins are defines universally for all ports as
|
|
||||||
// PORT0 through PORT7. However, this renaming causes a code-portability
|
|
||||||
// issue from non-mega128 AVRs to the mega128. Including this file will
|
|
||||||
// replace the missing defines.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef PORT128_H
|
|
||||||
#define PORT128_H
|
|
||||||
|
|
||||||
// Mega128 individual port defines
|
|
||||||
// (using these is technically unnecessary but improves code compatibility to
|
|
||||||
// the mega128 from other AVR processors where these values were still defined
|
|
||||||
// in the io.h for that processor)
|
|
||||||
|
|
||||||
// PORTA
|
|
||||||
#define PA0 PORT0
|
|
||||||
#define PA1 PORT1
|
|
||||||
#define PA2 PORT2
|
|
||||||
#define PA3 PORT3
|
|
||||||
#define PA4 PORT4
|
|
||||||
#define PA5 PORT5
|
|
||||||
#define PA6 PORT6
|
|
||||||
#define PA7 PORT7
|
|
||||||
// PORTB
|
|
||||||
#define PB0 PORT0
|
|
||||||
#define PB1 PORT1
|
|
||||||
#define PB2 PORT2
|
|
||||||
#define PB3 PORT3
|
|
||||||
#define PB4 PORT4
|
|
||||||
#define PB5 PORT5
|
|
||||||
#define PB6 PORT6
|
|
||||||
#define PB7 PORT7
|
|
||||||
// PORTC
|
|
||||||
#define PC0 PORT0
|
|
||||||
#define PC1 PORT1
|
|
||||||
#define PC2 PORT2
|
|
||||||
#define PC3 PORT3
|
|
||||||
#define PC4 PORT4
|
|
||||||
#define PC5 PORT5
|
|
||||||
#define PC6 PORT6
|
|
||||||
#define PC7 PORT7
|
|
||||||
// PORTD
|
|
||||||
#define PD0 PORT0
|
|
||||||
#define PD1 PORT1
|
|
||||||
#define PD2 PORT2
|
|
||||||
#define PD3 PORT3
|
|
||||||
#define PD4 PORT4
|
|
||||||
#define PD5 PORT5
|
|
||||||
#define PD6 PORT6
|
|
||||||
#define PD7 PORT7
|
|
||||||
// PORTE
|
|
||||||
#define PE0 PORT0
|
|
||||||
#define PE1 PORT1
|
|
||||||
#define PE2 PORT2
|
|
||||||
#define PE3 PORT3
|
|
||||||
#define PE4 PORT4
|
|
||||||
#define PE5 PORT5
|
|
||||||
#define PE6 PORT6
|
|
||||||
#define PE7 PORT7
|
|
||||||
// PORTF
|
|
||||||
#define PF0 PORT0
|
|
||||||
#define PF1 PORT1
|
|
||||||
#define PF2 PORT2
|
|
||||||
#define PF3 PORT3
|
|
||||||
#define PF4 PORT4
|
|
||||||
#define PF5 PORT5
|
|
||||||
#define PF6 PORT6
|
|
||||||
#define PF7 PORT7
|
|
||||||
// PORTG
|
|
||||||
#define PG0 PORT0
|
|
||||||
#define PG1 PORT1
|
|
||||||
#define PG2 PORT2
|
|
||||||
#define PG3 PORT3
|
|
||||||
#define PG4 PORT4
|
|
||||||
#define PG5 PORT5
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,286 +0,0 @@
|
|||||||
/*! \file pulse.c \brief Pulse/frequency generation function library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'pulse.c'
|
|
||||||
// Title : Pulse/frequency generation function library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2000-2002
|
|
||||||
// Created : 2002-08-19
|
|
||||||
// Revised : 2003-05-29
|
|
||||||
// Version : 0.7
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include <avr/signal.h>
|
|
||||||
#include <avr/interrupt.h>
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include "timer.h"
|
|
||||||
#include "pulse.h"
|
|
||||||
|
|
||||||
// Global variables
|
|
||||||
// pulse generation registers
|
|
||||||
volatile static unsigned char PulseT1AMode;
|
|
||||||
volatile static unsigned short PulseT1ACount;
|
|
||||||
volatile static unsigned short PulseT1APeriodTics;
|
|
||||||
volatile static unsigned char PulseT1BMode;
|
|
||||||
volatile static unsigned short PulseT1BCount;
|
|
||||||
volatile static unsigned short PulseT1BPeriodTics;
|
|
||||||
|
|
||||||
// pulse mode bit definitions
|
|
||||||
// PULSE_MODE_COUNTED
|
|
||||||
// if true, the requested number of pulses are output, then output is turned off
|
|
||||||
// if false, pulses are output continuously
|
|
||||||
#define PULSE_MODE_CONTINUOUS 0x00
|
|
||||||
#define PULSE_MODE_COUNTED 0x01
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
void pulseInit(void)
|
|
||||||
{
|
|
||||||
// initialize timer1 for pulse operation
|
|
||||||
pulseT1Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
void pulseT1Init(void)
|
|
||||||
{
|
|
||||||
// try to make sure that timer1 is in "normal" mode
|
|
||||||
// most importantly, turn off PWM mode
|
|
||||||
timer1PWMOff();
|
|
||||||
|
|
||||||
// set some reasonable initial values
|
|
||||||
// in case the user forgets to
|
|
||||||
PulseT1AMode = 0;
|
|
||||||
PulseT1BMode = 0;
|
|
||||||
PulseT1ACount = 0;
|
|
||||||
PulseT1BCount = 0;
|
|
||||||
PulseT1APeriodTics = 0x8000;
|
|
||||||
PulseT1BPeriodTics = 0x8000;
|
|
||||||
|
|
||||||
// attach the pulse service routines to
|
|
||||||
// the timer 1 output compare A and B interrupts
|
|
||||||
timerAttach(TIMER1OUTCOMPAREA_INT,pulseT1AService);
|
|
||||||
timerAttach(TIMER1OUTCOMPAREB_INT,pulseT1BService);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pulseT1Off(void)
|
|
||||||
{
|
|
||||||
// turns pulse outputs off immediately
|
|
||||||
|
|
||||||
// set pulse counters to zero (finished)
|
|
||||||
PulseT1ACount = 0;
|
|
||||||
PulseT1BCount = 0;
|
|
||||||
// disconnect OutputCompare action from OC1A pin
|
|
||||||
cbi(TCCR1A,COM1A1);
|
|
||||||
cbi(TCCR1A,COM1A0);
|
|
||||||
// disconnect OutputCompare action from OC1B pin
|
|
||||||
cbi(TCCR1A,COM1B1);
|
|
||||||
cbi(TCCR1A,COM1B0);
|
|
||||||
// detach the pulse service routines
|
|
||||||
timerDetach(TIMER1OUTCOMPAREA_INT);
|
|
||||||
timerDetach(TIMER1OUTCOMPAREB_INT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pulseT1ASetFreq(u16 freqHz)
|
|
||||||
{
|
|
||||||
// set the frequency of the pulse output
|
|
||||||
// we need to find the requested period/2 (in timer tics)
|
|
||||||
// from the frequency (in hertz)
|
|
||||||
|
|
||||||
// calculate how many tics in period/2
|
|
||||||
// this is the (timer tic rate)/(2*requested freq)
|
|
||||||
PulseT1APeriodTics = ((u32)F_CPU/((u32)timer1GetPrescaler()*2*freqHz));
|
|
||||||
}
|
|
||||||
|
|
||||||
void pulseT1BSetFreq(u16 freqHz)
|
|
||||||
{
|
|
||||||
// set the frequency of the pulse output
|
|
||||||
// we need to find the requested period/2 (in timer tics)
|
|
||||||
// from the frequency (in hertz)
|
|
||||||
|
|
||||||
// calculate how many tics in period/2
|
|
||||||
// this is the (timer tic rate)/(2*requested freq)
|
|
||||||
PulseT1BPeriodTics = ((u32)F_CPU/((u32)timer1GetPrescaler()*2*freqHz));
|
|
||||||
}
|
|
||||||
|
|
||||||
void pulseT1ARun(u16 nPulses)
|
|
||||||
{
|
|
||||||
// set the number of pulses we want and the mode
|
|
||||||
if(nPulses)
|
|
||||||
{
|
|
||||||
// if the nPulses is non-zero, use "counted" mode
|
|
||||||
PulseT1AMode |= PULSE_MODE_COUNTED;
|
|
||||||
PulseT1ACount = nPulses<<1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// if nPulses is zero, run forever
|
|
||||||
PulseT1AMode &= ~PULSE_MODE_COUNTED;
|
|
||||||
PulseT1ACount = 1<<1;
|
|
||||||
}
|
|
||||||
// set OutputCompare action to toggle OC1A pin
|
|
||||||
cbi(TCCR1A,COM1A1);
|
|
||||||
sbi(TCCR1A,COM1A0);
|
|
||||||
|
|
||||||
// now the "enabling" stuff
|
|
||||||
|
|
||||||
// set the output compare one pulse cycle ahead of current timer position
|
|
||||||
// to make sure we don't have to wait until the timer overflows and comes
|
|
||||||
// back to the current value
|
|
||||||
// set future output compare time to TCNT1 + PulseT1APeriodTics
|
|
||||||
//outw(OCR1A, inw(TCNT1) + PulseT1APeriodTics);
|
|
||||||
OCR1A += PulseT1APeriodTics;
|
|
||||||
|
|
||||||
// enable OutputCompare interrupt
|
|
||||||
sbi(TIMSK, OCIE1A);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pulseT1BRun(u16 nPulses)
|
|
||||||
{
|
|
||||||
// set the number of pulses we want and the mode
|
|
||||||
if(nPulses)
|
|
||||||
{
|
|
||||||
// if the nPulses is non-zero, use "counted" mode
|
|
||||||
PulseT1BMode |= PULSE_MODE_COUNTED;
|
|
||||||
PulseT1BCount = nPulses<<1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// if nPulses is zero, run forever
|
|
||||||
PulseT1BMode &= ~PULSE_MODE_COUNTED;
|
|
||||||
PulseT1BCount = 1<<1;
|
|
||||||
}
|
|
||||||
// set OutputCompare action to toggle OC1B pin
|
|
||||||
// (note: with all the A's and B's flying around, TCCR1A is not a bug)
|
|
||||||
cbi(TCCR1A,COM1B1);
|
|
||||||
sbi(TCCR1A,COM1B0);
|
|
||||||
|
|
||||||
// now the "enabling" stuff
|
|
||||||
|
|
||||||
// set the output compare one pulse cycle ahead of current timer position
|
|
||||||
// to make sure we don't have to wait until the timer overflows and comes
|
|
||||||
// back to the current value
|
|
||||||
// set future output compare time to TCNT1 + PulseT1APeriodTics
|
|
||||||
//outw(OCR1B, inw(TCNT1) + PulseT1BPeriodTics);
|
|
||||||
OCR1B += PulseT1BPeriodTics;
|
|
||||||
|
|
||||||
// enable OutputCompare interrupt
|
|
||||||
sbi(TIMSK, OCIE1B);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pulseT1AStop(void)
|
|
||||||
{
|
|
||||||
// stop output regardless of remaining pulses or mode
|
|
||||||
// go to "counted" mode
|
|
||||||
PulseT1AMode |= PULSE_MODE_COUNTED;
|
|
||||||
// set pulses to zero
|
|
||||||
PulseT1ACount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pulseT1BStop(void)
|
|
||||||
{
|
|
||||||
// stop output regardless of remaining pulses or mode
|
|
||||||
// go to "counted" mode
|
|
||||||
PulseT1BMode |= PULSE_MODE_COUNTED;
|
|
||||||
// set pulses to zero
|
|
||||||
PulseT1BCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u16 pulseT1ARemaining(void)
|
|
||||||
{
|
|
||||||
// return the number of pulses remaining for channel A
|
|
||||||
// add 1 to make sure we round up, >>1 equivalent to /2
|
|
||||||
return (PulseT1ACount+1)>>1;
|
|
||||||
}
|
|
||||||
|
|
||||||
u16 pulseT1BRemaining(void)
|
|
||||||
{
|
|
||||||
// return the number of pulses remaining for channel A
|
|
||||||
// add 1 to make sure we round up, >>1 equivalent to /2
|
|
||||||
return (PulseT1BCount+1)>>1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pulseT1AService(void)
|
|
||||||
{
|
|
||||||
// check if TimerPulseACount is non-zero
|
|
||||||
// (i.e. pulses are still requested)
|
|
||||||
if(PulseT1ACount)
|
|
||||||
{
|
|
||||||
//u16 OCValue;
|
|
||||||
// read in current value of output compare register OCR1A
|
|
||||||
//OCValue = inp(OCR1AL); // read low byte of OCR1A
|
|
||||||
//OCValue += inp(OCR1AH)<<8; // read high byte of OCR1A
|
|
||||||
// increment OCR1A value by PulseT1APeriodTics
|
|
||||||
//OCValue += PulseT1APeriodTics;
|
|
||||||
// set future output compare time to this new value
|
|
||||||
//outp((OCValue>>8), OCR1AH); // write high byte
|
|
||||||
//outp((OCValue & 0x00FF),OCR1AL); // write low byte
|
|
||||||
|
|
||||||
// the following line should be identical in operation
|
|
||||||
// to the lines above, but for the moment, I'm not convinced
|
|
||||||
// this method is bug-free. At least it's simpler!
|
|
||||||
//outw(OCR1A, inw(OCR1A) + PulseT1APeriodTics);
|
|
||||||
// change again
|
|
||||||
OCR1A += PulseT1APeriodTics;
|
|
||||||
|
|
||||||
// decrement the number of pulses executed
|
|
||||||
if(PulseT1AMode & PULSE_MODE_COUNTED)
|
|
||||||
PulseT1ACount--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// pulse count has reached zero
|
|
||||||
// disable the output compare's action on OC1A pin
|
|
||||||
cbi(TCCR1A,COM1A1);
|
|
||||||
cbi(TCCR1A,COM1A0);
|
|
||||||
// and disable the output compare's interrupt to stop pulsing
|
|
||||||
cbi(TIMSK, OCIE1A);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void pulseT1BService(void)
|
|
||||||
{
|
|
||||||
// check if TimerPulseACount is non-zero
|
|
||||||
// (i.e. pulses are still requested)
|
|
||||||
if(PulseT1BCount)
|
|
||||||
{
|
|
||||||
//u16 OCValue;
|
|
||||||
// read in current value of output compare register OCR1B
|
|
||||||
//OCValue = inp(OCR1BL); // read low byte of OCR1B
|
|
||||||
//OCValue += inp(OCR1BH)<<8; // read high byte of OCR1B
|
|
||||||
// increment OCR1B value by PulseT1BPeriodTics
|
|
||||||
//OCValue += PulseT1BPeriodTics;
|
|
||||||
// set future output compare time to this new value
|
|
||||||
//outp((OCValue>>8), OCR1BH); // write high byte
|
|
||||||
//outp((OCValue & 0x00FF),OCR1BL); // write low byte
|
|
||||||
|
|
||||||
// the following line should be identical in operation
|
|
||||||
// to the lines above, but for the moment, I'm not convinced
|
|
||||||
// this method is bug-free. At least it's simpler!
|
|
||||||
//outw(OCR1B, inw(OCR1B) + PulseT1BPeriodTics);
|
|
||||||
// change again
|
|
||||||
OCR1B += PulseT1BPeriodTics;
|
|
||||||
|
|
||||||
|
|
||||||
// decrement the number of pulses executed
|
|
||||||
if(PulseT1BMode & PULSE_MODE_COUNTED)
|
|
||||||
PulseT1BCount--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// pulse count has reached zero
|
|
||||||
// disable the output compare's action on OC1B pin
|
|
||||||
cbi(TCCR1A,COM1B1);
|
|
||||||
cbi(TCCR1A,COM1B0);
|
|
||||||
// and disable the output compare's interrupt to stop pulsing
|
|
||||||
cbi(TIMSK, OCIE1B);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,98 +0,0 @@
|
|||||||
/*! \file pulse.h \brief Pulse/frequency generation function library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'pulse.h'
|
|
||||||
// Title : Pulse/frequency generation function library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2000-2002
|
|
||||||
// Created : 2002-08-19
|
|
||||||
// Revised : 2003-05-29
|
|
||||||
// Version : 0.7
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// Description : This library is designed to facilitate the output of square
|
|
||||||
// wave pulses at a frequency determined by the user. The library uses
|
|
||||||
// the AVR processor built-in timers and the output is on the timer Output
|
|
||||||
// Compare (OC) pins.
|
|
||||||
//
|
|
||||||
// The allowable range of frequencies which can be generated is governed
|
|
||||||
// by the tic rate of the timer (therefore the CPU clock rate and the
|
|
||||||
// timer prescaler), and the computing speed of the processor itself. See
|
|
||||||
// the SetFreq commands for more details.
|
|
||||||
//
|
|
||||||
// NOTE: in order for the pulse library to work, pulseInit() will attach
|
|
||||||
// the pulse service routines to the timer interrupts using the
|
|
||||||
// timerAttach function. You must not detach the service routines during
|
|
||||||
// pulse library operation.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef PULSE_H
|
|
||||||
#define PULSE_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
// constants/macros/typdefs
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
// Master Pulse Commands
|
|
||||||
// pulseInit()
|
|
||||||
// Initializes the pulse system/library.
|
|
||||||
void pulseInit(void);
|
|
||||||
|
|
||||||
// Pulse commands for timer1
|
|
||||||
// pulseT1Init()
|
|
||||||
// configures the timer1 hardware to produce pulses on pins OC1A and OC1B.
|
|
||||||
// A "pulse" is considered to be one high and low period of a square wave.
|
|
||||||
void pulseT1Init(void);
|
|
||||||
|
|
||||||
// pulseT1Off()
|
|
||||||
// Turns pulse output off immediately (cancels running pulse operations).
|
|
||||||
// Unconfigures hardware and interrupts.
|
|
||||||
void pulseT1Off(void);
|
|
||||||
|
|
||||||
// pulseT1ASetFreq() and pulseT1BSetFreq()
|
|
||||||
// sets the frequency in hertz for each channel of square-wave pulse output
|
|
||||||
// Note1: the freqency <freqHz> must always be greater than zero
|
|
||||||
// Note2: both channels share the same frequency range which is governed
|
|
||||||
// by the timer1 prescaler setting. A prescaler setting of DIV/8 allows
|
|
||||||
// frequencies of a few hertz through a few kilohertz.
|
|
||||||
//
|
|
||||||
// Lower frequency bound = overflow rate of timer1 at current prescaling
|
|
||||||
// Upper frequency bound = the tics rate of timer1 at current prescaling,
|
|
||||||
// or approx. the (clock rate of the processor)/50,
|
|
||||||
// whichever is smaller
|
|
||||||
void pulseT1ASetFreq(u16 freqHz);
|
|
||||||
void pulseT1BSetFreq(u16 freqHz);
|
|
||||||
|
|
||||||
// pulseT1ARun() and pulseT1BRun();
|
|
||||||
// Sets the number of square-wave pulses to be output on the given channel.
|
|
||||||
// For continuous (unlimited) pulse output, use nPulses = 0. Pulses begin
|
|
||||||
// coming out immediately.
|
|
||||||
// Note: <nPulses> must be between 0 and 32767
|
|
||||||
void pulseT1ARun(u16 nPulses);
|
|
||||||
void pulseT1BRun(u16 nPulses);
|
|
||||||
|
|
||||||
// pulseT1AStop() and pulseT1BStop();
|
|
||||||
// Stop pulse output at the next cycle (regardless of the number of
|
|
||||||
// remaining pulses).
|
|
||||||
void pulseT1AStop(void);
|
|
||||||
void pulseT1BStop(void);
|
|
||||||
|
|
||||||
// pulseT1ARemaining() and pulseT1BRemaining()
|
|
||||||
// Returns the number of pulses remaining to be output for each channel.
|
|
||||||
// This function is useful for figuring out if the pulses are done.
|
|
||||||
u16 pulseT1ARemaining(void);
|
|
||||||
u16 pulseT1BRemaining(void);
|
|
||||||
|
|
||||||
// pulseT1AService() and pulseT1BService()
|
|
||||||
// Interrupt service routines for pulse output (do not call these functions directly)
|
|
||||||
void pulseT1AService(void);
|
|
||||||
void pulseT1BService(void);
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,153 +0,0 @@
|
|||||||
/*! \file pwmsw.c \brief Software interrupt-driven multi-output PWM function library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'pwmsw.c'
|
|
||||||
// Title : Software interrupt-driven multi-output PWM function library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002
|
|
||||||
// Created : 7/20/2002
|
|
||||||
// Revised : 7/31/2002
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// WARNING: this PWM library does not work perfectly. It has known and
|
|
||||||
// understood problems when two or more PWM outputs are set to nearly the
|
|
||||||
// same duty cycle. IT MAY NOT BE WORTH USING! YOU HAVE BEEN WARNED!
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
#include <avr/io.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include "pwmsw.h"
|
|
||||||
|
|
||||||
// Program ROM constants
|
|
||||||
|
|
||||||
// Global variables
|
|
||||||
// PWM channel registers
|
|
||||||
u16 PosTics;
|
|
||||||
u16 PeriodTics;
|
|
||||||
u08 Channel;
|
|
||||||
SwPwmChannelType SwPwmChannels[SWPWM_NUM_CHANNELS];
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
// initializes software PWM system
|
|
||||||
void pwmswInit(u16 periodTics)
|
|
||||||
{
|
|
||||||
u08 index;
|
|
||||||
|
|
||||||
// attach the software PWM service routine to timer1 output compare A
|
|
||||||
timerAttach(TIMER1OUTCOMPAREA_INT, pwmswService);
|
|
||||||
// set PeriodTics
|
|
||||||
PeriodTics = periodTics;
|
|
||||||
// set PosTics
|
|
||||||
PosTics = 0;
|
|
||||||
// clear channels
|
|
||||||
for(index=0; index<SWPWM_NUM_CHANNELS; index++)
|
|
||||||
{
|
|
||||||
SwPwmChannels[index].duty = 0;
|
|
||||||
SwPwmChannels[index].setduty = 0;
|
|
||||||
}
|
|
||||||
// set initial interrupt time
|
|
||||||
u16 OCValue;
|
|
||||||
// read in current value of output compare register OCR1A
|
|
||||||
OCValue = inb(OCR1AL); // read low byte of OCR1A
|
|
||||||
OCValue += inb(OCR1AH)<<8; // read high byte of OCR1A
|
|
||||||
// increment OCR1A value by nextTics
|
|
||||||
OCValue += PeriodTics;
|
|
||||||
// set future output compare time to this new value
|
|
||||||
outb(OCR1AH, (OCValue>>8)); // write high byte
|
|
||||||
outb(OCR1AL, (OCValue & 0x00FF)); // write low byte
|
|
||||||
|
|
||||||
// enable the timer1 output compare A interrupt
|
|
||||||
sbi(TIMSK, OCIE1A);
|
|
||||||
}
|
|
||||||
|
|
||||||
// turns off software PWM system
|
|
||||||
void pwmswOff(void)
|
|
||||||
{
|
|
||||||
// disable the timer1 output compare A interrupt
|
|
||||||
cbi(TIMSK, OCIE1A);
|
|
||||||
// detach the service routine
|
|
||||||
timerDetach(TIMER1OUTCOMPAREA_INT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set duty on channel
|
|
||||||
void pwmswPWMSet(u08 channel, u16 duty)
|
|
||||||
{
|
|
||||||
// compare with max value of PeriodTics
|
|
||||||
duty = MIN(duty, PeriodTics);
|
|
||||||
SwPwmChannels[channel].setduty = duty;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pwmswService(void)
|
|
||||||
{
|
|
||||||
u16 nextTics=PeriodTics;
|
|
||||||
u08 index;
|
|
||||||
|
|
||||||
// check for beginning of period
|
|
||||||
if(PosTics == 0)
|
|
||||||
{
|
|
||||||
// examine all channels
|
|
||||||
for(index=0; index<SWPWM_NUM_CHANNELS; index++)
|
|
||||||
{
|
|
||||||
// transfer set-duty to active-duty
|
|
||||||
SwPwmChannels[index].duty = SwPwmChannels[index].setduty;
|
|
||||||
// find next channel event to schedule
|
|
||||||
// if no channel has a duty setting greater than 0 (PosTics);
|
|
||||||
// nextTics will remain at PeriodTics for the next cycle
|
|
||||||
if(SwPwmChannels[index].duty)
|
|
||||||
{
|
|
||||||
nextTics = MIN(nextTics, SwPwmChannels[index].duty);
|
|
||||||
// set all non-zero channels to on
|
|
||||||
outb(SWPWMPORT, inb(SWPWMPORT) | (1<<index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// examine all channels
|
|
||||||
for(index=0; index<SWPWM_NUM_CHANNELS; index++)
|
|
||||||
{
|
|
||||||
// check if we have a duty cycle match
|
|
||||||
if(PosTics == SwPwmChannels[index].duty)
|
|
||||||
{
|
|
||||||
// clear output channel
|
|
||||||
outb(SWPWMPORT, inb(SWPWMPORT) & ~(1<<index));
|
|
||||||
}
|
|
||||||
// find next channel event to schedule
|
|
||||||
// if no channel has a duty setting greater than PosTics;
|
|
||||||
// nextTics will remain at PeriodTics and is handled below
|
|
||||||
if(SwPwmChannels[index].duty > PosTics)
|
|
||||||
nextTics = MIN(nextTics, SwPwmChannels[index].duty-PosTics);
|
|
||||||
}
|
|
||||||
if(nextTics == PeriodTics)
|
|
||||||
{
|
|
||||||
// no more channels to schedule
|
|
||||||
// schedule next cycle
|
|
||||||
nextTics = PeriodTics - PosTics;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// schedule next interrupt
|
|
||||||
u16 OCValue;
|
|
||||||
// read in current value of output compare register OCR1A
|
|
||||||
OCValue = inb(OCR1AL); // read low byte of OCR1A
|
|
||||||
OCValue += inb(OCR1AH)<<8; // read high byte of OCR1A
|
|
||||||
// increment OCR1A value by nextTics
|
|
||||||
OCValue += nextTics;
|
|
||||||
// OCR1A+=nextTics;
|
|
||||||
// set future output compare time to this new value
|
|
||||||
outb(OCR1AH, (OCValue>>8)); // write high byte
|
|
||||||
outb(OCR1AL, (OCValue & 0x00FF)); // write low byte
|
|
||||||
// set our new tic position
|
|
||||||
PosTics += nextTics;
|
|
||||||
if(PosTics >= PeriodTics) PosTics -= PeriodTics;
|
|
||||||
}
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
|||||||
/*! \file pwmsw.h \brief Software interrupt-driven multi-output PWM function library. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'pwmsw.h'
|
|
||||||
// Title : Software interrupt-driven multi-output PWM function library
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2002
|
|
||||||
// Created : 7/20/2002
|
|
||||||
// Revised : 7/31/2002
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR Series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// WARNING: this PWM library does not work perfectly. It has known and
|
|
||||||
// understood problems when two or more PWM outputs are set to nearly the
|
|
||||||
// same duty cycle. IT MAY NOT BE WORTH USING! YOU HAVE BEEN WARNED!
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef PWMSW_H
|
|
||||||
#define PWMSW_H
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include "timer.h"
|
|
||||||
|
|
||||||
// constants/macros/typdefs
|
|
||||||
typedef struct struct_SwPwmChannel
|
|
||||||
{
|
|
||||||
u08 port; ///< channel's hardware I/O port
|
|
||||||
u08 pin; ///< channel's hardware I/O pin
|
|
||||||
u16 duty; ///< active PWM duty setting
|
|
||||||
u16 setduty; ///< requested PWM duty setting
|
|
||||||
} SwPwmChannelType;
|
|
||||||
|
|
||||||
// number of PWM channels
|
|
||||||
#define SWPWM_NUM_CHANNELS 3
|
|
||||||
// define port
|
|
||||||
#define SWPWMPORT PORTB
|
|
||||||
#define SWPWMDDR DDRB
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
//! initializes software PWM system
|
|
||||||
void pwmswInit(u16 periodTics);
|
|
||||||
|
|
||||||
//! turns off software PWM system
|
|
||||||
void pwmswOff(void);
|
|
||||||
|
|
||||||
//! set duty on channel
|
|
||||||
void pwmswPWMSet(u08 channel, u16 duty);
|
|
||||||
|
|
||||||
//! software PWM interrupt service routine
|
|
||||||
void pwmswService(void);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,340 +0,0 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Procyon AVRlib Release Notes</title>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<!--#config timefmt="%a %b %d, %Y" -->
|
|
||||||
<h1 align="center">Procyon AVRlib Release Notes</h1>
|
|
||||||
<center>Written by Pascal Stang | Updated:
|
|
||||||
<!--#echo var="LAST_MODIFIED" -->
|
|
||||||
</center>
|
|
||||||
<hr>
|
|
||||||
<p><strong>3/12/2005</strong>
|
|
||||||
<ul>
|
|
||||||
<li>Fixed AVRlib to comply to new WinAVR package (avr-libc has dropped several
|
|
||||||
methods that were depricated causing the old AVRlib to fail to compile). Sorry
|
|
||||||
about the delay. Please note that I've changed small parts of dozens of files.
|
|
||||||
I may have introduced bugs that I haven't yet detected. Your feedback welcome.</li>
|
|
||||||
</ul>
|
|
||||||
<p><strong>1/30/2005</strong>
|
|
||||||
<ul>
|
|
||||||
<li>Added new <strong>lis3l02</strong> accelerometer library. This ST accelerometer
|
|
||||||
incorporates a 3-axis sensor and A/D converter in one 28-pin SOIC package
|
|
||||||
with I2C and SPI bus. Unfortunately, the production future of the digital
|
|
||||||
version of this accelerometer is unknown.</li>
|
|
||||||
<li>Added new <strong>extint</strong> external interrupt library. The library
|
|
||||||
is not complete, but does work nicely for some processors. It is primarily
|
|
||||||
designed to do two things:
|
|
||||||
<ul>
|
|
||||||
<li>abstract AVR external interrupts so that programs which use them can
|
|
||||||
more easily cross-compile between different processors</li>
|
|
||||||
<li>allow novice (and even advanced) users to be able to use external interrupts
|
|
||||||
without looking up a bunch of register and bit defines in the datasheets.</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li>Revised GPS library to standardize on units used for latitude/longitude
|
|
||||||
angles</li>
|
|
||||||
<li>Improved NMEA library. Packet processing function now returns type of packet
|
|
||||||
decoded. Packet parsers reject valid but empty packets.</li>
|
|
||||||
<li>MMC library has proper #defines to turn on/off debugging statements</li>
|
|
||||||
<li>uartsw and uartsw2 libraries now support optional inversion of serial signal
|
|
||||||
via #define in conf file</li>
|
|
||||||
</ul>
|
|
||||||
<p><strong></strong><strong>10/15/2004</strong>
|
|
||||||
<ul>
|
|
||||||
<li>Added new spieeprom library. Not quite sure if it works properly.</li>
|
|
||||||
</ul>
|
|
||||||
<p><strong></strong><strong>9/25/2004</strong>
|
|
||||||
<ul>
|
|
||||||
<li>Added a simple MultiMedia Card / SecureDigital Card interface library. The
|
|
||||||
library allows you to read and write sector-sized (512 byte) data chunks.
|
|
||||||
Please see mmc.h for information about how to connect the card to the microcontroller.</li>
|
|
||||||
<li>Added uartGetByte() functions to uart.c and uart2.c. These functions emulate
|
|
||||||
the typical getchar() function and return a received character if available,
|
|
||||||
otherwise -1.</li>
|
|
||||||
<li>Fixed bug causing incorrect I2C bus speed.</li>
|
|
||||||
</ul>
|
|
||||||
<p><strong>6/25/2004</strong>
|
|
||||||
<ul>
|
|
||||||
<li>Changed encoder library to new read-in scheme which is more technically
|
|
||||||
correct and resistant to error. New scheme counts both rising and falling
|
|
||||||
edges of PHASEA, so be prepared for twice the precision (you'll get double
|
|
||||||
the usual number of counts per revolution).</li>
|
|
||||||
<li>Added timer functions to exploit arbitrary frequency/precision PWM in new
|
|
||||||
AVR processors</li>
|
|
||||||
<li>Fixed timerPause() precision management bug in Timer/Timer128 libraries.<br>
|
|
||||||
TimerPause function should now work correctly for longer delays</li>
|
|
||||||
<li>Added timerXGetPrescaler() functions to timer libraries to avoid code maintenance
|
|
||||||
issues and to reduce overall code size</li>
|
|
||||||
<li>Fixed bug in Pulse library that cause wildly incorrect frequencies to be
|
|
||||||
produced</li>
|
|
||||||
</ul>
|
|
||||||
<p><strong>5/04/2004</strong>
|
|
||||||
<ul>
|
|
||||||
<li>Added MegaIO directory with simple routines for accessing the MegaIO peripheral
|
|
||||||
expander. MegaIO allows you to use a slave AVR processor as a peripheral expander
|
|
||||||
and control it easily from a master AVR processor over the I2C bus. This gives
|
|
||||||
your master processor easy access to: an extra buffered UART, extra PWM outputs,
|
|
||||||
extra A/D inputs, extra I/O lines, extra RAM, and more.</li>
|
|
||||||
</ul>
|
|
||||||
<p><strong>2/27/2004</strong>
|
|
||||||
<ul>
|
|
||||||
<li>Improved original Software UART library (uartsw: uses Timer1 OC1A OC1B and
|
|
||||||
IC1)</li>
|
|
||||||
<li>Added new Software UART library (uartsw2: uses Timer0 and Timer2 and INT2)</li>
|
|
||||||
<li>Fixed small but catastrophic bug in the Software Memory Bus (sramsw)</li>
|
|
||||||
<li>Fixed small but catastrophic bug in the Timer library when using Timer 0
|
|
||||||
Output Compare</li>
|
|
||||||
<li>Fixed Timer128 library bug when using Timer 3 Output Compare B</li>
|
|
||||||
<li>Added support for ICR top-count PWM when supported by processor</li>
|
|
||||||
<li><strong>Thanks to all the users who have offered bugfixes and feedback!</strong></li>
|
|
||||||
</ul>
|
|
||||||
<p><strong>2/22/2004</strong>
|
|
||||||
<ul>
|
|
||||||
<li>Added ADS7828 I2C A/D Converter Library + example code</li>
|
|
||||||
<li>Added DS1631 I2C Temperature Sensor Library + example code</li>
|
|
||||||
<li>Timer/Timer128 Library</li>
|
|
||||||
<ol>
|
|
||||||
<li>For processor that support it, timerPause() will sleep the processor during the delay time,
|
|
||||||
thereby reducing power consumption. All interrupts are still active so hopefully this shouldn't
|
|
||||||
break anybody's code.</li>
|
|
||||||
<li>The timer library will now compile properly for the processors with only timers 0,1
|
|
||||||
(by excluding timer2 functions automatically)</li>
|
|
||||||
<li>Bugfix on Timer3 initialization</li>
|
|
||||||
<li>A big thanks to those that wrote in to report bugs or offer suggestions for improvement!</li>
|
|
||||||
</ol>
|
|
||||||
<li>Servo Library: optimized slightly</li>
|
|
||||||
<li>UART/UART2 Library: Improved compile compatibility across more AVR processors</li>
|
|
||||||
</ul>
|
|
||||||
<p><strong>9/15/2003</strong>
|
|
||||||
<ul>
|
|
||||||
<li>I2C Library
|
|
||||||
<ol>
|
|
||||||
<li>A few bugfixes here. i2cMasterSend and i2cMasterReceive finally return
|
|
||||||
error values if the target device is not present. This is especially important
|
|
||||||
in the case of receive because that would otherwise hang. Some debugging
|
|
||||||
has been added to the I2C interrupt state machine. Debugging can be turned
|
|
||||||
on via #define but needs to be customized based on the processor in use.</li>
|
|
||||||
</ol>
|
|
||||||
</ul>
|
|
||||||
<p><strong>7/23/2003</strong>
|
|
||||||
<ul>
|
|
||||||
<li>Cmdline Library (<strong>NEW</strong>)
|
|
||||||
<ol>
|
|
||||||
<li>This library is a complete fairly-easy-to-use command line interface
|
|
||||||
complete with advanced line editing and history buffer. You add the commands
|
|
||||||
and the functions to run for those commands. The arguments passed to your
|
|
||||||
commands are available as strings or interpreted as decimal or hex integers.</li>
|
|
||||||
</ol>
|
|
||||||
<li>Uart/Uart2 Library
|
|
||||||
<ol>
|
|
||||||
<li>Added a new method uartAddToTxBuffer() which adds one character at a
|
|
||||||
time to the uart transmit buffer. The function can be used the the same
|
|
||||||
way as uartSendByte, but writes only to the buffer. This is helpful for
|
|
||||||
printf-ing inside interrupts or time-critical sections.</li>
|
|
||||||
</ol>
|
|
||||||
<li>i2ceeprom function library
|
|
||||||
<ol>
|
|
||||||
<li>Fixed a compile bug that escaped last time.</li>
|
|
||||||
<li>Bugfix: there was an endian-ness discrepancy between the read and write
|
|
||||||
byte routines for the eeprom. Problem has been fixed thanks to feedback
|
|
||||||
from users.</li>
|
|
||||||
</ol>
|
|
||||||
</ul>
|
|
||||||
<p><strong>7/12/2003</strong>
|
|
||||||
<ul>
|
|
||||||
<li>General Note
|
|
||||||
<ol>
|
|
||||||
<li>CAUTION: The makefile and build process for AVRlib has changed to make
|
|
||||||
installation and management simpler. You will need to define an AVRLIB
|
|
||||||
environment variable to point to the location where you keep AVRlib. See
|
|
||||||
the revised installation guide for more details.</li>
|
|
||||||
<li>I made a lot of small fixes to various libraries without properly recording
|
|
||||||
the changes. Sorry.</li>
|
|
||||||
</ol>
|
|
||||||
<li>STX/ETX function library
|
|
||||||
<ol>
|
|
||||||
<li>The receiving packet engine has been revised for the stx/etx protocol.
|
|
||||||
It's somewhat less stupidly coded now and should perform better. Fixed
|
|
||||||
a bug that made servicing an empty receive buffer excessively long.</li>
|
|
||||||
</ol>
|
|
||||||
<li>Timer/Timer128 function library
|
|
||||||
<ol>
|
|
||||||
<li>Since the creation of the timer library, the timerPause function had
|
|
||||||
a bug/deficiency which caused it to be either slightly or grossly off
|
|
||||||
in timing depending on the delay requested and the current prescaler setting.
|
|
||||||
This bug is now fixed at the expense of a little extra code and timing
|
|
||||||
performance should be considerably more accurate.</li>
|
|
||||||
</ol>
|
|
||||||
</ul>
|
|
||||||
<p><strong>6/06/2003</strong>
|
|
||||||
<ul>
|
|
||||||
<li>General Note
|
|
||||||
<ol>
|
|
||||||
<li>I've recently seen the need for more project-dependent configurable
|
|
||||||
settings in the core AVRlib libraries (uart, timer, rprintf). Rather than
|
|
||||||
creating a smorgasboard of new "conf" files to handle the settings,
|
|
||||||
I've decided to handle most things via #ifdefs and user-optional #defines.
|
|
||||||
My feeling is that for core libraries, it nice to not have to lug around
|
|
||||||
"conf" files all the time. We'll see how it goes...</li>
|
|
||||||
</ol>
|
|
||||||
<li>UART and UART2 function libraries
|
|
||||||
<ol>
|
|
||||||
<li>You can now override the default UART receive handling (placing of the
|
|
||||||
data into the receive buffer), by using the uartSetRxHandler() function
|
|
||||||
and providing your own function.</li>
|
|
||||||
<li>You can now adjust the default size of the UART Rx/Tx buffers by #defining
|
|
||||||
the size before including uart.h. I recommend placing such #defines in
|
|
||||||
your global.h.</li>
|
|
||||||
</ol>
|
|
||||||
<li>UARTSW function library
|
|
||||||
<ol>
|
|
||||||
<li>Out of personal need, I have finally gotten the software-driven UART
|
|
||||||
code working. Please consider this an alpha release. It works well, but
|
|
||||||
the library is still in flux.</li>
|
|
||||||
</ol>
|
|
||||||
<li>A2D function library
|
|
||||||
<ol>
|
|
||||||
<li>Efforts are being made to make the A2D functions compatible (compile
|
|
||||||
transparently) over a greater range of AVR processors including the new
|
|
||||||
Mega8,16,32,64. Please be patient if proper support for your processor
|
|
||||||
is temporarily broken.</li>
|
|
||||||
</ol>
|
|
||||||
<li>Timer/Timer128 function library
|
|
||||||
<ol>
|
|
||||||
<li>#defines have been added to specify the timer prescaler rates on RealTimeClock-equipped
|
|
||||||
timer. You may have noticed that the RTC-equipped timer always has a different
|
|
||||||
prescaler selection range than the other timers. You must use the new
|
|
||||||
TIMERRTC_CLK_DIV defines instead of the TIMER_CLK_DIV defines on these
|
|
||||||
timers, otherwise you will get wrong results. </li>
|
|
||||||
<li>You can now change the default interrupt handler type (INTERRUPT vs.
|
|
||||||
SIGNAL) used for the timers by #defining it before including timer.h.
|
|
||||||
I recommend placing such #defines in your global.h.</li>
|
|
||||||
</ol>
|
|
||||||
</ul>
|
|
||||||
<p><strong>5/29/2003</strong>
|
|
||||||
<ul>
|
|
||||||
<li>Pulse function library
|
|
||||||
<ol>
|
|
||||||
<li>There are two new functions PulseT1AStop() and PulseT1BStop(), that
|
|
||||||
allow the stopping of pulse output regardless of the previously programmed
|
|
||||||
number of pulses to be output. The new stop commands are crucial when
|
|
||||||
using the continuous pulse output mode.</li>
|
|
||||||
</ol>
|
|
||||||
</ul>
|
|
||||||
<p><strong>5/1/2003</strong>
|
|
||||||
<ul>
|
|
||||||
<li>KS0108 Graphic LCD driver library
|
|
||||||
<ol>
|
|
||||||
<li>Made some improvements to the code structure and #define names, eliminates
|
|
||||||
some unnecessary lines.</li>
|
|
||||||
<li>Implemented <font color="#FF0000">untested</font> support for up to
|
|
||||||
4 controller chips (240x64 pixel display).</li>
|
|
||||||
</ol>
|
|
||||||
<li>rprintf library
|
|
||||||
<ol>
|
|
||||||
<li>Thanks to some feedback, and some testing, I recently realized I had
|
|
||||||
doubled the compiled size of the printf library when I added a floating-point
|
|
||||||
print function a several months ago.</li>
|
|
||||||
<li>The floating-point print can now be enabled or disabled in the rprintfconf.h
|
|
||||||
file. (it is disabled by default)</li>
|
|
||||||
</ol>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p><strong>4/30/2003</strong>
|
|
||||||
<ul>
|
|
||||||
<li>Uart function library
|
|
||||||
<ol>
|
|
||||||
<li>Like the timer library, you can now universally switch from SIGNAL-type
|
|
||||||
interrupt handlers to INTERRUPT-type handlers by changing a #define in
|
|
||||||
uart.h or uart2.h. Note, for the time being, I'm avoiding creating a "conf"
|
|
||||||
file for the uart libraries because of their widespread use. Don't want
|
|
||||||
to confuse users any mor than I have to.</li>
|
|
||||||
</ol>
|
|
||||||
<li>Pulse function library </li>
|
|
||||||
<ol>
|
|
||||||
<li>Fixed a major bug which caused some pulse output requests to idle until
|
|
||||||
the timer overflowed</li>
|
|
||||||
</ol>
|
|
||||||
<li>ATA/IDE interface driver</li>
|
|
||||||
<ol>
|
|
||||||
<li>Brought this code out of basic disrepair and into service again - effort
|
|
||||||
will continue as time permits</li>
|
|
||||||
</ol>
|
|
||||||
<li>FAT filesystem driver
|
|
||||||
<ol>
|
|
||||||
<li>Brought this code out of basic disrepair and into service again - effort
|
|
||||||
will continue as time permits</li>
|
|
||||||
<li>Will attempt to improve the overall interface for FAT as well as begin
|
|
||||||
to support file writing</li>
|
|
||||||
</ol>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p><strong>3/13/2003</strong>
|
|
||||||
<ul>
|
|
||||||
<li>New "debug" function library
|
|
||||||
<ol>
|
|
||||||
<li>Added a new library for general functions useful when debugging. Currently
|
|
||||||
the only available function is for nicely formatted hex/ascii table dumps
|
|
||||||
(useful when inspecting memory or buffers).</li>
|
|
||||||
</ol>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p><strong>3/2/2003</strong>
|
|
||||||
<ul>
|
|
||||||
<li>I2C Library
|
|
||||||
<ol>
|
|
||||||
<li>Continued updating of I2C library - NOTE: some old functions have changed
|
|
||||||
names slightly to clarify their purpose and relationship to new functions.</li>
|
|
||||||
<li>Added two function pointers designed to be set by the user to handle
|
|
||||||
incoming Slave Receive and Slave Transmit operations.</li>
|
|
||||||
<li>Added i2cMasterTransfer function which does the common write-then-read
|
|
||||||
operation with repeated start in between so control of the bus is not
|
|
||||||
lost. This kind of access is common when accessing memories or register
|
|
||||||
based devices where the address must be written before reading back a
|
|
||||||
value. </li>
|
|
||||||
<li>NOTE: Structure of the library continues to change but has solidified
|
|
||||||
substantially.</li>
|
|
||||||
</ol>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</p>
|
|
||||||
<p><strong>2/24/2003</strong>
|
|
||||||
<ul>
|
|
||||||
<li>Encoder Library
|
|
||||||
<ol>
|
|
||||||
<li>Improved interrupt flexibility and processor compatibility for this library</li>
|
|
||||||
<li>Unfortunately, the complexity comes at the cost of a somewhat more complicated
|
|
||||||
encoderconf.h which the user must edit to suit their specific needs on a per-project basis.</li>
|
|
||||||
</ol>
|
|
||||||
</li>
|
|
||||||
<li>I2C Library
|
|
||||||
<ol>
|
|
||||||
<li>Second major revision of I2C library in an attempt to make it general enough to use for
|
|
||||||
any common I2C operations.</li>
|
|
||||||
<li>Changes include the "functionalizing" of basic low-level I2C operations
|
|
||||||
such as generate start,stop, and send address/data.</li>
|
|
||||||
<li>NOTE: Structure of the library has changed somewhat and will likely continue to be refined.</li>
|
|
||||||
</ol>
|
|
||||||
</li>
|
|
||||||
<li>Timer128 Library
|
|
||||||
<ol>
|
|
||||||
<li>Added missing PWM on and off functions in Timer128 library</li>
|
|
||||||
</ol>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</p>
|
|
||||||
<p><strong>2/24/2003</strong>
|
|
||||||
<ul>
|
|
||||||
<li>Release Notes Started</li>
|
|
||||||
</ul>
|
|
||||||
</p>
|
|
||||||
<hr>
|
|
||||||
<center>Written by Pascal Stang | Updated:
|
|
||||||
<!--#echo var="LAST_MODIFIED" -->
|
|
||||||
</center>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,773 +0,0 @@
|
|||||||
/*! \file rprintf.c \brief printf routine and associated routines. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'rprintf.c'
|
|
||||||
// Title : printf routine and associated routines
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2000-2002
|
|
||||||
// Created : 2000.12.26
|
|
||||||
// Revised : 2003.5.1
|
|
||||||
// Version : 1.0
|
|
||||||
// Target MCU : Atmel AVR series and other targets
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
//#include <string-avr.h>
|
|
||||||
//#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include "global.h"
|
|
||||||
#include "rprintf.h"
|
|
||||||
|
|
||||||
#ifndef TRUE
|
|
||||||
#define TRUE -1
|
|
||||||
#define FALSE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define INF 32766 // maximum field size to print
|
|
||||||
#define READMEMBYTE(a,char_ptr) ((a)?(pgm_read_byte(char_ptr)):(*char_ptr))
|
|
||||||
|
|
||||||
#ifdef RPRINTF_COMPLEX
|
|
||||||
static unsigned char buf[128];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// use this to store hex conversion in RAM
|
|
||||||
//static char HexChars[] = "0123456789ABCDEF";
|
|
||||||
// use this to store hex conversion in program memory
|
|
||||||
//static prog_char HexChars[] = "0123456789ABCDEF";
|
|
||||||
static char __attribute__ ((progmem)) HexChars[] = "0123456789ABCDEF";
|
|
||||||
|
|
||||||
// function pointer to single character output routine
|
|
||||||
static void (*rputchar)(unsigned char c);
|
|
||||||
|
|
||||||
// *** rprintf initialization ***
|
|
||||||
// you must call this function once and supply the character output
|
|
||||||
// routine before using other functions in this library
|
|
||||||
void rprintfInit(void (*putchar_func)(unsigned char c))
|
|
||||||
{
|
|
||||||
rputchar = putchar_func;
|
|
||||||
}
|
|
||||||
|
|
||||||
// *** rprintfChar ***
|
|
||||||
// send a character/byte to the current output device
|
|
||||||
inline void rprintfChar(unsigned char c)
|
|
||||||
{
|
|
||||||
// send character
|
|
||||||
rputchar(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
// *** rprintfStr ***
|
|
||||||
// prints a null-terminated string stored in RAM
|
|
||||||
void rprintfStr(char str[])
|
|
||||||
{
|
|
||||||
// send a string stored in RAM
|
|
||||||
// check to make sure we have a good pointer
|
|
||||||
if (!str) return;
|
|
||||||
|
|
||||||
// print the string until a null-terminator
|
|
||||||
while (*str)
|
|
||||||
rprintfChar(*str++);
|
|
||||||
}
|
|
||||||
|
|
||||||
// *** rprintfStrLen ***
|
|
||||||
// prints a section of a string stored in RAM
|
|
||||||
// begins printing at position indicated by <start>
|
|
||||||
// prints number of characters indicated by <len>
|
|
||||||
void rprintfStrLen(char str[], unsigned int start, unsigned int len)
|
|
||||||
{
|
|
||||||
register int i=0;
|
|
||||||
|
|
||||||
// check to make sure we have a good pointer
|
|
||||||
if (!str) return;
|
|
||||||
// spin through characters up to requested start
|
|
||||||
// keep going as long as there's no null
|
|
||||||
while((i++<start) && (*str++));
|
|
||||||
// for(i=0; i<start; i++)
|
|
||||||
// {
|
|
||||||
// // keep steping through string as long as there's no null
|
|
||||||
// if(*str) str++;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// then print exactly len characters
|
|
||||||
for(i=0; i<len; i++)
|
|
||||||
{
|
|
||||||
// print data out of the string as long as we haven't reached a null yet
|
|
||||||
// at the null, start printing spaces
|
|
||||||
if(*str)
|
|
||||||
rprintfChar(*str++);
|
|
||||||
else
|
|
||||||
rprintfChar(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// *** rprintfProgStr ***
|
|
||||||
// prints a null-terminated string stored in program ROM
|
|
||||||
void rprintfProgStr(const prog_char str[])
|
|
||||||
{
|
|
||||||
// print a string stored in program memory
|
|
||||||
register char c;
|
|
||||||
|
|
||||||
// check to make sure we have a good pointer
|
|
||||||
if (!str) return;
|
|
||||||
|
|
||||||
// print the string until the null-terminator
|
|
||||||
while((c = pgm_read_byte(str++)))
|
|
||||||
rprintfChar(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
// *** rprintfCRLF ***
|
|
||||||
// prints carriage return and line feed
|
|
||||||
void rprintfCRLF(void)
|
|
||||||
{
|
|
||||||
// print CR/LF
|
|
||||||
rprintfChar('\r');
|
|
||||||
rprintfChar('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
// *** rprintfu04 ***
|
|
||||||
// prints an unsigned 4-bit number in hex (1 digit)
|
|
||||||
void rprintfu04(unsigned char data)
|
|
||||||
{
|
|
||||||
// print 4-bit hex value
|
|
||||||
// char Character = data&0x0f;
|
|
||||||
// if (Character>9)
|
|
||||||
// Character+='A'-10;
|
|
||||||
// else
|
|
||||||
// Character+='0';
|
|
||||||
rprintfChar(pgm_read_byte( HexChars+(data&0x0f) ));
|
|
||||||
}
|
|
||||||
|
|
||||||
// *** rprintfu08 ***
|
|
||||||
// prints an unsigned 8-bit number in hex (2 digits)
|
|
||||||
void rprintfu08(unsigned char data)
|
|
||||||
{
|
|
||||||
// print 8-bit hex value
|
|
||||||
rprintfu04(data>>4);
|
|
||||||
rprintfu04(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// *** rprintfu16 ***
|
|
||||||
// prints an unsigned 16-bit number in hex (4 digits)
|
|
||||||
void rprintfu16(unsigned short data)
|
|
||||||
{
|
|
||||||
// print 16-bit hex value
|
|
||||||
rprintfu08(data>>8);
|
|
||||||
rprintfu08(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// *** rprintfu32 ***
|
|
||||||
// prints an unsigned 32-bit number in hex (8 digits)
|
|
||||||
void rprintfu32(unsigned long data)
|
|
||||||
{
|
|
||||||
// print 32-bit hex value
|
|
||||||
rprintfu16(data>>16);
|
|
||||||
rprintfu16(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// *** rprintfNum ***
|
|
||||||
// special printf for numbers only
|
|
||||||
// see formatting information below
|
|
||||||
// Print the number "n" in the given "base"
|
|
||||||
// using exactly "numDigits"
|
|
||||||
// print +/- if signed flag "isSigned" is TRUE
|
|
||||||
// use the character specified in "padchar" to pad extra characters
|
|
||||||
//
|
|
||||||
// Examples:
|
|
||||||
// uartPrintfNum(10, 6, TRUE, ' ', 1234); --> " +1234"
|
|
||||||
// uartPrintfNum(10, 6, FALSE, '0', 1234); --> "001234"
|
|
||||||
// uartPrintfNum(16, 6, FALSE, '.', 0x5AA5); --> "..5AA5"
|
|
||||||
void rprintfNum(char base, char numDigits, char isSigned, char padchar, long n)
|
|
||||||
{
|
|
||||||
// define a global HexChars or use line below
|
|
||||||
//static char HexChars[16] = "0123456789ABCDEF";
|
|
||||||
char *p, buf[32];
|
|
||||||
unsigned long x;
|
|
||||||
unsigned char count;
|
|
||||||
|
|
||||||
// prepare negative number
|
|
||||||
if( isSigned && (n < 0) )
|
|
||||||
{
|
|
||||||
x = -n;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup little string buffer
|
|
||||||
count = (numDigits-1)-(isSigned?1:0);
|
|
||||||
p = buf + sizeof (buf);
|
|
||||||
*--p = '\0';
|
|
||||||
|
|
||||||
// force calculation of first digit
|
|
||||||
// (to prevent zero from not printing at all!!!)
|
|
||||||
*--p = pgm_read_byte(HexChars + (x%base)); x /= base;
|
|
||||||
// calculate remaining digits
|
|
||||||
while(count--)
|
|
||||||
{
|
|
||||||
if(x != 0)
|
|
||||||
{
|
|
||||||
// calculate next digit
|
|
||||||
*--p = pgm_read_byte(HexChars + (x%base)); x /= base;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// no more digits left, pad out to desired length
|
|
||||||
*--p = padchar;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply signed notation if requested
|
|
||||||
if( isSigned )
|
|
||||||
{
|
|
||||||
if(n < 0)
|
|
||||||
{
|
|
||||||
*--p = '-';
|
|
||||||
}
|
|
||||||
else if(n > 0)
|
|
||||||
{
|
|
||||||
*--p = '+';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*--p = ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// print the string right-justified
|
|
||||||
count = numDigits;
|
|
||||||
while(count--)
|
|
||||||
{
|
|
||||||
rprintfChar(*p++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef RPRINTF_FLOAT
|
|
||||||
// *** rprintfFloat ***
|
|
||||||
// floating-point print
|
|
||||||
void rprintfFloat(char numDigits, double x)
|
|
||||||
{
|
|
||||||
unsigned char firstplace = FALSE;
|
|
||||||
unsigned char negative;
|
|
||||||
unsigned char i, digit;
|
|
||||||
double place = 1.0;
|
|
||||||
|
|
||||||
// save sign
|
|
||||||
negative = (x<0);
|
|
||||||
// convert to absolute value
|
|
||||||
x = (x>0)?(x):(-x);
|
|
||||||
|
|
||||||
// find starting digit place
|
|
||||||
for(i=0; i<15; i++)
|
|
||||||
{
|
|
||||||
if((x/place) < 10.0)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
place *= 10.0;
|
|
||||||
}
|
|
||||||
// print polarity character
|
|
||||||
if(negative)
|
|
||||||
rprintfChar('-');
|
|
||||||
else
|
|
||||||
rprintfChar('+');
|
|
||||||
|
|
||||||
// print digits
|
|
||||||
for(i=0; i<numDigits; i++)
|
|
||||||
{
|
|
||||||
digit = (x/place);
|
|
||||||
|
|
||||||
if(digit | firstplace | (place == 1.0))
|
|
||||||
{
|
|
||||||
firstplace = TRUE;
|
|
||||||
rprintfChar(digit+0x30);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rprintfChar(' ');
|
|
||||||
|
|
||||||
if(place == 1.0)
|
|
||||||
{
|
|
||||||
rprintfChar('.');
|
|
||||||
}
|
|
||||||
|
|
||||||
x -= (digit*place);
|
|
||||||
place /= 10.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef RPRINTF_SIMPLE
|
|
||||||
// *** rprintf1RamRom ***
|
|
||||||
//! called by rprintf() - does a simple printf (supports %d, %x, %c)
|
|
||||||
// Supports:
|
|
||||||
// %d - decimal
|
|
||||||
// %x - hex
|
|
||||||
// %c - character
|
|
||||||
int rprintf1RamRom(unsigned char stringInRom, const char *format, ...)
|
|
||||||
{
|
|
||||||
// simple printf routine
|
|
||||||
// define a global HexChars or use line below
|
|
||||||
//static char HexChars[16] = "0123456789ABCDEF";
|
|
||||||
char format_flag;
|
|
||||||
unsigned int u_val, div_val, base;
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, format);
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
while ((format_flag = READMEMBYTE(stringInRom,format++) ) != '%')
|
|
||||||
{ // Until '%' or '\0'
|
|
||||||
if (!format_flag)
|
|
||||||
{
|
|
||||||
va_end(ap);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
rprintfChar(format_flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (format_flag = READMEMBYTE(stringInRom,format++) )
|
|
||||||
{
|
|
||||||
case 'c': format_flag = va_arg(ap,int);
|
|
||||||
default: rprintfChar(format_flag); continue;
|
|
||||||
case 'd': base = 10; div_val = 10000; goto CONVERSION_LOOP;
|
|
||||||
case 'x': base = 16; div_val = 0x10;
|
|
||||||
|
|
||||||
CONVERSION_LOOP:
|
|
||||||
u_val = va_arg(ap,int);
|
|
||||||
if (format_flag == 'd')
|
|
||||||
{
|
|
||||||
if (((int)u_val) < 0)
|
|
||||||
{
|
|
||||||
u_val = - u_val;
|
|
||||||
rprintfChar('-');
|
|
||||||
}
|
|
||||||
while (div_val > 1 && div_val > u_val) div_val /= 10;
|
|
||||||
}
|
|
||||||
do
|
|
||||||
{
|
|
||||||
rprintfChar(pgm_read_byte(HexChars+(u_val/div_val)));
|
|
||||||
u_val %= div_val;
|
|
||||||
div_val /= base;
|
|
||||||
} while (div_val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef RPRINTF_COMPLEX
|
|
||||||
// *** rprintf2RamRom ***
|
|
||||||
//! called by rprintf() - does a more powerful printf (supports %d, %u, %o, %x, %c, %s)
|
|
||||||
// Supports:
|
|
||||||
// %d - decimal
|
|
||||||
// %u - unsigned decimal
|
|
||||||
// %o - octal
|
|
||||||
// %x - hex
|
|
||||||
// %c - character
|
|
||||||
// %s - strings
|
|
||||||
// and the width,precision,padding modifiers
|
|
||||||
// **this printf does not support floating point numbers
|
|
||||||
int rprintf2RamRom(unsigned char stringInRom, const char *sfmt, ...)
|
|
||||||
{
|
|
||||||
register unsigned char *f, *bp;
|
|
||||||
register long l;
|
|
||||||
register unsigned long u;
|
|
||||||
register int i;
|
|
||||||
register int fmt;
|
|
||||||
register unsigned char pad = ' ';
|
|
||||||
int flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
|
|
||||||
int sign = 0;
|
|
||||||
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, sfmt);
|
|
||||||
|
|
||||||
f = (unsigned char *) sfmt;
|
|
||||||
|
|
||||||
for (; READMEMBYTE(stringInRom,f); f++)
|
|
||||||
{
|
|
||||||
if (READMEMBYTE(stringInRom,f) != '%')
|
|
||||||
{ // not a format character
|
|
||||||
// then just output the char
|
|
||||||
rprintfChar(READMEMBYTE(stringInRom,f));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
f++; // if we have a "%" then skip it
|
|
||||||
if (READMEMBYTE(stringInRom,f) == '-')
|
|
||||||
{
|
|
||||||
flush_left = 1; // minus: flush left
|
|
||||||
f++;
|
|
||||||
}
|
|
||||||
if (READMEMBYTE(stringInRom,f) == '0'
|
|
||||||
|| READMEMBYTE(stringInRom,f) == '.')
|
|
||||||
{
|
|
||||||
// padding with 0 rather than blank
|
|
||||||
pad = '0';
|
|
||||||
f++;
|
|
||||||
}
|
|
||||||
if (READMEMBYTE(stringInRom,f) == '*')
|
|
||||||
{ // field width
|
|
||||||
f_width = va_arg(ap, int);
|
|
||||||
f++;
|
|
||||||
}
|
|
||||||
else if (Isdigit(READMEMBYTE(stringInRom,f)))
|
|
||||||
{
|
|
||||||
f_width = atoiRamRom(stringInRom, (char *) f);
|
|
||||||
while (Isdigit(READMEMBYTE(stringInRom,f)))
|
|
||||||
f++; // skip the digits
|
|
||||||
}
|
|
||||||
if (READMEMBYTE(stringInRom,f) == '.')
|
|
||||||
{ // precision
|
|
||||||
f++;
|
|
||||||
if (READMEMBYTE(stringInRom,f) == '*')
|
|
||||||
{
|
|
||||||
prec = va_arg(ap, int);
|
|
||||||
f++;
|
|
||||||
}
|
|
||||||
else if (Isdigit(READMEMBYTE(stringInRom,f)))
|
|
||||||
{
|
|
||||||
prec = atoiRamRom(stringInRom, (char *) f);
|
|
||||||
while (Isdigit(READMEMBYTE(stringInRom,f)))
|
|
||||||
f++; // skip the digits
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (READMEMBYTE(stringInRom,f) == '#')
|
|
||||||
{ // alternate form
|
|
||||||
hash = 1;
|
|
||||||
f++;
|
|
||||||
}
|
|
||||||
if (READMEMBYTE(stringInRom,f) == 'l')
|
|
||||||
{ // long format
|
|
||||||
do_long = 1;
|
|
||||||
f++;
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt = READMEMBYTE(stringInRom,f);
|
|
||||||
bp = buf;
|
|
||||||
switch (fmt) { // do the formatting
|
|
||||||
case 'd': // 'd' signed decimal
|
|
||||||
if (do_long)
|
|
||||||
l = va_arg(ap, long);
|
|
||||||
else
|
|
||||||
l = (long) (va_arg(ap, int));
|
|
||||||
if (l < 0)
|
|
||||||
{
|
|
||||||
sign = 1;
|
|
||||||
l = -l;
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
*bp++ = l % 10 + '0';
|
|
||||||
} while ((l /= 10) > 0);
|
|
||||||
if (sign)
|
|
||||||
*bp++ = '-';
|
|
||||||
f_width = f_width - (bp - buf);
|
|
||||||
if (!flush_left)
|
|
||||||
while (f_width-- > 0)
|
|
||||||
rprintfChar(pad);
|
|
||||||
for (bp--; bp >= buf; bp--)
|
|
||||||
rprintfChar(*bp);
|
|
||||||
if (flush_left)
|
|
||||||
while (f_width-- > 0)
|
|
||||||
rprintfChar(' ');
|
|
||||||
break;
|
|
||||||
case 'o': // 'o' octal number
|
|
||||||
case 'x': // 'x' hex number
|
|
||||||
case 'u': // 'u' unsigned decimal
|
|
||||||
if (do_long)
|
|
||||||
u = va_arg(ap, unsigned long);
|
|
||||||
else
|
|
||||||
u = (unsigned long) (va_arg(ap, unsigned));
|
|
||||||
if (fmt == 'u')
|
|
||||||
{ // unsigned decimal
|
|
||||||
do {
|
|
||||||
*bp++ = u % 10 + '0';
|
|
||||||
} while ((u /= 10) > 0);
|
|
||||||
}
|
|
||||||
else if (fmt == 'o')
|
|
||||||
{ // octal
|
|
||||||
do {
|
|
||||||
*bp++ = u % 8 + '0';
|
|
||||||
} while ((u /= 8) > 0);
|
|
||||||
if (hash)
|
|
||||||
*bp++ = '0';
|
|
||||||
}
|
|
||||||
else if (fmt == 'x')
|
|
||||||
{ // hex
|
|
||||||
do {
|
|
||||||
i = u % 16;
|
|
||||||
if (i < 10)
|
|
||||||
*bp++ = i + '0';
|
|
||||||
else
|
|
||||||
*bp++ = i - 10 + 'a';
|
|
||||||
} while ((u /= 16) > 0);
|
|
||||||
if (hash)
|
|
||||||
{
|
|
||||||
*bp++ = 'x';
|
|
||||||
*bp++ = '0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i = f_width - (bp - buf);
|
|
||||||
if (!flush_left)
|
|
||||||
while (i-- > 0)
|
|
||||||
rprintfChar(pad);
|
|
||||||
for (bp--; bp >= buf; bp--)
|
|
||||||
rprintfChar((int) (*bp));
|
|
||||||
if (flush_left)
|
|
||||||
while (i-- > 0)
|
|
||||||
rprintfChar(' ');
|
|
||||||
break;
|
|
||||||
case 'c': // 'c' character
|
|
||||||
i = va_arg(ap, int);
|
|
||||||
rprintfChar((int) (i));
|
|
||||||
break;
|
|
||||||
case 's': // 's' string
|
|
||||||
bp = va_arg(ap, unsigned char *);
|
|
||||||
if (!bp)
|
|
||||||
bp = (unsigned char *) "(nil)";
|
|
||||||
f_width = f_width - strlen((char *) bp);
|
|
||||||
if (!flush_left)
|
|
||||||
while (f_width-- > 0)
|
|
||||||
rprintfChar(pad);
|
|
||||||
for (i = 0; *bp && i < prec; i++)
|
|
||||||
{
|
|
||||||
rprintfChar(*bp);
|
|
||||||
bp++;
|
|
||||||
}
|
|
||||||
if (flush_left)
|
|
||||||
while (f_width-- > 0)
|
|
||||||
rprintfChar(' ');
|
|
||||||
break;
|
|
||||||
case '%': // '%' character
|
|
||||||
rprintfChar('%');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
|
|
||||||
sign = 0;
|
|
||||||
pad = ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
va_end(ap);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char Isdigit(char c)
|
|
||||||
{
|
|
||||||
if((c >= 0x30) && (c <= 0x39))
|
|
||||||
return TRUE;
|
|
||||||
else
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int atoiRamRom(unsigned char stringInRom, char *str)
|
|
||||||
{
|
|
||||||
int num = 0;;
|
|
||||||
|
|
||||||
while(Isdigit(READMEMBYTE(stringInRom,str)))
|
|
||||||
{
|
|
||||||
num *= 10;
|
|
||||||
num += ((READMEMBYTE(stringInRom,str++)) - 0x30);
|
|
||||||
}
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//******************************************************************************
|
|
||||||
// code below this line is commented out and can be ignored
|
|
||||||
//******************************************************************************
|
|
||||||
/*
|
|
||||||
char* sprintf(const char *sfmt, ...)
|
|
||||||
{
|
|
||||||
register unsigned char *f, *bp, *str;
|
|
||||||
register long l;
|
|
||||||
register unsigned long u;
|
|
||||||
register int i;
|
|
||||||
register int fmt;
|
|
||||||
register unsigned char pad = ' ';
|
|
||||||
int flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
|
|
||||||
int sign = 0;
|
|
||||||
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, sfmt);
|
|
||||||
|
|
||||||
str = bufstring;
|
|
||||||
f = (unsigned char *) sfmt;
|
|
||||||
|
|
||||||
for (; *f; f++)
|
|
||||||
{
|
|
||||||
if (*f != '%')
|
|
||||||
{ // not a format character
|
|
||||||
*str++ = (*f); // then just output the char
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
f++; // if we have a "%" then skip it
|
|
||||||
if (*f == '-')
|
|
||||||
{
|
|
||||||
flush_left = 1; // minus: flush left
|
|
||||||
f++;
|
|
||||||
}
|
|
||||||
if (*f == '0' || *f == '.')
|
|
||||||
{
|
|
||||||
// padding with 0 rather than blank
|
|
||||||
pad = '0';
|
|
||||||
f++;
|
|
||||||
}
|
|
||||||
if (*f == '*')
|
|
||||||
{ // field width
|
|
||||||
f_width = va_arg(ap, int);
|
|
||||||
f++;
|
|
||||||
}
|
|
||||||
else if (Isdigit(*f))
|
|
||||||
{
|
|
||||||
f_width = atoi((char *) f);
|
|
||||||
while (Isdigit(*f))
|
|
||||||
f++; // skip the digits
|
|
||||||
}
|
|
||||||
if (*f == '.')
|
|
||||||
{ // precision
|
|
||||||
f++;
|
|
||||||
if (*f == '*')
|
|
||||||
{
|
|
||||||
prec = va_arg(ap, int);
|
|
||||||
f++;
|
|
||||||
}
|
|
||||||
else if (Isdigit(*f))
|
|
||||||
{
|
|
||||||
prec = atoi((char *) f);
|
|
||||||
while (Isdigit(*f))
|
|
||||||
f++; // skip the digits
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (*f == '#')
|
|
||||||
{ // alternate form
|
|
||||||
hash = 1;
|
|
||||||
f++;
|
|
||||||
}
|
|
||||||
if (*f == 'l')
|
|
||||||
{ // long format
|
|
||||||
do_long = 1;
|
|
||||||
f++;
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt = *f;
|
|
||||||
bp = buf;
|
|
||||||
switch (fmt) { // do the formatting
|
|
||||||
case 'd': // 'd' signed decimal
|
|
||||||
if (do_long)
|
|
||||||
l = va_arg(ap, long);
|
|
||||||
else
|
|
||||||
l = (long) (va_arg(ap, int));
|
|
||||||
if (l < 0)
|
|
||||||
{
|
|
||||||
sign = 1;
|
|
||||||
l = -l;
|
|
||||||
}
|
|
||||||
do {
|
|
||||||
*bp++ = l % 10 + '0';
|
|
||||||
} while ((l /= 10) > 0);
|
|
||||||
if (sign)
|
|
||||||
*bp++ = '-';
|
|
||||||
f_width = f_width - (bp - buf);
|
|
||||||
if (!flush_left)
|
|
||||||
while (f_width-- > 0)
|
|
||||||
*str++ = (pad);
|
|
||||||
for (bp--; bp >= buf; bp--)
|
|
||||||
*str++ = (*bp);
|
|
||||||
if (flush_left)
|
|
||||||
while (f_width-- > 0)
|
|
||||||
*str++ = (' ');
|
|
||||||
break;
|
|
||||||
case 'o': // 'o' octal number
|
|
||||||
case 'x': // 'x' hex number
|
|
||||||
case 'u': // 'u' unsigned decimal
|
|
||||||
if (do_long)
|
|
||||||
u = va_arg(ap, unsigned long);
|
|
||||||
else
|
|
||||||
u = (unsigned long) (va_arg(ap, unsigned));
|
|
||||||
if (fmt == 'u')
|
|
||||||
{ // unsigned decimal
|
|
||||||
do {
|
|
||||||
*bp++ = u % 10 + '0';
|
|
||||||
} while ((u /= 10) > 0);
|
|
||||||
}
|
|
||||||
else if (fmt == 'o')
|
|
||||||
{ // octal
|
|
||||||
do {
|
|
||||||
*bp++ = u % 8 + '0';
|
|
||||||
} while ((u /= 8) > 0);
|
|
||||||
if (hash)
|
|
||||||
*bp++ = '0';
|
|
||||||
}
|
|
||||||
else if (fmt == 'x')
|
|
||||||
{ // hex
|
|
||||||
do {
|
|
||||||
i = u % 16;
|
|
||||||
if (i < 10)
|
|
||||||
*bp++ = i + '0';
|
|
||||||
else
|
|
||||||
*bp++ = i - 10 + 'a';
|
|
||||||
} while ((u /= 16) > 0);
|
|
||||||
if (hash)
|
|
||||||
{
|
|
||||||
*bp++ = 'x';
|
|
||||||
*bp++ = '0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i = f_width - (bp - buf);
|
|
||||||
if (!flush_left)
|
|
||||||
while (i-- > 0)
|
|
||||||
*str++ = (pad);
|
|
||||||
for (bp--; bp >= buf; bp--)
|
|
||||||
*str++ = ((int) (*bp));
|
|
||||||
if (flush_left)
|
|
||||||
while (i-- > 0)
|
|
||||||
*str++ = (' ');
|
|
||||||
break;
|
|
||||||
case 'c': // 'c' character
|
|
||||||
i = va_arg(ap, int);
|
|
||||||
*str++ = ((int) (i));
|
|
||||||
break;
|
|
||||||
case 's': // 's' string
|
|
||||||
bp = va_arg(ap, unsigned char *);
|
|
||||||
if (!bp)
|
|
||||||
bp = (unsigned char *) "(nil)";
|
|
||||||
f_width = f_width - strlen((char *) bp);
|
|
||||||
if (!flush_left)
|
|
||||||
while (f_width-- > 0)
|
|
||||||
*str++ = (pad);
|
|
||||||
for (i = 0; *bp && i < prec; i++)
|
|
||||||
{
|
|
||||||
*str++ = (*bp);
|
|
||||||
bp++;
|
|
||||||
}
|
|
||||||
if (flush_left)
|
|
||||||
while (f_width-- > 0)
|
|
||||||
*str++ = (' ');
|
|
||||||
break;
|
|
||||||
case '%': // '%' character
|
|
||||||
*str++ = ('%');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
|
|
||||||
sign = 0;
|
|
||||||
pad = ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
va_end(ap);
|
|
||||||
// terminate string with null
|
|
||||||
*str++ = '\0';
|
|
||||||
return bufstring;
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
@ -1,135 +0,0 @@
|
|||||||
/*! \file rprintf.h \brief printf routine and associated routines. */
|
|
||||||
//****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'rprintf.h'
|
|
||||||
// Title : printf routine and associated routines
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2000-2002
|
|
||||||
// Created : 2000.12.26
|
|
||||||
// Revised : 2003.5.1
|
|
||||||
// Version : 1.0
|
|
||||||
// Target MCU : Atmel AVR series and other targets
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// NOTE: This code is currently below version 1.0, and therefore is considered
|
|
||||||
// to be lacking in some functionality or documentation, or may not be fully
|
|
||||||
// tested. Nonetheless, you can expect most functions to work.
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//****************************************************************************
|
|
||||||
|
|
||||||
#ifndef RPRINTF_H
|
|
||||||
#define RPRINTF_H
|
|
||||||
|
|
||||||
// needed for use of PSTR below
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
|
|
||||||
// configuration
|
|
||||||
// defining RPRINTF_SIMPLE will compile a smaller, simpler, and faster printf() function
|
|
||||||
// defining RPRINTF_COMPLEX will compile a larger, more capable, and slower printf() function
|
|
||||||
#ifndef RPRINTF_COMPLEX
|
|
||||||
#define RPRINTF_SIMPLE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Define RPRINTF_FLOAT to enable the floating-point printf function: rprintfFloat()
|
|
||||||
// (adds +4600bytes or 2.2Kwords of code)
|
|
||||||
|
|
||||||
// defines/constants
|
|
||||||
#define STRING_IN_RAM 0
|
|
||||||
#define STRING_IN_ROM 1
|
|
||||||
|
|
||||||
// make a putchar for those that are used to using it
|
|
||||||
//#define putchar(c) rprintfChar(c);
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
//! initializes the rprintf library for an output stream
|
|
||||||
// you must call this initializer once before using any other rprintf function
|
|
||||||
// the argument must be a single-character stream output function
|
|
||||||
void rprintfInit(void (*putchar_func)(unsigned char c));
|
|
||||||
|
|
||||||
//! prints a single character to the current output device
|
|
||||||
void rprintfChar(unsigned char c);
|
|
||||||
|
|
||||||
//! prints a null-terminated string stored in RAM
|
|
||||||
void rprintfStr(char str[]);
|
|
||||||
|
|
||||||
//! prints a section of a string stored in RAM
|
|
||||||
// begins printing at position indicated by <start>
|
|
||||||
// prints number of characters indicated by <len>
|
|
||||||
void rprintfStrLen(char str[], unsigned int start, unsigned int len);
|
|
||||||
|
|
||||||
//! prints a string stored in program rom
|
|
||||||
// NOTE: this function does not actually store your string in
|
|
||||||
// program rom, but merely reads it assuming you stored it properly.
|
|
||||||
void rprintfProgStr(const prog_char str[]);
|
|
||||||
// Using the function rprintfProgStrM(...) automatically causes
|
|
||||||
// your string to be stored in ROM, thereby not wasting precious RAM
|
|
||||||
// Example usage:
|
|
||||||
// rprintfProgStrM("Hello, this string is stored in program rom");
|
|
||||||
#define rprintfProgStrM(string) (rprintfProgStr(PSTR(string)))
|
|
||||||
|
|
||||||
//! prints a carriage return and line feed
|
|
||||||
// useful when printing to serial ports/terminals
|
|
||||||
void rprintfCRLF(void);
|
|
||||||
|
|
||||||
// prints the number contained in "data" in hex format
|
|
||||||
// u04,u08,u16,and u32 functions handle 4,8,16,or 32 bits respectively
|
|
||||||
void rprintfu04(unsigned char data); ///< print 4-bit hex number
|
|
||||||
void rprintfu08(unsigned char data); ///< print 8-bit hex number
|
|
||||||
void rprintfu16(unsigned short data); ///< print 16-bit hex number
|
|
||||||
void rprintfu32(unsigned long data); ///< print 32-bit hex number
|
|
||||||
|
|
||||||
//! a flexible integer number printing routine
|
|
||||||
void rprintfNum(char base, char numDigits, char isSigned, char padchar, long n);
|
|
||||||
|
|
||||||
#ifdef RPRINTF_FLOAT
|
|
||||||
//! floating-point print routine
|
|
||||||
void rprintfFloat(char numDigits, double x);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// NOTE: Below you'll see the function prototypes of rprintf1RamRom and
|
|
||||||
// rprintf2RamRom. rprintf1RamRom and rprintf2RamRom are both reduced versions
|
|
||||||
// of the regular C printf() command. However, they are modified to be able
|
|
||||||
// to read their text/format strings from RAM or ROM in the Atmel microprocessors.
|
|
||||||
// Unless you really intend to, do not use the "RamRom" versions of the functions
|
|
||||||
// directly. Instead use the #defined function versions:
|
|
||||||
//
|
|
||||||
// printfx("text/format",args) ...to keep your text/format string stored in RAM
|
|
||||||
// - or -
|
|
||||||
// printfxROM("text/format",args) ...to keep your text/format string stored in ROM
|
|
||||||
//
|
|
||||||
// where x is either 1 or 2 for the simple or more powerful version of printf()
|
|
||||||
//
|
|
||||||
// Since there is much more ROM than RAM available in the Atmel microprocessors,
|
|
||||||
// and nearly all text/format strings are constant (never change in the course
|
|
||||||
// of the program), you should try to use the ROM printf version exclusively.
|
|
||||||
// This will ensure you leave as much RAM as possible for program variables and
|
|
||||||
// data.
|
|
||||||
|
|
||||||
#ifdef RPRINTF_SIMPLE
|
|
||||||
// a simple printf routine
|
|
||||||
int rprintf1RamRom(unsigned char stringInRom, const char *format, ...);
|
|
||||||
// #defines for RAM or ROM operation
|
|
||||||
#define rprintf1(format, args...) rprintf1RamRom(STRING_IN_ROM, PSTR(format), ## args)
|
|
||||||
#define rprintf1RAM(format, args...) rprintf1RamRom(STRING_IN_RAM, format, ## args)
|
|
||||||
|
|
||||||
// *** Default rprintf(...) ***
|
|
||||||
// this next line determines what the the basic rprintf() defaults to:
|
|
||||||
#define rprintf(format, args...) rprintf1RamRom(STRING_IN_ROM, PSTR(format), ## args)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef RPRINTF_COMPLEX
|
|
||||||
// a more powerful printf routine
|
|
||||||
int rprintf2RamRom(unsigned char stringInRom, const char *sfmt, ...);
|
|
||||||
// #defines for RAM or ROM operation
|
|
||||||
#define rprintf2(format, args...) rprintf2RamRom(STRING_IN_ROM, format, ## args)
|
|
||||||
#define rprintf2RAM(format, args...) rprintf2RamRom(STRING_IN_RAM, format, ## args)
|
|
||||||
|
|
||||||
// *** Default rprintf(...) ***
|
|
||||||
// this next line determines what the the basic rprintf() defaults to:
|
|
||||||
#define rprintf(format, args...) rprintf2RamRom(STRING_IN_ROM, PSTR(format), ## args)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,102 +0,0 @@
|
|||||||
/*! \file avrcore.c \brief AVR-Core Board Driver Functions. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'avrcore.c'
|
|
||||||
// Title : AVR-Core Board Driver Functions
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2004
|
|
||||||
// Created : 2004.10.1
|
|
||||||
// Revised : 2004.10.1
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
//----- Include Files ---------------------------------------------------------
|
|
||||||
#include <avr/io.h> // include I/O definitions (port names, pin names, etc)
|
|
||||||
#include <avr/signal.h> // include "signal" names (interrupt names)
|
|
||||||
#include <avr/interrupt.h> // include interrupt support
|
|
||||||
|
|
||||||
#include "global.h" // include our global settings
|
|
||||||
#include "avrcore.h"
|
|
||||||
|
|
||||||
// globals
|
|
||||||
u08 AvrcoreLatch;
|
|
||||||
|
|
||||||
// functions
|
|
||||||
void avrcoreInit(void)
|
|
||||||
{
|
|
||||||
// initialize ports to input with pullup
|
|
||||||
// (this is done to avoid contentions and input-pin oscillation)
|
|
||||||
outb(DDRA, 0x00);
|
|
||||||
outb(DDRB, 0x00);
|
|
||||||
outb(DDRC, 0x00);
|
|
||||||
outb(DDRD, 0x00);
|
|
||||||
outb(DDRE, 0x00);
|
|
||||||
outb(DDRF, 0x00);
|
|
||||||
outb(PORTA, 0xFF);
|
|
||||||
outb(PORTB, 0xFF);
|
|
||||||
outb(PORTC, 0xFF);
|
|
||||||
outb(PORTD, 0xFF);
|
|
||||||
outb(PORTE, 0xFF);
|
|
||||||
outb(PORTF, 0xFF);
|
|
||||||
// turn on RAM interface
|
|
||||||
sbi(MCUCR, SRE);
|
|
||||||
// initialize RAM page
|
|
||||||
avrcoreSetRamPage(0);
|
|
||||||
// initialize LEDs
|
|
||||||
avrcoreSetLeds(0);
|
|
||||||
// set serial power to on by default
|
|
||||||
avrcoreSetSerialPortPower(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void avrcoreSetRamPage(u08 page)
|
|
||||||
{
|
|
||||||
// update latch state
|
|
||||||
AvrcoreLatch &= ~AVRCORELATCH_ADDRMASK;
|
|
||||||
AvrcoreLatch |= page & AVRCORELATCH_ADDRMASK;
|
|
||||||
// write new latch state to latch
|
|
||||||
AVRCORELATCH = AvrcoreLatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
void avrcoreSetLeds(u08 leds)
|
|
||||||
{
|
|
||||||
// NOTE: LEDs are negative-logic (active-low)
|
|
||||||
// update latch state
|
|
||||||
AvrcoreLatch |= AVRCORELATCH_LEDMASK;
|
|
||||||
AvrcoreLatch &= ~(leds<<4);
|
|
||||||
// write new latch state to latch
|
|
||||||
AVRCORELATCH = AvrcoreLatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
void avrcoreSetLedsOn(u08 leds)
|
|
||||||
{
|
|
||||||
// NOTE: LEDs are negative-logic (active-low)
|
|
||||||
// update latch state to turn on inidicated leds
|
|
||||||
AvrcoreLatch &= ~(leds<<4);
|
|
||||||
// write new latch state to latch
|
|
||||||
AVRCORELATCH = AvrcoreLatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
void avrcoreSetLedsOff(u08 leds)
|
|
||||||
{
|
|
||||||
// NOTE: LEDs are negative-logic (active-low)
|
|
||||||
// update latch state to turn off inidicated leds
|
|
||||||
AvrcoreLatch |= (leds<<4);
|
|
||||||
// write new latch state to latch
|
|
||||||
AVRCORELATCH = AvrcoreLatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
void avrcoreSetSerialPortPower(u08 on)
|
|
||||||
{
|
|
||||||
// this function simply manipulates LED3/power control
|
|
||||||
if(on)
|
|
||||||
AvrcoreLatch &= ~(0x80);
|
|
||||||
else
|
|
||||||
AvrcoreLatch |= (0x80);
|
|
||||||
// write new latch state to latch
|
|
||||||
AVRCORELATCH = AvrcoreLatch;
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
/*! \file avrcore.h \brief AVR-Core Board Driver Functions. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'avrcore.h'
|
|
||||||
// Title : AVR-Core Board Driver Functions
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2004
|
|
||||||
// Created : 2004.10.1
|
|
||||||
// Revised : 2004.10.1
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
#ifndef AVRCORE_H
|
|
||||||
#define AVRCORE_H
|
|
||||||
|
|
||||||
// defines and typedefs
|
|
||||||
#define AVRCORELATCH (*((unsigned char*)0x4000))
|
|
||||||
#define AVRCORELATCH_ADDRMASK 0x0F
|
|
||||||
#define AVRCORELATCH_LEDMASK 0xF0
|
|
||||||
|
|
||||||
// functions
|
|
||||||
|
|
||||||
//! Initialize AVRCore hardware
|
|
||||||
void avrcoreInit(void);
|
|
||||||
|
|
||||||
//! Set the current external RAM page
|
|
||||||
// The AVRCore on-board external RAM is typically 512KBytes.
|
|
||||||
// The RAM is memory-mapped into the 32KByte address space from
|
|
||||||
// 0x8000-0xFFFF, and must therefore be accessed in pages (32KB chunks).
|
|
||||||
// Use this function to select which of the 16 (0-15) 32KByte pages
|
|
||||||
// you wish to access.
|
|
||||||
void avrcoreSetRamPage(u08 page);
|
|
||||||
|
|
||||||
//! Set the state of the four LEDs on AVRCore
|
|
||||||
// leds bit0 => LED1 (0=off, 1=on)
|
|
||||||
// leds bit1 => LED2 (0=off, 1=on)
|
|
||||||
// leds bit2 => LED3 (0=off, 1=on)
|
|
||||||
// leds bit3 => LED4 (0=off, 1=on)
|
|
||||||
void avrcoreSetLeds(u08 leds);
|
|
||||||
|
|
||||||
//! Turn on selected LEDs
|
|
||||||
// '0' bit = no change
|
|
||||||
// '1' bit = turn on
|
|
||||||
void avrcoreSetLedsOn(u08 leds);
|
|
||||||
|
|
||||||
//! Turn off selected LEDs
|
|
||||||
// '0' bit = no change
|
|
||||||
// '1' bit = turn off
|
|
||||||
void avrcoreSetLedsOff(u08 leds);
|
|
||||||
|
|
||||||
//! Set on/off power setting of AVRCore serial port
|
|
||||||
// (0=off, 1=on)
|
|
||||||
void avrcoreSetSerialPortPower(u08 on);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,495 +0,0 @@
|
|||||||
/*! \file edp.c \brief Emerald Data Protocol System. */
|
|
||||||
//*****************************************************************************
|
|
||||||
//
|
|
||||||
// File Name : 'edp.c'
|
|
||||||
// Title : Emerald Data Protocol System
|
|
||||||
// Author : Pascal Stang - Copyright (C) 2003
|
|
||||||
// Created : 2003.07.01
|
|
||||||
// Revised : 2003.07.21
|
|
||||||
// Version : 0.1
|
|
||||||
// Target MCU : Atmel AVR series
|
|
||||||
// Editor Tabs : 4
|
|
||||||
//
|
|
||||||
// This code is distributed under the GNU Public License
|
|
||||||
// which can be found at http://www.gnu.org/licenses/gpl.txt
|
|
||||||
//
|
|
||||||
//*****************************************************************************
|
|
||||||
|
|
||||||
//----- Include Files ---------------------------------------------------------
|
|
||||||
#include <avr/io.h> // include I/O definitions (port names, pin names, etc)
|
|
||||||
#include <avr/signal.h> // include "signal" names (interrupt names)
|
|
||||||
#include <avr/interrupt.h> // include interrupt support
|
|
||||||
#include <avr/pgmspace.h> // include program-space support
|
|
||||||
|
|
||||||
#include "global.h" // include our global settings
|
|
||||||
#include "i2c.h" // include I2C support
|
|
||||||
#include "rprintf.h" // include printf function library
|
|
||||||
|
|
||||||
#include "edp.h"
|
|
||||||
|
|
||||||
// globals
|
|
||||||
// EDP master/command: response code and reply buffer
|
|
||||||
u08 EdpCommandResponseCode;
|
|
||||||
//u08 EdpCommandReplyLength;
|
|
||||||
u08 EdpCommandReplyBuffer[EDP_REPLY_BUFFER_SIZE];
|
|
||||||
u08 EdpCommandReplyChecksum;
|
|
||||||
// EDP slave: response code and reply buffer
|
|
||||||
u08 EdpSlaveResponseCode;
|
|
||||||
u08 EdpSlaveReplyLength;
|
|
||||||
u08 EdpSlaveReplyBuffer[EDP_REPLY_BUFFER_SIZE];
|
|
||||||
// EDP slave request handler function pointer
|
|
||||||
EdpSlaveHandlerFuncType edpSlaveHandlerFunc;
|
|
||||||
|
|
||||||
// functions
|
|
||||||
void edpInit(void)
|
|
||||||
{
|
|
||||||
// initialize i2c interface and function library
|
|
||||||
i2cInit();
|
|
||||||
// set i2c bit rate to 30KHz
|
|
||||||
i2cSetBitrate(30);
|
|
||||||
// set the Slave Receive Handler function
|
|
||||||
// (this function will run whenever a master somewhere else on the bus
|
|
||||||
// writes data to us as a slave)
|
|
||||||
i2cSetSlaveReceiveHandler( edpSlaveReceiveService );
|
|
||||||
// set the Slave Transmit Handler function
|
|
||||||
// (this function will run whenever a master somewhere else on the bus
|
|
||||||
// attempts to read data from us as a slave)
|
|
||||||
i2cSetSlaveTransmitHandler( edpSlaveTransmitService );
|
|
||||||
}
|
|
||||||
|
|
||||||
void edpSetSlaveHandler(EdpSlaveHandlerFuncType edpSlaveHandlerFunction)
|
|
||||||
{
|
|
||||||
edpSlaveHandlerFunc = edpSlaveHandlerFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ************ EDP Master operations ************
|
|
||||||
u08 edpSendCommand(u08 deviceAddr, u08 cmdLength, EdpCommand* edpCommand)
|
|
||||||
{
|
|
||||||
EdpReply* edpCommandReply = (EdpReply*)EdpCommandReplyBuffer;
|
|
||||||
u08* sendData;
|
|
||||||
u08* replyData;
|
|
||||||
u08 replyLength;
|
|
||||||
u08 checksum;
|
|
||||||
|
|
||||||
// initialize response variables
|
|
||||||
edpCommandReply->Length = 0;
|
|
||||||
EdpCommandReplyChecksum = 0;
|
|
||||||
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("\r\nBegin EdpSendCommand, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// disable TWI interrupt
|
|
||||||
cbi(TWCR, TWIE);
|
|
||||||
|
|
||||||
// clear TWI interface
|
|
||||||
//outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK));
|
|
||||||
|
|
||||||
// send start condition
|
|
||||||
i2cSendStart();
|
|
||||||
i2cWaitForComplete();
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("Sent Start, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// send device address with write
|
|
||||||
i2cSendByte( (deviceAddr&0xFE) );
|
|
||||||
i2cWaitForComplete();
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("Sent Device Address+Write, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// check if device is present and live
|
|
||||||
if( i2cGetStatus() != TW_MT_SLA_ACK)
|
|
||||||
{
|
|
||||||
// device did not ACK it's address, command will not continue
|
|
||||||
// transmit stop condition
|
|
||||||
// leave with TWEA on for slave receiving
|
|
||||||
i2cSendStop();
|
|
||||||
while( !(inb(TWCR) & BV(TWSTO)) );
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("No Device!, Sent Stop, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
// enable TWI interrupt
|
|
||||||
sbi(TWCR, TWIE);
|
|
||||||
// return error
|
|
||||||
return EDP_COMMAND_NODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
// send data
|
|
||||||
sendData = (u08*)edpCommand;
|
|
||||||
checksum = 0;
|
|
||||||
while(cmdLength)
|
|
||||||
{
|
|
||||||
i2cSendByte( *sendData );
|
|
||||||
i2cWaitForComplete();
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("Sent Data, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
checksum += *sendData++;
|
|
||||||
cmdLength--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// send the checksum
|
|
||||||
i2cSendByte( ~checksum );
|
|
||||||
i2cWaitForComplete();
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("Sent Checksum, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// send repeated start condition
|
|
||||||
i2cSendStart();
|
|
||||||
i2cWaitForComplete();
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("Sent Repeated Start, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// send device address with read
|
|
||||||
i2cSendByte( deviceAddr|0x01 );
|
|
||||||
i2cWaitForComplete();
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("Sent Device Address+Read, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// read response code, return NACK
|
|
||||||
i2cReceiveByte(FALSE);
|
|
||||||
i2cWaitForComplete();
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("Read Data, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
EdpCommandResponseCode = i2cGetReceivedByte();
|
|
||||||
|
|
||||||
if(EdpCommandResponseCode==EDP_RESP_DATA_REPLY)
|
|
||||||
{
|
|
||||||
// a data reply is being sent
|
|
||||||
|
|
||||||
// send repeated start condition
|
|
||||||
i2cSendStart();
|
|
||||||
i2cWaitForComplete();
|
|
||||||
|
|
||||||
// send device address with read
|
|
||||||
i2cSendByte( deviceAddr|0x01 );
|
|
||||||
i2cWaitForComplete();
|
|
||||||
|
|
||||||
// get length, return ACK
|
|
||||||
i2cReceiveByte(TRUE);
|
|
||||||
i2cWaitForComplete();
|
|
||||||
edpCommandReply->Length = i2cGetReceivedByte();
|
|
||||||
// set temp variables
|
|
||||||
replyLength = edpCommandReply->Length;
|
|
||||||
replyData = edpCommandReply->Data;
|
|
||||||
|
|
||||||
// get data, return ACKs
|
|
||||||
// preset checksum with the datalength byte
|
|
||||||
checksum = replyLength;
|
|
||||||
while(replyLength > 1)
|
|
||||||
{
|
|
||||||
i2cReceiveByte(TRUE); // receive data byte and return ACK
|
|
||||||
i2cWaitForComplete();
|
|
||||||
*replyData = i2cGetReceivedByte();
|
|
||||||
checksum += *replyData++;
|
|
||||||
replyLength--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get last data (actually the checksum), return NACK (last-byte signal)
|
|
||||||
i2cReceiveByte(FALSE);
|
|
||||||
i2cWaitForComplete();
|
|
||||||
*replyData = i2cGetReceivedByte();
|
|
||||||
// add received checksum+1 to our checksum, the result should be zero
|
|
||||||
checksum += (*replyData) + 1;
|
|
||||||
// save the reply checksum
|
|
||||||
EdpCommandReplyChecksum = checksum;
|
|
||||||
}
|
|
||||||
|
|
||||||
// transmit stop condition
|
|
||||||
// leave with TWEA on for slave receiving
|
|
||||||
i2cSendStop();
|
|
||||||
while( !(inb(TWCR) & BV(TWSTO)) );
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("Sent Stop, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// enable TWI interrupt
|
|
||||||
sbi(TWCR, TWIE);
|
|
||||||
|
|
||||||
return EDP_COMMAND_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the response code and reply from last command
|
|
||||||
u08 edpGetCommandReply(u08* responseCode, EdpReply** edpReply)
|
|
||||||
{
|
|
||||||
u08 retval=EDP_REPLY_OK;
|
|
||||||
|
|
||||||
// get the response code from last command
|
|
||||||
*responseCode = EdpCommandResponseCode;
|
|
||||||
// get the reply from last command
|
|
||||||
*edpReply = (EdpReply*)EdpCommandReplyBuffer;
|
|
||||||
|
|
||||||
// check response code
|
|
||||||
if(EdpCommandResponseCode == EDP_RESP_DATA_REPLY)
|
|
||||||
{
|
|
||||||
// there was a reply, check the checksum
|
|
||||||
// if it's non-zero, data corruption is present
|
|
||||||
if(EdpCommandReplyChecksum)
|
|
||||||
retval = EDP_REPLY_BADCHKSUM;
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
u08 edpSendCommand(u08 deviceAddr, u08 sendLength, u08* sendData)
|
|
||||||
{
|
|
||||||
u08* replyData = EdpCommandReplyBuffer;
|
|
||||||
u08 replyLength;
|
|
||||||
u08 checksum;
|
|
||||||
|
|
||||||
// initialize response variables
|
|
||||||
EdpCommandReplyLength = 0;
|
|
||||||
EdpCommandReplyChecksum = 0;
|
|
||||||
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("\r\nBegin EdpSendCommand, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// disable TWI interrupt
|
|
||||||
cbi(TWCR, TWIE);
|
|
||||||
|
|
||||||
// clear TWI interface
|
|
||||||
//outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK));
|
|
||||||
|
|
||||||
// send start condition
|
|
||||||
i2cSendStart();
|
|
||||||
i2cWaitForComplete();
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("Sent Start, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// send device address with write
|
|
||||||
i2cSendByte( (deviceAddr&0xFE) );
|
|
||||||
i2cWaitForComplete();
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("Sent Device Address+Write, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// check if device is present and live
|
|
||||||
if( i2cGetStatus() != TW_MT_SLA_ACK)
|
|
||||||
{
|
|
||||||
// device did not ACK it's address, command will not continue
|
|
||||||
// transmit stop condition
|
|
||||||
// leave with TWEA on for slave receiving
|
|
||||||
i2cSendStop();
|
|
||||||
while( !(inb(TWCR) & BV(TWSTO)) );
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("No Device!, Sent Stop, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
// enable TWI interrupt
|
|
||||||
sbi(TWCR, TWIE);
|
|
||||||
// return error
|
|
||||||
return EDP_COMMAND_NODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
// send data
|
|
||||||
checksum = 0;
|
|
||||||
while(sendLength)
|
|
||||||
{
|
|
||||||
i2cSendByte( *sendData );
|
|
||||||
i2cWaitForComplete();
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("Sent Data, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
checksum += *sendData++;
|
|
||||||
sendLength--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// send the checksum
|
|
||||||
i2cSendByte( ~checksum );
|
|
||||||
i2cWaitForComplete();
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("Sent Checksum, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// send repeated start condition
|
|
||||||
i2cSendStart();
|
|
||||||
i2cWaitForComplete();
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("Sent Repeated Start, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// send device address with read
|
|
||||||
i2cSendByte( deviceAddr|0x01 );
|
|
||||||
i2cWaitForComplete();
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("Sent Device Address+Read, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// read response code, return NACK
|
|
||||||
i2cReceiveByte(FALSE);
|
|
||||||
i2cWaitForComplete();
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("Read Data, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
EdpCommandResponseCode = i2cGetReceivedByte();
|
|
||||||
|
|
||||||
if(EdpCommandResponseCode==EDP_RESP_DATA_REPLY)
|
|
||||||
{
|
|
||||||
// a data reply is being sent
|
|
||||||
|
|
||||||
// send repeated start condition
|
|
||||||
i2cSendStart();
|
|
||||||
i2cWaitForComplete();
|
|
||||||
|
|
||||||
// send device address with read
|
|
||||||
i2cSendByte( deviceAddr|0x01 );
|
|
||||||
i2cWaitForComplete();
|
|
||||||
|
|
||||||
// get length, return ACK
|
|
||||||
i2cReceiveByte(TRUE);
|
|
||||||
i2cWaitForComplete();
|
|
||||||
replyLength = i2cGetReceivedByte();
|
|
||||||
EdpCommandReplyLength = replyLength;
|
|
||||||
|
|
||||||
// get data, return ACKs
|
|
||||||
// preset checksum with the datalength byte
|
|
||||||
checksum = replyLength;
|
|
||||||
while(replyLength > 1)
|
|
||||||
{
|
|
||||||
i2cReceiveByte(TRUE); // receive data byte and return ACK
|
|
||||||
i2cWaitForComplete();
|
|
||||||
*replyData = i2cGetReceivedByte();
|
|
||||||
checksum += *replyData++;
|
|
||||||
replyLength--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get last data (actually the checksum), return NACK (last-byte signal)
|
|
||||||
i2cReceiveByte(FALSE);
|
|
||||||
i2cWaitForComplete();
|
|
||||||
*replyData = i2cGetReceivedByte();
|
|
||||||
// add received checksum+1 to our checksum, the result should be zero
|
|
||||||
checksum += (*replyData) + 1;
|
|
||||||
// save the reply checksum
|
|
||||||
EdpCommandReplyChecksum = checksum;
|
|
||||||
}
|
|
||||||
|
|
||||||
// transmit stop condition
|
|
||||||
// leave with TWEA on for slave receiving
|
|
||||||
i2cSendStop();
|
|
||||||
while( !(inb(TWCR) & BV(TWSTO)) );
|
|
||||||
#ifdef EDP_DEBUG
|
|
||||||
rprintf("Sent Stop, TWSR:0x%x\r\n",inb(TWSR));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// enable TWI interrupt
|
|
||||||
sbi(TWCR, TWIE);
|
|
||||||
|
|
||||||
return EDP_COMMAND_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
u08 edpGetCommandReply(u08* responseCode, u08* replyLength, u08** replyData)
|
|
||||||
{
|
|
||||||
u08 retval=EDP_REPLY_OK;
|
|
||||||
|
|
||||||
// get the response code and reply data from last command
|
|
||||||
*responseCode = EdpCommandResponseCode;
|
|
||||||
// get the reply length from last command
|
|
||||||
*replyLength = EdpCommandReplyLength;
|
|
||||||
// get the reply data from last command
|
|
||||||
*replyData = EdpCommandReplyBuffer;
|
|
||||||
|
|
||||||
// check response code
|
|
||||||
if(EdpCommandResponseCode == EDP_RESP_DATA_REPLY)
|
|
||||||
{
|
|
||||||
// there was a reply, check the checksum
|
|
||||||
// if it's non-zero, data corruption is present
|
|
||||||
if(EdpCommandReplyChecksum)
|
|
||||||
retval = EDP_REPLY_BADCHKSUM;
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// ************ EDP Slave operations ************
|
|
||||||
|
|
||||||
// this function will run when a master somewhere else on the bus
|
|
||||||
// addresses us and wishes to write data to us
|
|
||||||
void edpSlaveReceiveService(u08 receiveDataLength, u08* receiveData)
|
|
||||||
{
|
|
||||||
u08 i,checksum;
|
|
||||||
|
|
||||||
// initialize the reply length from this command
|
|
||||||
EdpSlaveReplyLength = 0;
|
|
||||||
// verify the checksum
|
|
||||||
// initialize the checksum with 1
|
|
||||||
checksum = 0x01;
|
|
||||||
// sum all the data in the packet and the data's checksum
|
|
||||||
for(i=0; i<receiveDataLength; i++)
|
|
||||||
{
|
|
||||||
checksum += receiveData[i];
|
|
||||||
}
|
|
||||||
// if the checksum is non-zero, then the data is corrupt
|
|
||||||
if(checksum)
|
|
||||||
{
|
|
||||||
// set reply code
|
|
||||||
// [FIX] which should it be?
|
|
||||||
EdpSlaveResponseCode = EDP_RESP_DATA_CHK_ERROR;
|
|
||||||
//EdpSlaveResponseCode = EDP_RESP_CMD_CHK_ERROR;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make an EDP command pointer to the received I2C data
|
|
||||||
EdpCommand* edpCommand = (EdpCommand*)receiveData;
|
|
||||||
|
|
||||||
// if a slave handler is defined
|
|
||||||
if(edpSlaveHandlerFunc)
|
|
||||||
{
|
|
||||||
// then use it
|
|
||||||
EdpSlaveResponseCode = edpSlaveHandlerFunc(
|
|
||||||
receiveDataLength, edpCommand,
|
|
||||||
EDP_REPLY_BUFFER_SIZE, (EdpReply*)EdpSlaveReplyBuffer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// otherwise reply with unknown command
|
|
||||||
EdpSlaveResponseCode = EDP_RESP_UNKWN_CMD;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// this function will run when a master somewhere else on the bus
|
|
||||||
// addresses us and wishes to read data from us
|
|
||||||
u08 edpSlaveTransmitService(u08 transmitDataLengthMax, u08* transmitData)
|
|
||||||
{
|
|
||||||
u08 i;
|
|
||||||
u08 checksum;
|
|
||||||
u08 transmitDataLength = 0;
|
|
||||||
|
|
||||||
EdpReply* edpReply = (EdpReply*)EdpSlaveReplyBuffer;
|
|
||||||
|
|
||||||
if(EdpSlaveResponseCode)
|
|
||||||
{
|
|
||||||
// reply code is non-zero, we must send it
|
|
||||||
*transmitData = EdpSlaveResponseCode;
|
|
||||||
transmitDataLength = 1;
|
|
||||||
// reset the reply code to flag that we've sent it
|
|
||||||
EdpSlaveResponseCode = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// reply code already sent, now send data (if any)
|
|
||||||
// copy length of reply to transmit buffer (+1 for checksum)
|
|
||||||
*transmitData++ = edpReply->Length+1;
|
|
||||||
// initialize checksum
|
|
||||||
checksum = edpReply->Length+1;
|
|
||||||
// copy reply buffer to the transmit buffer
|
|
||||||
for(i=0; i<edpReply->Length; i++)
|
|
||||||
{
|
|
||||||
*transmitData++ = edpReply->Data[i];
|
|
||||||
checksum += edpReply->Data[i];
|
|
||||||
}
|
|
||||||
// copy checksum to transmit buffer
|
|
||||||
*transmitData++ = ~checksum;
|
|
||||||
// set number of bytes to transmit
|
|
||||||
transmitDataLength = edpReply->Length+2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return number of bytes written to transmit buffer
|
|
||||||
return transmitDataLength;
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user