mirror of
https://github.com/arduino/Arduino.git
synced 2025-02-20 14:54:31 +01: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:
parent
daf909cc1a
commit
18951f0437
@ -168,7 +168,6 @@
|
||||
/* End PBXApplicationTarget 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 */; };
|
||||
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 */; };
|
||||
@ -411,16 +410,13 @@
|
||||
339514FA097AEB8000193C89 /* license.txt in CopyFiles */,
|
||||
339514FB097AEB8000193C89 /* readme.txt in CopyFiles */,
|
||||
33FF07050965BEE60016AC38 /* macosx_setup.command in CopyFiles */,
|
||||
330B21540968180400345666 /* librxtxSerial.jnilib in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase 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>"; };
|
||||
333269E1099BB1FC007D3AE2 /* tools.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = tools.zip; 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>"; };
|
||||
338C47870AA204B0008F2C0D /* FTDIUSBSerialDriver_v2_1_6.dmg */ = {isa = PBXFileReference; lastKnownFileType = file; path = FTDIUSBSerialDriver_v2_1_6.dmg; sourceTree = "<group>"; };
|
||||
@ -987,8 +983,6 @@
|
||||
33FFFEAC0965BD110016AC38 /* dist */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
333269E1099BB1FC007D3AE2 /* tools.zip */,
|
||||
330B21530968180400345666 /* librxtxSerial.jnilib */,
|
||||
33FFFEAE0965BD110016AC38 /* bootloader */,
|
||||
33FFFEB20965BD110016AC38 /* drivers */,
|
||||
33FFFEB50965BD110016AC38 /* DS_Store */,
|
||||
@ -1078,7 +1072,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
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 */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
@ -1091,7 +1085,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
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 */ = {
|
||||
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
Loading…
x
Reference in New Issue
Block a user