Directory transmitter renamed to radio

This commit is contained in:
Bertrand Songis
2013-12-02 07:13:57 +01:00
parent f4df52a033
commit 942e658c8e
707 changed files with 0 additions and 0 deletions
@@ -0,0 +1,343 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../../opentx.h"
#ifndef SIMU
inline void boardInit()
{
// Set up I/O port data directions and initial states
DDRA = 0xff; PORTA = 0x00; // LCD data
DDRB = 0b11000111; PORTB = 0b00111111; // 7:SPKR, 6:PPM_OUT, 5:TrainSW, 4:IDL2_SW, SDCARD[3:MISO 2:MOSI 1:SCK 0:CS]
DDRC = 0x3f; PORTC = 0xc0; // 7:AilDR, 6:EleDR, LCD[5,4,3,2,1], 0:BackLight
DDRD = 0b11000000; PORTD = 0b11111100; // 7:VIB, 6:LED BL, 5:RENC2_PUSH, 4:RENC1_PUSH, 3:RENC2_B, 2:RENC2_A, 1:I2C_SDA, 0:I2C_SCL
DDRE = 0b00001010; PORTE = 0b11110100; // 7:PPM_IN, 6: RENC1_B, 5:RENC1_A, 4:USB_DNEG, 3:BUZZER, 2:USB_DPOS, 1:TELEM_TX, 0:TELEM_RX(pull-up off)
DDRF = 0x00; PORTF = 0x00; // 7-4:JTAG, 3:ADC_REF_1.2V input, 2-0:ADC_SPARE_2-0
DDRG = 0b00010000; PORTG = 0xff; // 7-6:N/A, 5:GearSW, 4: Sim_Ctrl[out], 3:IDL1_Sw, 2:TCut_Sw, 1:RF_Power[in], 0: RudDr_Sw
#if defined(DEBUG) && !defined(VOICE)
DDRH = 0b11111000; PORTH = 0b11010111; // PORTH:7-6 enabled for timing analysis output ... see below ...
#else
DDRH = 0b10111000; PORTH = 0b11010111; // [7:0 DSM/PPM TX-caddy control. 1=PPM, 0=DSM ]
// [6:SOMO14D-BUSY 5:SOMO14D-DATA 4:SOMO14D-CLK 3:SOMO14D-RESET]
// [2:VIB_OPTION -- setting to input for now]
// [1:TxD 0:RxD Spare serial port]
#endif
DDRJ = 0x00; PORTJ = 0xff; // 7-0:Trim switch inputs
DDRK = 0x00; PORTK = 0x00; // anain. No pull-ups!
#ifdef REV0
DDRL = 0x80; PORTL = 0x7f; // 7: Hold_PWR_On (1=On, default Off), 6:Jack_Presence_TTL, 5-0: User Button inputs
#else
DDRL = 0x80; PORTL = 0xff; // 7: Hold_PWR_On (1=On, default Off), 6:Jack_Presence_TTL, 5-0: User Button inputs
#endif
ADMUX=ADC_VREF_TYPE;
ADCSRA=0x85; // ADC enabled, pre-scaler division=32 (no interrupt, no auto-triggering)
ADCSRB=(1<<MUX5);
/**** Set up timer/counter 0 ****/
/** Move old 64A Timer0 functions to Timer2 and use WGM on OC0(A) (PB7) for spkear tone output **/
// TCNT0 10ms = 16MHz/1024/156(.25) periodic timer (100ms interval)
// cycles at 9.984ms but includes 1:4 duty cycle correction to /157 to average at 10.0ms
TCCR2B = (0b111 << CS20); // Norm mode, clk/1024 (differs from ATmega64 chip)
OCR2A = 156;
TIMSK2 |= (1<<OCIE2A) | (1<<TOIE2); // Enable Output-Compare and Overflow interrrupts
// Set up Phase correct Waveform Gen. mode, at clk/64 = 250,000 counts/second
// (Higher speed allows for finer control of frquencies in the audio range.)
// Used for audio tone generation
TCCR0B = (1<<WGM02) | (0b011 << CS00);
TCCR0A = (0b01<<WGM00);
/***************************************************/
/* Rotary encoder interrupt set-up (V4 board only) */
// All external interrupts initialise to disabled. But maybe not after
// a WDT or BOD event? So to be safe ...
EIMSK = 0; // disable ALL external interrupts.
// encoder 1
EICRB = (1<<ISC60) | (1<<ISC50); // 01 = interrupt on any edge
EIFR = (3<<INTF5); // clear the int. flag in case it got set when changing modes
// encoder 2
EICRA = (1<<ISC30) | (1<<ISC20); // do the same for encoder 1
EIFR = (3<<INTF2);
#if ROTARY_ENCODERS > 2
EIMSK = (3<<INT5); // enable the ONE rot. enc. ext. int. pairs.
#else
EIMSK = (3<<INT5) | (3<<INT2); // enable the two rot. enc. ext. int. pairs.
#endif
/***************************************************/
#if defined (VOICE)
/*
* SOMO set-up (V4 board only)
*/
OCR4A = 0x1F4; //2ms
TCCR4B = (1 << WGM42) | (0b011 << CS40); // CTC OCR1A, 16MHz / 64 (4us ticks)
TIMSK4 |= (1<<OCIE4A); // Start the interrupt so the unit reset can occur
#endif
#if ROTARY_ENCODERS > 2
//configure uart1 here
DDRD &= ~(1 << 2);
PORTD &= ~(1 << 2);
#define EXTRA_ROTARY_ENCODERS_USART_BAUD 9600UL
UBRR1 = F_CPU/(16*EXTRA_ROTARY_ENCODERS_USART_BAUD)-1;
//9 bit mode
UCSR1C = (1<<USBS1)|(3<<UCSZ10);
UCSR1B = (1<<RXEN1)|(0<<TXEN1)|(1<<UCSZ12);
UCSR1B |= 1 << RXCIE1; //enable interrupt on rx
#endif
}
#if ROTARY_ENCODERS > 2
uint8_t vpotToChange = 0;
uint8_t vpot_mod_state = 0;
ISR(USART1_RX_vect)
{
//receive data from extension board
//bit 9 = 1 mean encoder number, following byte with bit 9 = 0 is increment value
/* Get status and 9th bit, then data */
/* from buffer */
uint16_t resh = UCSR1B;
uint16_t resl = UDR1;
uint16_t res = 0;
/* Filter the 9th bit, then return */
resh = (resh >> 1) & 0x01;
res = ((resh << 8) | resl);
if((res == 0x180) | (res == 0x1C0)){ //button REb filter
keys[BTN_REa].input((res & 0x1C0) == 0x1C0, BTN_REa);
} else if((res & 0x100) == 0x100){ //rotary filter
vpotToChange = res & 0xEF;
vpot_mod_state = 1;
}
else {
if(vpot_mod_state & (vpotToChange < NUM_ROTARY_ENCODERS))
{
int8_t vpot_inc = res & 0xFF;
if(vpot_inc){
incRotaryEncoder(vpotToChange, vpot_inc);
}
vpot_mod_state = 0;
}
}
}
#endif
#endif // !SIMU
uint8_t pwrCheck()
{
#if !defined(SIMU) && !defined(REV0)
if ((PING & 0b00000010) && (~PINL & 0b01000000))
return e_power_off;
#endif
return e_power_on;
}
void pwrOff()
{
#ifndef REV0
PORTL = 0x7f;
#endif
}
#if ROTARY_ENCODERS <= 2
#define ROTENC_DOWN() ((~PIND & 0x20) || (~PIND & 0x10))
#else
#define ROTENC_DOWN() (0)
#endif
FORCEINLINE uint8_t keyDown()
{
return ((~PINL) & 0x3F) || ROTENC_DOWN();
}
bool switchState(EnumKeys enuk)
{
uint8_t result = 0 ;
if (enuk < (int)DIM(keys))
return keys[enuk].state() ? 1 : 0;
switch(enuk){
case SW_ELE:
result = PINC & (1<<INP_C_ElevDR);
break;
case SW_AIL:
result = PINC & (1<<INP_C_AileDR);
break;
case SW_RUD:
result = PING & (1<<INP_G_RuddDR);
break;
// INP_G_ID1 INP_B_ID2
// id0 0 1
// id1 1 1
// id2 1 0
case SW_ID0:
result = !(PING & (1<<INP_G_ID1));
break;
case SW_ID1:
result = (PING & (1<<INP_G_ID1))&& (PINB & (1<<INP_B_ID2));
break;
case SW_ID2:
result = !(PINB & (1<<INP_B_ID2));
break;
#if 0
case SW_ID3:
result = (calibratedStick[POT1+EXTRA_3POS-1] < 0);
break;
case SW_ID4:
result = (calibratedStick[POT1+EXTRA_3POS-1] == 0);
break;
case SW_ID5:
result = (calibratedStick[POT1+EXTRA_3POS-1] > 0);
break;
#endif
case SW_GEA:
result = PING & (1<<INP_G_Gear);
break;
case SW_THR:
result = PING & (1<<INP_G_ThrCt);
break;
case SW_TRN:
result = PINB & (1<<INP_B_Trainer);
break;
default:
break;
}
return result;
}
FORCEINLINE void readKeysAndTrims()
{
/* Original keys were connected to PORTB as follows:
Bit Key
7 other use
6 LEFT
5 RIGHT
4 UP
3 DOWN
2 EXIT
1 MENU
0 other use
*/
uint8_t enuk = KEY_MENU;
#if ROTARY_ENCODERS <= 2
keys[BTN_REa].input(~PIND & 0x20, BTN_REa);
#endif
keys[BTN_REb].input(~PIND & 0x10, BTN_REb);
uint8_t tin = ~PINL;
uint8_t in;
in = (tin & 0x0f) << 3;
in |= (tin & 0x30) >> 3;
for (int i=1; i<7; i++)
{
//INP_B_KEY_MEN 1 .. INP_B_KEY_LFT 6
keys[enuk].input(in & (1<<i),(EnumKeys)enuk);
++enuk;
}
// Trim switches ...
static const pm_uchar crossTrim[] PROGMEM ={
1<<INP_J_TRM_LH_DWN,
1<<INP_J_TRM_LH_UP,
1<<INP_J_TRM_LV_DWN,
1<<INP_J_TRM_LV_UP,
1<<INP_J_TRM_RV_DWN,
1<<INP_J_TRM_RV_UP,
1<<INP_J_TRM_RH_DWN,
1<<INP_J_TRM_RH_UP
};
in = ~PINJ;
for (int i=0; i<8; i++) {
// INP_D_TRM_RH_UP 0 .. INP_D_TRM_LH_UP 7
keys[enuk].input(in & pgm_read_byte(crossTrim+i),(EnumKeys)enuk);
++enuk;
}
}
#if ROTARY_ENCODERS <= 2
ISR(INT2_vect)
{
uint8_t input = (PIND & 0x0C);
if (input == 0 || input == 0x0C) incRotaryEncoder(0, -1);
}
ISR(INT3_vect)
{
uint8_t input = (PIND & 0x0C);
if (input == 0 || input == 0x0C) incRotaryEncoder(0, +1);
}
#endif
ISR(INT5_vect)
{
uint8_t input = (PINE & 0x60);
if (input == 0 || input == 0x60) incRotaryEncoder(1, +1);
}
ISR(INT6_vect)
{
uint8_t input = (PINE & 0x60);
if (input == 0 || input == 0x60) incRotaryEncoder(1, -1);
}
+190
View File
@@ -0,0 +1,190 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef board_gruvin9x_h
#define board_gruvin9x_h
#define GPIO_BUTTON_MENU pinl
#define GPIO_BUTTON_EXIT pinl
#define GPIO_BUTTON_RIGHT pinl
#define GPIO_BUTTON_LEFT pinl
#define GPIO_BUTTON_UP pinl
#define GPIO_BUTTON_DOWN pinl
#define PIN_BUTTON_MENU (1<<INP_L_KEY_MEN)
#define PIN_BUTTON_EXIT (1<<INP_L_KEY_EXT)
#define PIN_BUTTON_UP (1<<INP_L_KEY_UP)
#define PIN_BUTTON_DOWN (1<<INP_L_KEY_DWN)
#define PIN_BUTTON_RIGHT (1<<INP_L_KEY_RGT)
#define PIN_BUTTON_LEFT (1<<INP_L_KEY_LFT)
#define GPIO_TRIM_LH_L pinj
#define GPIO_TRIM_LV_DN pinj
#define GPIO_TRIM_RV_UP pinj
#define GPIO_TRIM_RH_L pinj
#define GPIO_TRIM_LH_R pinj
#define GPIO_TRIM_LV_UP pinj
#define GPIO_TRIM_RV_DN pinj
#define GPIO_TRIM_RH_R pinj
#define PIN_TRIM_LH_L (1<<INP_J_TRM_LH_DWN)
#define PIN_TRIM_LV_DN (1<<INP_J_TRM_LV_DWN)
#define PIN_TRIM_RV_UP (1<<INP_J_TRM_RV_UP)
#define PIN_TRIM_RH_L (1<<INP_J_TRM_RH_DWN)
#define PIN_TRIM_LH_R (1<<INP_J_TRM_LH_UP)
#define PIN_TRIM_LV_UP (1<<INP_J_TRM_LV_UP)
#define PIN_TRIM_RV_DN (1<<INP_J_TRM_RV_DWN)
#define PIN_TRIM_RH_R (1<<INP_J_TRM_RH_UP)
#define TIMER_16KHZ_VECT TIMER2_OVF_vect
#define COUNTER_16KHZ TCNT2
#define TIMER_10MS_VECT TIMER2_COMPA_vect
#define TIMER_10MS_COMPVAL OCR2A
#define PAUSE_10MS_INTERRUPT() TIMSK2 &= ~(1<<OCIE2A)
#define RESUME_10MS_INTERRUPT() TIMSK2 |= (1<<OCIE2A)
#define PAUSE_PPMIN_INTERRUPT() TIMSK3 &= ~(1<<ICIE3)
#define RESUME_PPMIN_INTERRUPT() TIMSK3 |= (1<<ICIE3)
#define SLAVE_MODE() (PING & (1<<INP_G_RF_POW))
#define JACK_PPM_OUT() PORTG |= (1<<OUT_G_SIM_CTL)
#define JACK_PPM_IN() PORTG &= ~(1<<OUT_G_SIM_CTL)
// SD driver
#if !defined(SIMU)
bool sdMounted();
void sdMountPoll();
void sdPoll10ms();
#define sdDone()
#define SD_IS_HC() (0)
#define SD_GET_BLOCKNR() (0)
#define SD_GET_SIZE_MB() (0)
#define SD_GET_SPEED() (0)
#endif
#define SPEAKER_ON TCCR0A |= (1 << COM0A0)
#define SPEAKER_OFF TCCR0A &= ~(1 << COM0A0)
#define __BACKLIGHT_ON PORTC |= (1 << OUT_C_LIGHT)
#define __BACKLIGHT_OFF PORTC &= ~(1 << OUT_C_LIGHT)
#define IS_BACKLIGHT_ON() (PORTC & (1<<OUT_C_LIGHT))
# define INP_L_SPARE6 7
# define INP_L_SPARE5 6
# define INP_L_KEY_EXT 5
# define INP_L_KEY_MEN 4
# define INP_L_KEY_LFT 3
# define INP_L_KEY_RGT 2
# define INP_L_KEY_UP 1
# define INP_L_KEY_DWN 0
# define INP_J_TRM_RH_UP 7
# define INP_J_TRM_RH_DWN 6
# define INP_J_TRM_RV_UP 5
# define INP_J_TRM_RV_DWN 4
# define INP_J_TRM_LV_UP 3
# define INP_J_TRM_LV_DWN 2
# define INP_J_TRM_LH_UP 1
# define INP_J_TRM_LH_DWN 0
# define INP_E_PPM_IN 7
# define INP_E_ROT_ENC_1_B 6
# define INP_E_ROT_ENC_1_A 5
# define INP_E_USB_D_PLS 4
# define OUT_E_BUZZER 3
# define INP_E_USB_D_NEG 2
# define INP_E_TELEM_RX 1
# define OUT_E_TELEM_TX 0
# define OUT_D_HAPTIC 7
# define INP_D_SPARE4 6
# define INP_D_ROT_ENC_2_PUSH 5
# define INP_D_ROT_ENC_1_PUSH 4
# define OUT_D_ROT_ENC_2_B 3
# define INP_D_ROT_ENC_2_A 2
# define INP_D_I2C_SCL 1
# define INP_D_I2C_SDA 0
# define INP_G_Gear 5
# define INP_G_ThrCt 2
# define OUT_G_SIM_CTL 4 //1 : phone-jack=ppm_in
# define INP_G_ID1 3
# define INP_G_RF_POW 1
# define INP_G_RuddDR 0
# define INP_C_AileDR 7
# define INP_C_ElevDR 6
# define OUT_C_LIGHT 0
# define OUT_B_Speaker 7
# define OUT_B_PPM 6 // will be switched by TCNT1==OCR1B in hardware
# define INP_B_Trainer 5
# define INP_B_ID2 4
#if defined(VOICE)
# define OUT_H_14DRESET 3
# define OUT_H_14DCLK 4
# define OUT_H_14DDATA 5
# define INP_H_14DBUSY 6
#endif
// Keys driver
#define TRIMS_PRESSED() (~PINJ)
#define KEYS_PRESSED() (~PINL) // used only for DBLKEYS code.
#define DBLKEYS_PRESSED_RGT_LFT(i) ((in & ((1<<INP_L_KEY_RGT) + (1<<INP_L_KEY_LFT))) == ((1<<INP_L_KEY_RGT) + (1<<INP_L_KEY_LFT)))
#define DBLKEYS_PRESSED_UP_DWN(i) ((in & ((1<<INP_L_KEY_UP) + (1<<INP_L_KEY_DWN))) == ((1<<INP_L_KEY_UP) + (1<<INP_L_KEY_DWN)))
#define DBLKEYS_PRESSED_RGT_UP(i) ((in & ((1<<INP_L_KEY_RGT) + (1<<INP_L_KEY_UP))) == ((1<<INP_L_KEY_RGT) + (1<<INP_L_KEY_UP)))
#define DBLKEYS_PRESSED_LFT_DWN(i) ((in & ((1<<INP_L_KEY_LFT) + (1<<INP_L_KEY_DWN))) == ((1<<INP_L_KEY_LFT) + (1<<INP_L_KEY_DWN)))
// LCD driver
#define PORTA_LCD_DAT PORTA
#define PORTC_LCD_CTRL PORTC
#define OUT_C_LCD_E 5
#define OUT_C_LCD_RnW 4
#define OUT_C_LCD_A0 3
#define OUT_C_LCD_RES 2
#define OUT_C_LCD_CS1 1
// Power driver
uint8_t pwrCheck();
void pwrOff();
#define UNEXPECTED_SHUTDOWN() ((mcusr & (1 << WDRF)) || g_eeGeneral.unexpectedShutdown)
// USB fake driver
#define usbPlugged() false
// Haptic driver
#define hapticOff() // TODO hapticOn() cleaner ...
#endif
+692
View File
@@ -0,0 +1,692 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*-----------------------------------------------------------------------*/
/* MMCv3/SDv1/SDv2 (in SPI mode) control module (C)ChaN, 2010 */
/*-----------------------------------------------------------------------*/
/* Only rcvr_spi(), xmit_spi(), sdPoll10mS() and some macros */
/* are platform dependent. */
/*-----------------------------------------------------------------------*/
#include "../opentx.h"
#include "../FatFs/diskio.h"
/* Definitions for MMC/SDC command */
#define CMD0 (0) /* GO_IDLE_STATE */
#define CMD1 (1) /* SEND_OP_COND (MMC) */
#define ACMD41 (0x80+41) /* SEND_OP_COND (SDC) */
#define CMD8 (8) /* SEND_IF_COND */
#define CMD9 (9) /* SEND_CSD */
#define CMD10 (10) /* SEND_CID */
#define CMD12 (12) /* STOP_TRANSMISSION */
#define ACMD13 (0x80+13) /* SD_STATUS (SDC) */
#define CMD16 (16) /* SET_BLOCKLEN */
#define CMD17 (17) /* READ_SINGLE_BLOCK */
#define CMD18 (18) /* READ_MULTIPLE_BLOCK */
#define CMD23 (23) /* SET_BLOCK_COUNT (MMC) */
#define ACMD23 (0x80+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
#define CMD24 (24) /* WRITE_BLOCK */
#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */
#define CMD55 (55) /* APP_CMD */
#define CMD58 (58) /* READ_OCR */
/* Card type flags (CardType) */
#define CT_MMC 0x01 /* MMC ver 3 */
#define CT_SD1 0x02 /* SD ver 1 */
#define CT_SD2 0x04 /* SD ver 2 */
#define CT_SDC (CT_SD1|CT_SD2) /* SD */
#define CT_BLOCK 0x08 /* Block addressing */
/* Port Controls (Platform dependent) */
// GCC optimisation should result in a single CBI/SBI instructions here
#if defined (PCBGRUVIN9X)
# define CS_LOW() PORTB &= ~0x01 /* MMC CS = L */
# define CS_HIGH() PORTB |= 0x01 /* MMC CS = H */
#else
# define CS_LOW() PORTB &= ~0x10 /* MMC CS = L */
# define CS_HIGH() PORTB |= 0x10 /* MMC CS = H */
#endif
#define SOCKPORT PINB /* Socket contact port */
#define SOCKWP 0x00 // not implemented /* Write protect switch */
#define SOCKINS 0x00 // not implemented /* Card detect switch */
#define FCLK_SLOW() SPCR = 0x52 /* Set slow clock (100k-400k) */
#define FCLK_FAST() SPCR = 0x50 /* Set fast clock (depends on the CSD) */
/*--------------------------------------------------------------------------
Module Private Functions
---------------------------------------------------------------------------*/
static volatile
DSTATUS Stat = STA_NOINIT; /* Disk status */
volatile BYTE Timer1, Timer2; /* 100Hz decrement timer */
static
BYTE CardType; /* Card type flags */
#if defined(SIMU)
#define loop_mixer_until_bit_is_set loop_until_bit_is_set
#else
inline void checkMixer()
{
// TODO duplicated code ...
uint16_t t0 = getTmr16KHz();
int16_t delta = (nextMixerEndTime - lastMixerDuration) - t0;
if (delta > 0 && delta < MAX_MIXER_DELTA) return;
nextMixerEndTime = t0 + MAX_MIXER_DELTA;
doMixerCalculations();
t0 = getTmr16KHz() - t0;
lastMixerDuration = t0;
if (t0 > maxMixerDuration) maxMixerDuration = t0;
}
#define loop_mixer_until_bit_is_set(sfr, bit) do { checkMixer(); wdt_reset(); } while (bit_is_clear(sfr, bit))
#endif
/*-----------------------------------------------------------------------*/
/* Transmit a byte to MMC via SPI (Platform dependent) */
/*-----------------------------------------------------------------------*/
#define xmit_spi(dat) SPDR=(dat); loop_mixer_until_bit_is_set(SPSR,SPIF)
/*-----------------------------------------------------------------------*/
/* Receive a byte from MMC via SPI (Platform dependent) */
/*-----------------------------------------------------------------------*/
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
loop_mixer_until_bit_is_set(SPSR, SPIF);
return SPDR;
}
/* Alternative macro to receive data fast */
#define rcvr_spi_m(dst) SPDR=0xFF; loop_mixer_until_bit_is_set(SPSR,SPIF); *(dst)=SPDR
/*-----------------------------------------------------------------------*/
/* Wait for card ready */
/*-----------------------------------------------------------------------*/
static
int wait_ready (void) /* 1:OK, 0:Timeout */
{
Timer2 = 50; /* Wait for ready in timeout of 500ms (G: now 50x16ms) */
rcvr_spi();
do
if (rcvr_spi() == 0xFF) return 1;
while (Timer2);
return 0;
}
/*-----------------------------------------------------------------------*/
/* Deselect the card and release SPI bus */
/*-----------------------------------------------------------------------*/
static
void deselect (void)
{
CS_HIGH();
rcvr_spi();
}
/*-----------------------------------------------------------------------*/
/* Select the card and wait for ready */
/*-----------------------------------------------------------------------*/
static
int select (void) /* 1:Successful, 0:Timeout */
{
CS_LOW();
if (!wait_ready()) {
deselect();
return 0;
}
return 1;
}
/*-----------------------------------------------------------------------*/
/* Power Control (Platform dependent) */
/*-----------------------------------------------------------------------*/
/* When the target system does not support socket power control, there */
/* is nothing to do in these functions and chk_power always returns 1. */
static
int power_status(void) /* Socket power state: 0=off, 1=on */
{
return (PORTE & 0x80) ? 0 : 1;
}
static
void power_on (void)
{
// PORTE &= ~0x80; // Socket power on
#ifndef SIMU
for (Timer1 = 2; Timer1; ); // Wait for 20ms
#endif
//PORTB = 0b10110101; // Enable drivers
//DDRB = 0b11000111;
SPCR = 0x52; // Enable SPI function in mode 0
SPSR = 0x00; // G: was 0x01; // SPI 2x mode
}
static
void power_off (void)
{
SPCR = 0; /* Disable SPI function */
// DDRB = 0b11000000; /* Disable drivers */
// PORTB = 0b10110000;
// PORTE |= 0x80; /* Socket power off */
Stat |= STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Receive a data packet from MMC */
/*-----------------------------------------------------------------------*/
static
int rcvr_datablock (
BYTE *buff, /* Data buffer to store received data */
UINT btr /* Byte count (must be multiple of 4) */
)
{
BYTE token;
Timer1 = 20;
do { /* Wait for data packet in timeout of 200ms */
token = rcvr_spi();
} while ((token == 0xFF) && Timer1);
if(token != 0xFE) return 0; /* If not valid data token, retutn with error */
do { /* Receive the data block into buffer */
rcvr_spi_m(buff++);
rcvr_spi_m(buff++);
rcvr_spi_m(buff++);
rcvr_spi_m(buff++);
} while (btr -= 4);
rcvr_spi(); /* Discard CRC */
rcvr_spi();
return 1; /* Return with success */
}
/*-----------------------------------------------------------------------*/
/* Send a data packet to MMC */
/*-----------------------------------------------------------------------*/
static
int xmit_datablock (
const BYTE *buff, /* 512 byte data block to be transmitted */
BYTE token /* Data/Stop token */
)
{
BYTE resp, wc;
if (!wait_ready()) return 0;
xmit_spi(token); /* Xmit data token */
if (token != 0xFD) { /* Is data token */
wc = 0;
do { /* Xmit the 512 byte data block to MMC */
xmit_spi(*buff++);
xmit_spi(*buff++);
} while (--wc);
xmit_spi(0xFF); /* CRC (Dummy) */
xmit_spi(0xFF);
resp = rcvr_spi(); /* Reveive data response */
if ((resp & 0x1F) != 0x05) /* If not accepted, return with error */
return 0;
}
return 1;
}
/*-----------------------------------------------------------------------*/
/* Send a command packet to MMC */
/*-----------------------------------------------------------------------*/
static
BYTE send_cmd ( /* Returns R1 resp (bit7==1:Send failed) */
BYTE cmd, /* Command index */
DWORD arg /* Argument */
)
{
BYTE n, res;
if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
cmd &= 0x7F;
res = send_cmd(CMD55, 0);
if (res > 1) return res;
}
/* Select the card and wait for ready */
deselect();
if (!select()) return 0xFF;
/* Send command packet */
xmit_spi(0x40 | cmd); /* Start + Command index */
xmit_spi((BYTE)(arg >> 24)); /* Argument[31..24] */
xmit_spi((BYTE)(arg >> 16)); /* Argument[23..16] */
xmit_spi((BYTE)(arg >> 8)); /* Argument[15..8] */
xmit_spi((BYTE)arg); /* Argument[7..0] */
n = 0x01; /* Dummy CRC + Stop */
if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */
if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */
xmit_spi(n);
/* Receive command response */
if (cmd == CMD12) rcvr_spi(); /* Skip a stuff byte when stop reading */
n = 10; /* Wait for a valid response in timeout of 10 attempts */
do
res = rcvr_spi();
while ((res & 0x80) && --n);
return res; /* Return with the response value */
}
/*--------------------------------------------------------------------------
Public Functions
---------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
/* Initialize Disk Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
BYTE drv /* Physical drive nmuber (0) */
)
{
BYTE n, cmd, ty, ocr[4];
if (drv) return STA_NOINIT; /* Supports only single drive */
if (Stat & STA_NODISK) return Stat; /* No card in the socket */
power_on(); /* Force socket power on */
FCLK_SLOW();
for (n = 10; n; n--) rcvr_spi(); /* 80 dummy clocks */
ty = 0;
if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
Timer1 = 100; /* Initialization timeout of 1000 msec */
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2? */
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi(); /* Get trailing return value of R7 resp */
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
while (Timer1 && send_cmd(ACMD41, 1UL << 30)); /* Wait for leaving idle state (ACMD41 with HCS bit) */
if (Timer1 && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 */
}
}
} else { /* SDv1 or MMCv3 */
if (send_cmd(ACMD41, 0) <= 1) {
ty = CT_SD1; cmd = ACMD41; /* SDv1 */
} else {
ty = CT_MMC; cmd = CMD1; /* MMCv3 */
}
while (Timer1 && send_cmd(cmd, 0)); /* Wait for leaving idle state */
if (!Timer1 || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */
ty = 0;
}
}
CardType = ty;
deselect();
if (ty) { /* Initialization succeded */
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
FCLK_FAST();
} else { /* Initialization failed */
power_off();
}
return Stat;
}
/*-----------------------------------------------------------------------*/
/* Get Disk Status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE drv /* Physical drive number (0) */
)
{
if (drv) return STA_NOINIT; /* Supports only single drive */
return Stat;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE drv, /* Physical drive nmuber (0) */
BYTE *buff, /* Pointer to the data buffer to store read data */
DWORD sector, /* Start sector number (LBA) */
BYTE count /* Sector count (1..255) */
)
{
if (drv || !count) return RES_PARERR;
if (Stat & STA_NOINIT) return RES_NOTRDY;
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
if (count == 1) { /* Single block read */
if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */
&& rcvr_datablock(buff, 512))
count = 0;
}
else { /* Multiple block read */
if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */
do {
if (!rcvr_datablock(buff, 512)) break;
buff += 512;
} while (--count);
send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
}
}
deselect();
return count ? RES_ERROR : RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_write (
BYTE drv, /* Physical drive nmuber (0) */
const BYTE *buff, /* Pointer to the data to be written */
DWORD sector, /* Start sector number (LBA) */
BYTE count /* Sector count (1..255) */
)
{
if (drv || !count) return RES_PARERR;
if (Stat & STA_NOINIT) return RES_NOTRDY;
if (Stat & STA_PROTECT) return RES_WRPRT;
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
if (count == 1) { /* Single block write */
if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
&& xmit_datablock(buff, 0xFE))
count = 0;
}
else { /* Multiple block write */
if (CardType & CT_SDC) send_cmd(ACMD23, count);
if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
do {
if (!xmit_datablock(buff, 0xFC)) break;
buff += 512;
} while (--count);
if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
count = 1;
}
}
deselect();
return count ? RES_ERROR : RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
DRESULT disk_ioctl (
BYTE drv, /* Physical drive nmuber (0) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res;
BYTE n, csd[16], *ptr = (BYTE*)buff;
WORD csize;
if (drv) return RES_PARERR;
res = RES_ERROR;
if (ctrl == CTRL_POWER) {
switch (ptr[0]) {
case 0: /* Sub control code (POWER_OFF) */
power_off(); /* Power off */
res = RES_OK;
break;
case 1: /* Sub control code (POWER_GET) */
ptr[1] = (BYTE)power_status();
res = RES_OK;
break;
default :
res = RES_PARERR;
}
}
else {
if (Stat & STA_NOINIT) return RES_NOTRDY;
switch (ctrl) {
case CTRL_SYNC : /* Make sure that no pending write process. Do not remove this or written sector might not left updated. */
if (select()) {
deselect();
res = RES_OK;
}
break;
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */
csize = csd[9] + ((WORD)csd[8] << 8) + 1;
*(DWORD*)buff = (DWORD)csize << 10;
} else { /* SDC ver 1.XX or MMC*/
n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
*(DWORD*)buff = (DWORD)csize << (n - 9);
}
res = RES_OK;
}
break;
case GET_SECTOR_SIZE : /* Get R/W sector size (WORD) */
*(WORD*)buff = 512;
res = RES_OK;
break;
case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */
if (CardType & CT_SD2) { /* SDv2? */
if (send_cmd(ACMD13, 0) == 0) { /* Read SD status */
rcvr_spi();
if (rcvr_datablock(csd, 16)) { /* Read partial block */
for (n = 64 - 16; n; n--) rcvr_spi(); /* Purge trailing data */
*(DWORD*)buff = 16UL << (csd[10] >> 4);
res = RES_OK;
}
}
} else { /* SDv1 or MMCv3 */
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { /* Read CSD */
if (CardType & CT_SD1) { /* SDv1 */
*(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1);
} else { /* MMCv3 */
*(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1);
}
res = RES_OK;
}
}
break;
case MMC_GET_TYPE : /* Get card type flags (1 byte) */
*ptr = CardType;
res = RES_OK;
break;
case MMC_GET_CSD : /* Receive CSD as a data block (16 bytes) */
if (send_cmd(CMD9, 0) == 0 /* READ_CSD */
&& rcvr_datablock(ptr, 16))
res = RES_OK;
break;
case MMC_GET_CID : /* Receive CID as a data block (16 bytes) */
if (send_cmd(CMD10, 0) == 0 /* READ_CID */
&& rcvr_datablock(ptr, 16))
res = RES_OK;
break;
case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */
if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
for (n = 4; n; n--) *ptr++ = rcvr_spi();
res = RES_OK;
}
break;
case MMC_GET_SDSTAT : /* Receive SD statsu as a data block (64 bytes) */
if (send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */
rcvr_spi();
if (rcvr_datablock(ptr, 64))
res = RES_OK;
}
break;
default:
res = RES_PARERR;
}
deselect();
}
return res;
}
/*-----------------------------------------------------------------------*/
/* Device Timer Interrupt Procedure */
/*-----------------------------------------------------------------------*/
/* This function must be called in period of 10ms */
void sdPoll10ms()
{
BYTE s;
/*
n = Timer1; // 100Hz decrement timer
if (n) Timer1 = --n;
n = Timer2;
if (n) Timer2 = --n;
*/
if (Timer1) Timer1--;
if (Timer2) Timer2--;
s = Stat;
/* G: Not implemented
if (SOCKWP) // Write protected
s |= STA_PROTECT;
else // Write enabled
s &= ~STA_PROTECT;
if (SOCKINS) // Card inserted
s &= ~STA_NODISK;
else // Socket empty
s |= (STA_NODISK | STA_NOINIT);
*/
s &= ~STA_NODISK;
s &= ~STA_PROTECT;
Stat = s;
}
#if !defined(SIMU)
bool sdMounted()
{
return g_FATFS_Obj.fs_type != 0;
}
void sdMountPoll()
{
static uint8_t mountTimer;
if (mountTimer-- == 0) {
mountTimer = 100;
if (!sdMounted()) {
f_mount(0, &g_FATFS_Obj);
f_chdir(ROOT_PATH);
}
}
}
#endif
FATFS g_FATFS_Obj;
+36
View File
@@ -0,0 +1,36 @@
The ATmega2561 uses quite different bit assignment for its option fuses
Fuse defaults for ATmega64A
Default values for ATmega64 are:
hfuse = 0b10011001 (0x99)
lfuse = 0b11100001 (0xE1)
efuse = 0b11111101 (0xFD)
Preferred values for ATmega64A are:
hfuse = 0x11
lfuse = 0x1F
efuse = 0xff
... which includes EESAVE feature, so that the EEPROM model data does NOT get
erased during chip erase prior to re-programming ... respectively.
- - - - - - - - - - - - - - - - - - - - - -
Fuse defaults for ATmega2560/1 are:
hfuse = 0b10011001 (0x99)
lfuse = 0b01100010 (0x62)
efuse = 0b11111111 (0xFF)
The bit assignments ae quite different from the AT'64A in all cases.
Preferred vale es for ATmega2560/1 are:
hfuse = 0b10011001 (0x11) [OCD enabled, JTAG enabled, WDT disabled :(,
EESAVE enabled, BOOT at 0x0000]
lfuse = 0b01101110 (0xd7) [CKDIV8 disabled, CKOUT disabled,
Full Swing Xtal Osc, 16K CK + 0ms reset,
BOD enabled]
efuse = 0b11111111 (0xfc) [ Brown out detector (BOD) = 4.3V ]
+322
View File
@@ -0,0 +1,322 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*--------------------------------------------------------------------------*/
/* RTC controls */
#include "../opentx.h"
#include "../FatFs/integer.h"
typedef struct {
WORD year; /* 2000..2099 */
BYTE month; /* 1..12 */
BYTE mday; /* 1.. 31 */
BYTE wday; /* 1..7 */
BYTE hour; /* 0..23 */
BYTE min; /* 0..59 */
BYTE sec; /* 0..59 */
} RTC;
#define SCL_LOW() DDRD |= 0x01 /* SCL = LOW */
#define SCL_HIGH() DDRD &= ~0x01 /* SCL = High-Z */
#define SCL_VAL ((PIND & 0x01) ? 1 : 0) /* SCL input level */
#define SDA_LOW() DDRD |= 0x02 /* SDA = LOW */
#define SDA_HIGH() DDRD &= ~0x02 /* SDA = High-Z */
#define SDA_VAL ((PIND & 0x02) ? 1 : 0) /* SDA input level */
/*-------------------------------------------------*/
/* I2C bus protocol */
static
void iic_delay (void)
{
#ifndef SIMU
for (int n = 4; n; n--) PINB;
#endif
}
/* Generate start condition on the IIC bus */
static
void iic_start (void)
{
SDA_HIGH();
iic_delay();
SCL_HIGH();
iic_delay();
SDA_LOW();
iic_delay();
SCL_LOW();
iic_delay();
}
/* Generate stop condition on the IIC bus */
static
void iic_stop (void)
{
SDA_LOW();
iic_delay();
SCL_HIGH();
iic_delay();
SDA_HIGH();
iic_delay();
}
/* Send a byte to the IIC bus */
static
int iic_send (BYTE dat)
{
BYTE b = 0x80;
int ack;
do {
if (dat & b) { /* SDA = Z/L */
SDA_HIGH();
} else {
SDA_LOW();
}
iic_delay();
SCL_HIGH();
iic_delay();
SCL_LOW();
iic_delay();
} while (b >>= 1);
SDA_HIGH();
iic_delay();
SCL_HIGH();
ack = SDA_VAL ? 0 : 1; /* Sample ACK */
iic_delay();
SCL_LOW();
iic_delay();
return ack;
}
/* Receive a byte from the IIC bus */
static
BYTE iic_rcvr (int ack)
{
UINT d = 1;
do {
d <<= 1;
SCL_HIGH();
if (SDA_VAL) d++;
iic_delay();
SCL_LOW();
iic_delay();
} while (d < 0x100);
if (ack) { /* SDA = ACK */
SDA_LOW();
} else {
SDA_HIGH();
}
iic_delay();
SCL_HIGH();
iic_delay();
SCL_LOW();
SDA_HIGH();
iic_delay();
return (BYTE)d;
}
/*-------------------------------------------------*/
/* I2C block read/write controls */
int iic_read (
BYTE dev, /* Device address */
UINT adr, /* Read start address */
UINT cnt, /* Read byte count */
BYTE *buff /* Read data buffer */
)
{
BYTE *rbuff = buff;
int n;
if (!cnt) return 0;
n = 10;
do { /* Select device */
iic_start();
} while (!iic_send(dev) && --n);
if (n) {
if (iic_send((BYTE)adr)) { /* Set start address */
iic_start(); /* Reselect device in read mode */
if (iic_send(dev | 1)) {
do { /* Receive data */
cnt--;
*rbuff++ = iic_rcvr(cnt ? 1 : 0);
} while (cnt);
}
}
}
iic_stop(); /* Deselect device */
return cnt ? 0 : 1;
}
int iic_write (
BYTE dev, /* Device address */
UINT adr, /* Write start address */
UINT cnt, /* Write byte count */
const BYTE *buff /* Data to be written */
)
{
const BYTE *wbuff = buff;
int n;
if (!cnt) return 0;
n = 10;
do { /* Select device */
iic_start();
} while (!iic_send(dev) && --n);
if (n) {
if (iic_send((BYTE)adr)) { /* Set start address */
do { /* Send data */
if (!iic_send(*wbuff++)) break;
} while (--cnt);
}
}
iic_stop(); /* Deselect device */
return cnt ? 0 : 1;
}
/*-------------------------------------------------*/
/* RTC functions */
int g9x_rtc_gettime (RTC *rtc)
{
BYTE buf[8];
if (!iic_read(0xD0, 0, 7, buf)) return 0;
rtc->sec = (buf[0] & 0x0F) + ((buf[0] >> 4) & 7) * 10;
rtc->min = (buf[1] & 0x0F) + (buf[1] >> 4) * 10;
rtc->hour = (buf[2] & 0x0F) + ((buf[2] >> 4) & 3) * 10;
rtc->wday = (buf[2] & 0x07);
rtc->mday = (buf[4] & 0x0F) + ((buf[4] >> 4) & 3) * 10;
rtc->month = (buf[5] & 0x0F) + ((buf[5] >> 4) & 1) * 10;
rtc->year = 2000 + (buf[6] & 0x0F) + (buf[6] >> 4) * 10;
return 1;
}
int g9x_rtcSetTime (const RTC *rtc)
{
BYTE buf[8];
buf[0] = rtc->sec / 10 * 16 + rtc->sec % 10;
buf[1] = rtc->min / 10 * 16 + rtc->min % 10;
buf[2] = rtc->hour / 10 * 16 + rtc->hour % 10;
buf[3] = rtc->wday & 7;
buf[4] = rtc->mday / 10 * 16 + rtc->mday % 10;
buf[5] = rtc->month / 10 * 16 + rtc->month % 10;
buf[6] = (rtc->year - 2000) / 10 * 16 + (rtc->year - 2000) % 10;
return iic_write(0xD0, 0, 7, buf);
}
void rtc_gettime(struct gtm * utm)
{
RTC rtc = {0,0,0,0,0,0,0};
g9x_rtc_gettime(&rtc);
utm->tm_year = rtc.year - 1900;
utm->tm_mon = rtc.month - 1;
utm->tm_mday = rtc.mday;
utm->tm_hour = rtc.hour;
utm->tm_min = rtc.min;
utm->tm_sec = rtc.sec;
utm->tm_wday = rtc.wday - 1;
}
void rtcSetTime(struct gtm * t)
{
g_rtcTime = gmktime(t); // update local timestamp and get wday calculated
g_ms100 = 0; // start of next second begins now
RTC rtc;
rtc.year = t->tm_year + 1900;
rtc.month = t->tm_mon + 1;
rtc.mday = t->tm_mday;
rtc.hour = t->tm_hour;
rtc.min = t->tm_min;
rtc.sec = t->tm_sec;
rtc.wday = t->tm_wday + 1;
g9x_rtcSetTime(&rtc);
}
void rtcInit (void)
{
BYTE buf[8]; /* RTC R/W buffer */
UINT adr;
/* Read RTC registers */
if (!iic_read(0xD0, 0, 8, buf)) return; /* IIC error */
if (buf[7] & 0x20) { /* When data has been volatiled, set default time */
/* Clear nv-ram. Reg[8..63] */
memset(buf, 0, 8);
for (adr = 8; adr < 64; adr += 8)
iic_write(0x0D, adr, 8, buf);
/* Reset time to Jan 1, '08. Reg[0..7] */
buf[4] = 1; buf[5] = 1; buf[6] = 8;
iic_write(0x0D, 0, 8, buf);
}
struct gtm utm;
rtc_gettime(&utm);
g_rtcTime = gmktime(&utm);
}
+193
View File
@@ -0,0 +1,193 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*
Cam: I did think about implimenting this with an array for the timing durations
like the original bit bang DSM2 code was done but that meant another array
on top of the playlist one, therefore more memory waisted, and because
the playlist must be executed one after another it would mean putting
the code to fill the array in the interrupt (This would be unlike the
old DSM2 code) which seemed to much for the interrupt.
*/
#include "../../opentx.h"
// Start and stop bits need to be 2ms in duration. Start bit is low, stop bit is high
#define SOMOSSBIT 5 //The 2ms of a stop/start bit
#define SOMOSTOP 48 //This is the needed 2ms (4) + 20ms (40) to allow for the
//point at which the busy flag is checkable + 2ms for saftey (4)
#define SOMOSTART 60 //This is the needed 2ms (4) + 2ms (4) for safety + 26ms (52) for the
//undocumented delay that must exist between playbacks.
#define SOMOBUSY (PINH & 0x40) /* SOMO14D Busy flag */
#define SOMOCLK (PINH & 0x10) /* SOMO14D CLK */
#define QUEUE_LENGTH 10
uint16_t somo14playlist[QUEUE_LENGTH] = {0};
uint16_t somo14command = 0;
uint8_t somo14RIdx = 0;
volatile uint8_t somo14WIdx = 0;
#ifdef SIMU
#define BUSY busy
#else
#define BUSY
#endif
NOINLINE uint8_t SomoWakeup()
{
static uint16_t somo14_current;
static uint8_t i = 0;
static uint8_t busy = 0; // debugging make BOOL when done
static uint8_t startstop = SOMOSSBIT; // Only the first playback can have this short delay
// printf("startstop=%d i=%d\n", startstop, i); fflush(stdout);
// Send no data unless we are either not busy or it's a command
// Only when stop bit is sent do we increment read pointer
// This will happen before the SOMO14D busy flag gets set
// Busy flag happens 20ms after the last data is clocked in
if (i==0 && !busy) {
if (somo14command) { // Allow a command to be send even if the SOMO is busy, i.e. STOP or PAUSE
somo14_current = somo14command;
somo14command = 0;
busy = 1;
}
else if (!SOMOBUSY) {
if (somo14RIdx == somo14WIdx) {
return 1;
}
somo14_current = somo14playlist[somo14RIdx];
somo14RIdx = (somo14RIdx + 1) % QUEUE_LENGTH;
busy = 1;
}
}
// Start and stop bits
if (busy && startstop) {
// Start bit
if (i==0) {
if (startstop < SOMOSSBIT) { // This stretches the time before we start sending data to allow for the
// undocumented delay that must exist between playbacks. Unfortunately the
// device isn't ready even though the busy flag says it is.
PORTH &= ~(1<<OUT_H_14DCLK); // Start Bit, CLK low for 2ms
}
startstop--;
return 0;
}
// Stop bit
if (i==16) {
PORTH &= ~(1<<OUT_H_14DDATA); // Data low
PORTH |= (1<<OUT_H_14DCLK); // Stop Bit, CLK high for 2ms
startstop--;
return 0;
}
}
// After stop bit is sent
// we are done sending so prepair for next
if (i==16 && !startstop) {
// Cam, here I think there is a bug (if we send a "command") somo14RPtr++;
i=0;
busy=0;
startstop = SOMOSTART;
return 0;
}
// Send the data
if (i<16 && busy) {
if (!SOMOCLK) { // Only change data when the CLK is low
startstop =SOMOSTOP;
if (somo14_current & 0x8000) {
PORTH |= (1<<OUT_H_14DDATA); // Data high
}
somo14_current = (somo14_current<<1);
i++;
// Data setup delay
_delay_us(1);
PORTH |= (1<<OUT_H_14DCLK); // CLK high
}
else { // Don't alter after sending last bit in preparation for sending stop bit
PORTH &= ~(1<<OUT_H_14DCLK); // CLK low
PORTH &= ~(1<<OUT_H_14DDATA); // Data low
}
}
return 0;
}
#ifndef SIMU
ISR(TIMER4_COMPA_vect) //Every 0.5ms normally, every 2ms during startup reset
{
static uint8_t reset_dly=4;
static uint8_t reset_pause=150;
if (reset_dly)
{OCR4A=0x1f4; reset_dly--; PORTH &= ~(1<<OUT_H_14DRESET);} // CLK low
else if (reset_pause)
{OCR4A=0x1f4; reset_pause--; PORTH |= (1<<OUT_H_14DRESET);} // RESET high
else
{
OCR4A = 0x7d; // another 0.5ms
TIMSK4 &= ~(1<<OCIE4A); // stop reentrance
sei();
uint8_t finished = SomoWakeup();
cli();
if (!finished) TIMSK4 |= (1<<OCIE4A);
}
}
#endif
void pushPrompt(uint16_t prompt)
{
/* TODO id */
somo14playlist[somo14WIdx] = prompt;
somo14WIdx = (somo14WIdx + 1) % QUEUE_LENGTH;
cli();
TIMSK4 |= (1<<OCIE4A);
sei();
}
bool isPlaying()
{
/* TODO id */
#if defined(SIMU)
return false;
#else
return TIMSK4 & (1<<OCIE4A);
#endif
}
+56
View File
@@ -0,0 +1,56 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#define PROMPT_CUSTOM_BASE 0
#define PROMPT_I18N_BASE 256
#define PROMPT_SYSTEM_BASE 480
extern void pushPrompt(uint16_t prompt);
extern bool isPlaying();
#define I18N_PLAY_FUNCTION(lng, x, ...) void x(__VA_ARGS__)
#define PLAY_FUNCTION(x, ...) void x(__VA_ARGS__)
#define PUSH_CUSTOM_PROMPT(p, id) pushPrompt(PROMPT_CUSTOM_BASE+(p))
#define PUSH_NUMBER_PROMPT(p) pushPrompt(PROMPT_I18N_BASE+(p))
#define PUSH_SYSTEM_PROMPT(p) pushPrompt(PROMPT_SYSTEM_BASE+(p))
#define PLAY_NUMBER(n, u, a) playNumber((n), (u), (a))
#define PLAY_DURATION(d) playDuration((d))
#define IS_PLAYING(id) isPlaying()
#define PLAY_VALUE(v, id) playValue((v))
#define VOLUME_LEVEL_MAX 7
#define VOLUME_LEVEL_DEF 7
#define setVolume(v)
+22
View File
@@ -0,0 +1,22 @@
MEGA2560 board
======================= DESCRIPTION =======================
DIY radio wih :
- Arduino MEGA2560 or compatible
- Artronic LCD 128x64 ST7565R (and, in a second time : Digole LCD 128x64 ST9720)
- Aurora9 gimballs
- home made wood (or fiberglass) case
- Gruvin9x features (soft-off, SD-Card, etc.) with some pins reassignment
Drawings (case, additional cards, wiring) and components listing will follow
========================= STATUS ==========================
LCD driver ST7565R : works
Pins assignment : done (io_mega2560.h)
Additional cards :
- LCD driver (3.3V + backlight) : works
- PPM + power management : in test
- gimballs Op Amp : in test
@@ -0,0 +1,274 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../../opentx.h"
#ifndef SIMU
inline void boardInit() // Done 2013.10.09 : trims, keyboard, LCD, ID1+2 SW warning PORTF-3 (1.2V ADC_ref)
{
// Set up I/O port data directions and initial states
DDRA = 0b11111111; PORTA = 0b00000000; // LCD data
DDRB = 0b11000111; PORTB = 0b00111111; // 7:SPKR, 6:PPM_OUT, 5:TrainSW, 4:xxxxx, SDCARD[3:MISO 2:MOSI 1:SCK 0:CS]
DDRC = 0b11111100; PORTC = 0b00000011; // LCD[7,6,5,4,3], 2:BackLight, 1:ID2_Sw, 0:ID1_Sw
DDRD = 0b11000000; PORTD = 0b11111100; // 7:VIB, 6:LED BL, 5:RENC2_PUSH, 4:RENC1_PUSH, 3:RENC2_B, 2:RENC2_A, 1:I2C_SDA, 0:I2C_SCL
DDRE = 0b00001010; PORTE = 0b11110100; // 7:PPM_IN, 6: RENC1_B, 5:RENC1_A, 4:USB_DNEG, 3:BUZZER, 2:USB_DPOS, 1:TELEM_TX, 0:TELEM_RX(pull-up off)
//DDRF = 0b00000000; PORTF = 0b00000000; // 7-4:JTAG, 3:ADC_REF_1.2V input, 2-0:ADC_SPARE_2-0
DDRF = 0b00000000; PORTF = 0b11111111; // 7-0:Trim switch inputs
DDRG = 0b00010000; PORTG = 0b00111111; // 7-6:N/A, 5:GearSW, 4: Sim_Ctrl[out], 3:xxxxx, 2:TCut_Sw, 1:RF_Power[in], 0: RudDr_Sw
DDRH = 0b10111000; PORTH = 0b11010111; // [7:0 DSM/PPM TX-caddy control. 1=PPM, 0=DSM ]
// [6:SOMO14D-BUSY 5:SOMO14D-DATA 4:SOMO14D-CLK 3:SOMO14D-RESET]
// [2:VIB_OPTION -- setting to input for now]
// [1:TxD 0:RxD Spare serial port]
//DDRJ = 0b00000000; PORTJ = 0b11111111; // 7-0:Trim switch inputs
DDRK = 0b00000000; PORTK = 0b00000000; // Analogic input (no pull-ups)
DDRL = 0b10000000; PORTL = 0b11111111; // 7: Hold_PWR_On (1=On, default Off), 6:Jack_Presence_TTL, 5-0: Keyboard inputs
ADMUX=ADC_VREF_TYPE;
ADCSRA=0x85; // ADC enabled, pre-scaler division=32 (no interrupt, no auto-triggering)
ADCSRB=(1<<MUX5);
/**** Set up timer/counter 0 ****/
/** Move old 64A Timer0 functions to Timer2 and use WGM on OC0(A) (PB7) for spkear tone output **/
// TCNT0 10ms = 16MHz/1024/156(.25) periodic timer (100ms interval)
// cycles at 9.984ms but includes 1:4 duty cycle correction to /157 to average at 10.0ms
TCCR2B = (0b111 << CS20); // Norm mode, clk/1024 (differs from ATmega64 chip)
OCR2A = 156;
TIMSK2 |= (1<<OCIE2A) | (1<<TOIE2); // Enable Output-Compare and Overflow interrrupts
// Set up Phase correct Waveform Gen. mode, at clk/64 = 250,000 counts/second
// (Higher speed allows for finer control of frquencies in the audio range.)
// Used for audio tone generation
TCCR0B = (1<<WGM02) | (0b011 << CS00);
TCCR0A = (0b01<<WGM00);
/***************************************************/
/* Rotary encoder interrupt set-up */
EIMSK = 0; // disable ALL external interrupts.
// encoder 1
EICRB = (1<<ISC60) | (1<<ISC50); // 01 = interrupt on any edge
EIFR = (3<<INTF5); // clear the int. flag in case it got set when changing modes
// encoder 2
EICRA = (1<<ISC30) | (1<<ISC20); // do the same for encoder 1
EIFR = (3<<INTF2);
EIMSK = (3<<INT5) | (3<<INT2); // enable the two rot. enc. ext. int. pairs.
/***************************************************/
#if defined (VOICE)
/*
* SOMO set-up (V4 board only)
*/
OCR4A = 0x1F4; //2ms
TCCR4B = (1 << WGM42) | (0b011 << CS40); // CTC OCR1A, 16MHz / 64 (4us ticks)
TIMSK4 |= (1<<OCIE4A); // Start the interrupt so the unit reset can occur
#endif
}
#endif // !SIMU
uint8_t pwrCheck()
{
#if !defined(SIMU) && !defined(REV0)
if ((PING & 0b00000010) && (~PINL & 0b01000000))
return e_power_off;
#endif
return e_power_on;
}
void pwrOff()
{
#ifndef REV0
PORTL = 0x7f;
#endif
}
#if ROTARY_ENCODERS <= 2
#define ROTENC_DOWN() ((~PIND & 0x20) || (~PIND & 0x10))
#else
#define ROTENC_DOWN() (0)
#endif
FORCEINLINE uint8_t keyDown()
{
return ((~PINL) & 0x3F) || ROTENC_DOWN();
}
bool switchState(EnumKeys enuk)
{
uint8_t result = 0 ;
if (enuk < (int)DIM(keys))
return keys[enuk].state() ? 1 : 0;
switch(enuk){
//case SW_ELE:
// result = PINC & (1<<INP_C_ElevDR);
// break;
//case SW_AIL:
// result = PINC & (1<<INP_C_AileDR);
// break;
case SW_RUD:
result = PING & (1<<INP_G_RuddDR);
break;
// INP_G_ID1 INP_B_ID2
// id0 0 1
// id1 1 1
// id2 1 0
case SW_ID0:
result = !(PINC & (1<<INP_C_ID1));
break;
case SW_ID1:
result = (PINC & (1<<INP_C_ID1))&& (PINC & (1<<INP_C_ID2));
break;
case SW_ID2:
result = !(PINC & (1<<INP_C_ID2));
break;
#if 0
case SW_ID3:
result = (calibratedStick[POT1+EXTRA_3POS-1] < 0);
break;
case SW_ID4:
result = (calibratedStick[POT1+EXTRA_3POS-1] == 0);
break;
case SW_ID5:
result = (calibratedStick[POT1+EXTRA_3POS-1] > 0);
break;
#endif
case SW_GEA:
result = PING & (1<<INP_G_Gear);
break;
case SW_THR:
result = PING & (1<<INP_G_ThrCt);
break;
case SW_TRN:
result = PINB & (1<<INP_B_Trainer);
break;
default:
break;
}
return result;
}
FORCEINLINE void readKeysAndTrims()
{
/* Original keys were connected to PORTB as follows:
Bit Key
7 other use
6 LEFT
5 RIGHT
4 UP
3 DOWN
2 EXIT
1 MENU
0 other use
*/
uint8_t enuk = KEY_MENU;
keys[BTN_REa].input(~PIND & 0x20, BTN_REa);
keys[BTN_REb].input(~PIND & 0x10, BTN_REb);
uint8_t tin = ~PINL;
uint8_t in;
in = (tin & 0x0f) << 3;
in |= (tin & 0x30) >> 3;
for (int i=1; i<7; i++)
{
//INP_B_KEY_MEN 1 .. INP_B_KEY_LFT 6
keys[enuk].input(in & (1<<i),(EnumKeys)enuk);
++enuk;
}
// Trim switches ...
static const pm_uchar crossTrim[] PROGMEM ={
1<<INP_F_TRM_LH_DWN,
1<<INP_F_TRM_LH_UP,
1<<INP_F_TRM_LV_DWN,
1<<INP_F_TRM_LV_UP,
1<<INP_F_TRM_RV_DWN,
1<<INP_F_TRM_RV_UP,
1<<INP_F_TRM_RH_DWN,
1<<INP_F_TRM_RH_UP
};
in = ~PINF;
for (int i=0; i<8; i++) {
// INP_D_TRM_RH_UP 0 .. INP_D_TRM_LH_UP 7
keys[enuk].input(in & pgm_read_byte(crossTrim+i),(EnumKeys)enuk);
++enuk;
}
}
ISR(INT2_vect)
{
uint8_t input = (PIND & 0x0C);
if (input == 0 || input == 0x0C) incRotaryEncoder(0, -1);
}
ISR(INT3_vect)
{
uint8_t input = (PIND & 0x0C);
if (input == 0 || input == 0x0C) incRotaryEncoder(0, +1);
}
ISR(INT5_vect)
{
uint8_t input = (PINE & 0x60);
if (input == 0 || input == 0x60) incRotaryEncoder(1, +1);
}
ISR(INT6_vect)
{
uint8_t input = (PINE & 0x60);
if (input == 0 || input == 0x60) incRotaryEncoder(1, -1);
}
+193
View File
@@ -0,0 +1,193 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef board_mega2560_h
#define board_mega2560_h
#define GPIO_BUTTON_MENU pinl
#define GPIO_BUTTON_EXIT pinl
#define GPIO_BUTTON_RIGHT pinl
#define GPIO_BUTTON_LEFT pinl
#define GPIO_BUTTON_UP pinl
#define GPIO_BUTTON_DOWN pinl
#define PIN_BUTTON_MENU (1<<INP_L_KEY_MEN)
#define PIN_BUTTON_EXIT (1<<INP_L_KEY_EXT)
#define PIN_BUTTON_UP (1<<INP_L_KEY_UP)
#define PIN_BUTTON_DOWN (1<<INP_L_KEY_DWN)
#define PIN_BUTTON_RIGHT (1<<INP_L_KEY_RGT)
#define PIN_BUTTON_LEFT (1<<INP_L_KEY_LFT)
#define GPIO_TRIM_LH_L pinf
#define GPIO_TRIM_LV_DN pinf
#define GPIO_TRIM_RV_UP pinf
#define GPIO_TRIM_RH_L pinf
#define GPIO_TRIM_LH_R pinf
#define GPIO_TRIM_LV_UP pinf
#define GPIO_TRIM_RV_DN pinf
#define GPIO_TRIM_RH_R pinf
#define PIN_TRIM_LH_L (1<<INP_F_TRM_LH_DWN)
#define PIN_TRIM_LV_DN (1<<INP_F_TRM_LV_DWN)
#define PIN_TRIM_RV_UP (1<<INP_F_TRM_RV_UP)
#define PIN_TRIM_RH_L (1<<INP_F_TRM_RH_DWN)
#define PIN_TRIM_LH_R (1<<INP_F_TRM_LH_UP)
#define PIN_TRIM_LV_UP (1<<INP_F_TRM_LV_UP)
#define PIN_TRIM_RV_DN (1<<INP_F_TRM_RV_DWN)
#define PIN_TRIM_RH_R (1<<INP_F_TRM_RH_UP)
#define TIMER_16KHZ_VECT TIMER2_OVF_vect
#define COUNTER_16KHZ TCNT2
#define TIMER_10MS_VECT TIMER2_COMPA_vect
#define TIMER_10MS_COMPVAL OCR2A
#define PAUSE_10MS_INTERRUPT() TIMSK2 &= ~(1<<OCIE2A)
#define RESUME_10MS_INTERRUPT() TIMSK2 |= (1<<OCIE2A)
#define PAUSE_PPMIN_INTERRUPT() TIMSK3 &= ~(1<<ICIE3)
#define RESUME_PPMIN_INTERRUPT() TIMSK3 |= (1<<ICIE3)
#define SLAVE_MODE() (PING & (1<<INP_G_RF_POW))
#define JACK_PPM_OUT() PORTG |= (1<<OUT_G_SIM_CTL)
#define JACK_PPM_IN() PORTG &= ~(1<<OUT_G_SIM_CTL)
// SD driver
#if !defined(SIMU)
bool sdMounted();
void sdMountPoll();
void sdPoll10ms();
#define sdDone()
#define SD_IS_HC() (0)
#define SD_GET_BLOCKNR() (0)
#define SD_GET_SIZE_MB() (0)
#define SD_GET_SPEED() (0)
#endif
#define SPEAKER_ON TCCR0A |= (1 << COM0A0)
#define SPEAKER_OFF TCCR0A &= ~(1 << COM0A0)
#define __BACKLIGHT_ON PORTC |= (1 << OUT_C_LIGHT)
#define __BACKLIGHT_OFF PORTC &= ~(1 << OUT_C_LIGHT)
#define IS_BACKLIGHT_ON() (PORTC & (1<<OUT_C_LIGHT))
# define INP_L_SPARE6 7
# define INP_L_SPARE5 6
# define INP_L_KEY_EXT 5
# define INP_L_KEY_MEN 4
# define INP_L_KEY_LFT 3
# define INP_L_KEY_RGT 2
# define INP_L_KEY_UP 1
# define INP_L_KEY_DWN 0
# define INP_F_TRM_RH_UP 7
# define INP_F_TRM_RH_DWN 6
# define INP_F_TRM_RV_UP 5
# define INP_F_TRM_RV_DWN 4
# define INP_F_TRM_LV_UP 3
# define INP_F_TRM_LV_DWN 2
# define INP_F_TRM_LH_UP 1
# define INP_F_TRM_LH_DWN 0
# define INP_E_PPM_IN 7
# define INP_E_ROT_ENC_1_B 6
# define INP_E_ROT_ENC_1_A 5
# define INP_E_USB_D_PLS 4
# define OUT_E_BUZZER 3
# define INP_E_USB_D_NEG 2
# define INP_E_TELEM_RX 1
# define OUT_E_TELEM_TX 0
# define OUT_D_HAPTIC 7
# define INP_D_SPARE4 6
# define INP_D_ROT_ENC_2_PUSH 5
# define INP_D_ROT_ENC_1_PUSH 4
# define OUT_D_ROT_ENC_2_B 3
# define INP_D_ROT_ENC_2_A 2
# define INP_D_I2C_SCL 1
# define INP_D_I2C_SDA 0
# define INP_G_Gear 5
# define INP_G_ThrCt 2
# define OUT_G_SIM_CTL 4 //1 : phone-jack=ppm_in
# define INP_C_ID1 0
# define INP_G_RF_POW 1
# define INP_G_RuddDR 0
# define INP_C_AileDR 7
# define INP_C_ElevDR 6
# define OUT_C_LIGHT 2
# define OUT_B_Speaker 7
# define OUT_B_PPM 6
# define INP_B_Trainer 5
# define INP_C_ID2 1
#if defined(VOICE)
# define OUT_H_14DRESET 3
# define OUT_H_14DCLK 4
# define OUT_H_14DDATA 5
# define INP_H_14DBUSY 6
#endif
// Keys driver
#define TRIMS_PRESSED() (~PINJ)
#define KEYS_PRESSED() (~PINL) // used only for DBLKEYS code.
#define DBLKEYS_PRESSED_RGT_LFT(i) ((in & ((1<<INP_L_KEY_RGT) + (1<<INP_L_KEY_LFT))) == ((1<<INP_L_KEY_RGT) + (1<<INP_L_KEY_LFT)))
#define DBLKEYS_PRESSED_UP_DWN(i) ((in & ((1<<INP_L_KEY_UP) + (1<<INP_L_KEY_DWN))) == ((1<<INP_L_KEY_UP) + (1<<INP_L_KEY_DWN)))
#define DBLKEYS_PRESSED_RGT_UP(i) ((in & ((1<<INP_L_KEY_RGT) + (1<<INP_L_KEY_UP))) == ((1<<INP_L_KEY_RGT) + (1<<INP_L_KEY_UP)))
#define DBLKEYS_PRESSED_LFT_DWN(i) ((in & ((1<<INP_L_KEY_LFT) + (1<<INP_L_KEY_DWN))) == ((1<<INP_L_KEY_LFT) + (1<<INP_L_KEY_DWN)))
// LCD driver
#define PORTA_LCD_DAT PORTA
#define PORTC_LCD_CTRL PORTC
#define OUT_C_LCD_E 7
#define OUT_C_LCD_RnW 6
#define OUT_C_LCD_A0 5
#define OUT_C_LCD_RES 4
#define OUT_C_LCD_CS1 3
// Power driver
uint8_t pwrCheck();
void pwrOff();
#define UNEXPECTED_SHUTDOWN() ((mcusr & (1 << WDRF)) || g_eeGeneral.unexpectedShutdown)
// USB fake driver
#define usbPlugged() false
// Haptic driver
#define hapticOff() // TODO hapticOn() cleaner ...
#endif
+160
View File
@@ -0,0 +1,160 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _HAL_
#define _HAL_
/*
* GPIOS
*/
// Keys
#define GPIO_BUTTON_MENU GPIOL->IDR // only one port : to simplify ? //
#define GPIO_BUTTON_EXIT GPIOL->IDR
#define GPIO_BUTTON_RIGHT GPIOL->IDR
#define GPIO_BUTTON_LEFT GPIOL->IDR
#define GPIO_BUTTON_UP GPIOL->IDR
#define GPIO_BUTTON_DOWN GPIOL->IDR
#define PIN_BUTTON_MENU GPIO_Pin_4
#define PIN_BUTTON_EXIT GPIO_Pin_5
#define PIN_BUTTON_RIGHT GPIO_Pin_2
#define PIN_BUTTON_LEFT GPIO_Pin_3
#define PIN_BUTTON_UP GPIO_Pin_1
#define PIN_BUTTON_DOWN GPIO_Pin_0
// Trims
#define GPIO_TRIM_LH_L GPIOK->IDR // only one port : to simplify ? //
#define GPIO_TRIM_LH_R GPIOK->IDR
#define GPIO_TRIM_LV_DN GPIOK->IDR
#define GPIO_TRIM_LV_UP GPIOK->IDR
#define GPIO_TRIM_RH_L GPIOK->IDR
#define GPIO_TRIM_RH_R GPIOK->IDR
#define GPIO_TRIM_RV_DN GPIOK->IDR
#define GPIO_TRIM_RV_UP GPIOK->IDR
#define PIN_TRIM_LH_L GPIO_Pin_0
#define PIN_TRIM_LH_R GPIO_Pin_1
#define PIN_TRIM_LV_DN GPIO_Pin_2
#define PIN_TRIM_LV_UP GPIO_Pin_3
#define PIN_TRIM_RH_L GPIO_Pin_4
#define PIN_TRIM_RH_R GPIO_Pin_5
#define PIN_TRIM_RV_DN GPIO_Pin_5
#define PIN_TRIM_RV_UP GPIO_Pin_6
// Switchs
#define GPIO_PIN_SW_A GPIOC->IDR // A, B, C... to rename to ID1/2... ? //
#define GPIO_PIN_SW_B GPIOC->IDR
#define GPIO_PIN_SW_C GPIOD->IDR
#define GPIO_PIN_SW_D GPIOG->IDR
#define GPIO_PIN_SW_E GPIOG->IDR
#define GPIO_PIN_SW_F GPIOG->IDR
#define GPIO_PIN_SW_G GPIOL->IDR
#define GPIO_PIN_SW_H GPIOL->IDR
#define PIN_SW_A GPIO_Pin_1
#define PIN_SW_B GPIO_Pin_0
#define PIN_SW_C GPIO_Pin_7
#define PIN_SW_D GPIO_Pin_2
#define PIN_SW_E GPIO_Pin_1
#define PIN_SW_F GPIO_Pin_0
#define PIN_SW_G GPIO_Pin_6
#define PIN_SW_H GPIO_Pin_7
// Rotary encoders
#define GPIO_PIN_ROT_ENC_1_A GPIOH->IDR
#define GPIO_PIN_ROT_ENC_1_B GPIOJ->IDR
#define GPIO_PIN_ROT_ENC_1_PUSH GPIOJ->IDR
#define GPIO_PIN_ROT_ENC_2_A GPIOD->IDR
#define GPIO_PIN_ROT_ENC_2_B GPIOD->IDR
#define GPIO_PIN_ROT_ENC_2_PUSH GPIOH->IDR
#define PIN_ROT_ENC_1_A GPIO_Pin_1
#define PIN_ROT_ENC_1_B GPIO_Pin_0
#define PIN_ROT_ENC_1_PUSH GPIO_Pin_1
#define PIN_ROT_ENC_2_A GPIO_Pin_0
#define PIN_ROT_ENC_2_B GPIO_Pin_3
#define PIN_ROT_ENC_2_PUSH GPIO_Pin_2
// ADC
#define GPIO_PIN_ADC GPIOK->IDR
#define PIN_STK_J1 GPIO_Pin_0
#define PIN_STK_J2 GPIO_Pin_1
#define PIN_STK_J3 GPIO_Pin_2
#define PIN_STK_J4 GPIO_Pin_3
#define PIN_POT_1 GPIO_Pin_4
#define PIN_POT_2 GPIO_Pin_5
#define PIN_POT_3 GPIO_Pin_6
#define PIN_MVOLT GPIO_Pin_7
// Accessories
#define GPIO_PIN_PPM_IN GPIOB->IDR
#define GPIO_PIN_PPM_OUT GPIOB->IDR
#define GPIO_PIN_SIM_CTL GPIOB->IDR
#define GPIO_PIN_TELEM_RX GPIOE->IDR
#define GPIO_PIN_TELEM_TX GPIOE->IDR
#define GPIO_PIN_SPEAKER GPIOE->IDR
#define GPIO_PIN_BUZZER GPIOB->IDR
#define GPIO_PIN_JACK_PRES GPIOH->IDR
#define GPIO_PIN_HOLD_PWR GPIOH->IDR
#define PIN_PPM_IN GPIO_Pin_7
#define PIN_PPM_OUT GPIO_Pin_6
#define PIN_SIM_CTL GPIO_Pin_5
#define PIN_TELEM_RX GPIO_Pin_0
#define PIN_TELEM_TX GPIO_Pin_1
#define PIN_SPEAKER GPIO_Pin_3
#define PIN_BUZZER GPIO_Pin_4
#define PIN_JACK_PRES GPIO_Pin_5
#define PIN_HOLD_PWR GPIO_Pin_4
// LCD
#define GPIO_LCD_DAT GPIOA->IDR
#define GPIO_LCD_CTRL GPIOC->IDR
#define PIN_LCD_E GPIO_Pin_7
#define PIN_LCD_RnW GPIO_Pin_6
#define PIN_LCD_A0 GPIO_Pin_5
#define PIN_LCD_RES GPIO_Pin_4
#define PIN_LCD_CS1 GPIO_Pin_3
#define PIN_LCD_LIGHT GPIO_Pin_2
// SD
#define GPIO_SD GPIOB->IDR
#define PIN_SD_MISO GPIO_Pin_3
#define PIN_SD_MOSI GPIO_Pin_2
#define PIN_SD_SCK GPIO_Pin_1
#define PIN_SD_CS GPIO_Pin_0
#define SD_IS_HC() (0) // ?
#define SD_GET_BLOCKNR() (0) // ?
#define SD_GET_SIZE_MB() (0) // ?
#define SD_GET_SPEED() (0) // ?
#endif
@@ -0,0 +1,132 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "opentx.h"
#define delay_1us() _delay_us(1)
void delay_1_5us(int ms)
{
for(int i=0; i<ms; i++) delay_1us();
}
void lcdSendCtl(uint8_t val)
{
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
#ifdef LCD_MULTIPLEX
DDRA = 0xFF; // set LCD_DAT pins to output
#endif
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_A0);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
PORTA_LCD_DAT = val;
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_E);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0);
#ifdef LCD_MULTIPLEX
DDRA = 0x00; // set LCD_DAT pins to input
#endif
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS1);
}
#if defined(PCBSTD) && defined(VOICE)
volatile uint8_t LcdLock ;
#define LCD_LOCK() LcdLock = 1
#define LCD_UNLOCK() LcdLock = 0
#else
#define LCD_LOCK()
#define LCD_UNLOCK()
#endif
inline void lcdInit()
{
// /home/thus/txt/datasheets/lcd/KS0713.pdf
// ~/txt/flieger/ST7565RV17.pdf from http://www.glyn.de/content.asp?wdid=132&sid=
LCD_LOCK();
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES); //LCD_RES
delay_1us();
delay_1us();// f520 call 0xf4ce delay_1us() ; 0x0xf4ce
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); // f524 sbi 0x15, 2 IOADR-PORTC_LCD_CTRL; 21 1
delay_1_5us(1500);
lcdSendCtl(0xE2); //Initialize the internal functions
lcdSendCtl(0xAE); //DON = 0: display OFF
lcdSendCtl(0xA0); //ADC = 0: normal direction
lcdSendCtl(0xA6); //REV = 0: non-reverse display
lcdSendCtl(0xA4); //EON = 0: normal display. non-entire
lcdSendCtl(0xA2); //Select LCD bias=0
lcdSendCtl(0xC8); //SHL = 1: inverse direction
lcdSendCtl(0x2F); //Control power circuit operation VC=VR=VF=1
lcdSendCtl(0x25); //Select int resistance ratio R2 R1 R0 =5
lcdSendCtl(0x81); //Set reference voltage Mode
lcdSendCtl(0x22); //24 SV5 SV4 SV3 SV2 SV1 SV0 = 0x18
lcdSendCtl(0xAF); //DON = 1: display ON
lcdSendCtl(0x60); //sets the display start line to zero
g_eeGeneral.contrast = 0x22;
LCD_UNLOCK();
}
void lcdSetRefVolt(uint8_t val)
{
LCD_LOCK();
lcdSendCtl(0x81);
lcdSendCtl(val);
LCD_UNLOCK();
}
void lcdRefresh()
{
LCD_LOCK();
uint8_t *p=displayBuf;
for(uint8_t y=0; y < 8; y++) {
lcdSendCtl(0x01);
lcdSendCtl(0x10); //column addr 0
lcdSendCtl( y | 0xB0); //page addr y
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
#ifdef LCD_MULTIPLEX
DDRA = 0xFF; // set LCD_DAT pins to output
#endif
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
for (xcoord_t x=LCD_W; x>0; --x) {
PORTA_LCD_DAT = *p++;
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_E);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
}
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0);
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS1);
}
LCD_UNLOCK();
}
+95
View File
@@ -0,0 +1,95 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*--------------------------------------------------------------------------*/
/* RTC controls */
#include "../opentx.h"
#include "../FatFs/integer.h"
typedef struct {
WORD year; /* 2000..2099 */
BYTE month; /* 1..12 */
BYTE mday; /* 1.. 31 */
BYTE wday; /* 1..7 */
BYTE hour; /* 0..23 */
BYTE min; /* 0..59 */
BYTE sec; /* 0..59 */
} RTC;
void rtc_gettime(struct gtm * utm)
{
RTC rtc = {0,0,0,0,0,0,0};
// TODO g9x_rtc_gettime(&rtc);
utm->tm_year = rtc.year - 1900;
utm->tm_mon = rtc.month - 1;
utm->tm_mday = rtc.mday;
utm->tm_hour = rtc.hour;
utm->tm_min = rtc.min;
utm->tm_sec = rtc.sec;
utm->tm_wday = rtc.wday - 1;
}
void rtcSetTime(struct gtm * t)
{
g_rtcTime = gmktime(t); // update local timestamp and get wday calculated
g_ms100 = 0; // start of next second begins now
#if 0
RTC rtc;
rtc.year = t->tm_year + 1900;
rtc.month = t->tm_mon + 1;
rtc.mday = t->tm_mday;
rtc.hour = t->tm_hour;
rtc.min = t->tm_min;
rtc.sec = t->tm_sec;
rtc.wday = t->tm_wday + 1;
g9x_rtcSetTime(&rtc);
#endif
}
void rtcInit (void)
{
// TODO
struct gtm utm;
rtc_gettime(&utm);
g_rtcTime = gmktime(&utm);
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+256
View File
@@ -0,0 +1,256 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <string.h>
#include "Media.h"
#include "debug.h"
#include "board.h"
#include "../FatFs/diskio.h"
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
/// Number of SD Slots
#define NUM_SD_SLOTS 1
#define SD_BLOCK_SIZE 512
//------------------------------------------------------------------------------
/// Checks if the device is write protected.
/// \return 1 if protected.
//------------------------------------------------------------------------------
#if 0
static unsigned char CardIsProtected(unsigned char slot)
{
if (slot == 0) {
#ifdef BOARD_SD_PIN_WP
PIO_Configure(&pinMciWriteProtect, 1);
return (PIO_Get(&pinMciWriteProtect) != 0);
#else
return 0;
#endif
}
if (slot == 1) {
#ifdef BOARD_SD_MCI1_PIN_WP
PIO_Configure(&pinMciWriteProtect1, 1);
return (PIO_Get(&pinMciWriteProtect1) != 0);
#else
return 0;
#endif
}
return 0;
}
#endif
//------------------------------------------------------------------------------
/// Configure the PIO for SD
//------------------------------------------------------------------------------
#if 0
static void ConfigurePIO(unsigned char mciID)
{
#ifdef BOARD_SD_PINS
const Pin pinSd0[] = {BOARD_SD_PINS};
#endif
#ifdef BOARD_SD_MCI1_PINS
const Pin pinSd1[] = {BOARD_SD_MCI1_PINS};
#endif
if(mciID == 0) {
#ifdef BOARD_SD_PINS
PIO_Configure(pinSd0, PIO_LISTSIZE(pinSd0));
#endif
} else {
#ifdef BOARD_SD_MCI1_PINS
PIO_Configure(pinSd1, PIO_LISTSIZE(pinSd1));
#endif
}
}
#endif
//------------------------------------------------------------------------------
//! \brief Reads a specified amount of data from a SDCARD memory
//! \param media Pointer to a Media instance
//! \param address Address of the data to read
//! \param data Pointer to the buffer in which to store the retrieved
//! data
//! \param length Length of the buffer
//! \param callback Optional pointer to a callback function to invoke when
//! the operation is finished
//! \param argument Optional pointer to an argument for the callback
//! \return Operation result code
//------------------------------------------------------------------------------
static unsigned char MEDSdcard_Read(Media *media,
unsigned int address,
void *data,
unsigned int length,
MediaCallback callback,
void *argument)
{
TRACE_DEBUG("MEDSdcard_Read(address=%d length=%d)\n\r", address, length);
// Check that the media is ready
if (media->state != MED_STATE_READY) {
TRACE_INFO("Media busy\n\r");
return MED_STATUS_BUSY;
}
// Check that the data to read is not too big
if ((length + address) > media->size) {
TRACE_WARNING("MEDSdcard_Read: Data too big: %d, %d\n\r",
(int)length, (int)address);
return MED_STATUS_ERROR;
}
// Enter Busy state
media->state = MED_STATE_BUSY;
disk_read (0, data, address, length);
// Leave the Busy state
media->state = MED_STATE_READY;
// Invoke callback
if (callback != 0) {
callback(argument, MED_STATUS_SUCCESS, 0, 0);
}
return MED_STATUS_SUCCESS;
}
//------------------------------------------------------------------------------
//! \brief Writes data on a SDRAM media
//! \param media Pointer to a Media instance
//! \param address Address at which to write
//! \param data Pointer to the data to write
//! \param length Size of the data buffer
//! \param callback Optional pointer to a callback function to invoke when
//! the write operation terminates
//! \param argument Optional argument for the callback function
//! \return Operation result code
//! \see Media
//! \see MediaCallback
//------------------------------------------------------------------------------
static unsigned char MEDSdcard_Write(Media *media,
unsigned int address,
void *data,
unsigned int length,
MediaCallback callback,
void *argument)
{
TRACE_DEBUG("MEDSdcard_Write(address=%d length=%d)\n\r", address, length);
// Check that the media if ready
if (media->state != MED_STATE_READY) {
TRACE_WARNING("MEDSdcard_Write: Media is busy\n\r");
return MED_STATUS_BUSY;
}
// Check that the data to write is not too big
if ((length + address) > media->size) {
TRACE_WARNING("MEDSdcard_Write: Data too big\n\r");
return MED_STATUS_ERROR;
}
// Put the media in Busy state
media->state = MED_STATE_BUSY;
disk_write(0, data, address, length);
// Leave the Busy state
media->state = MED_STATE_READY;
// Invoke the callback if it exists
if (callback != 0) {
callback(argument, MED_STATUS_SUCCESS, 0, 0);
}
return MED_STATUS_SUCCESS;
}
//------------------------------------------------------------------------------
/// Initializes a Media instance and the associated physical interface
/// \param media Pointer to the Media instance to initialize
/// \return 1 if success.
//------------------------------------------------------------------------------
unsigned char MEDSdcard_Initialize(Media *media, unsigned char mciID)
{
TRACE_INFO("MEDSdcard init\n\r");
// Initialize SDcard
//--------------------------------------------------------------------------
if ( !SD_CARD_PRESENT( ) )
{
return 0;
}
media->write = MEDSdcard_Write;
media->read = MEDSdcard_Read;
media->lock = 0;
media->unlock = 0;
media->handler = 0;
media->flush = 0;
media->blockSize = SD_BLOCK_SIZE;
media->baseAddress = 0;
media->size = SD_GET_BLOCKNR();
media->mappedRD = 0;
media->mappedWR = 0;
media->protected = 0;
media->removable = 1;
media->state = MED_STATE_READY;
media->transfer.data = 0;
media->transfer.address = 0;
media->transfer.length = 0;
media->transfer.callback = 0;
media->transfer.argument = 0;
return 1;
}
+288
View File
@@ -0,0 +1,288 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
/// !Purpose
///
/// Generic Media type, which provides transparent access to all types of
/// memories.
///
/// \note The physical or HW related media operations (physical device
/// connection & protection detecting, PIO configurations and interface
/// driver initialization) are excluded.
///
/// !Usage
/// -# Do PIO initialization for peripheral interfaces.
/// -# Initialize peripheral interface driver & device driver.
/// -# Initialize specific media interface and link to this initialized driver.
///
//------------------------------------------------------------------------------
#ifndef MEDIA_H
#define MEDIA_H
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//! \brief Operation result code returned by media methods
#define MED_STATUS_SUCCESS 0x00
#define MED_STATUS_ERROR 0x01
#define MED_STATUS_BUSY 0x02
#define MED_STATUS_PROTECTED 0x04
//! \brief Media statuses
#define MED_STATE_READY 0x00 /// Media is ready for access
#define MED_STATE_BUSY 0x01 /// Media is busy
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
typedef struct _Media Media;
typedef void (*MediaCallback)(void *argument,
unsigned char status,
unsigned int transferred,
unsigned int remaining);
typedef unsigned char (*Media_write)(Media *media,
unsigned int address,
void *data,
unsigned int length,
MediaCallback callback,
void *argument);
typedef unsigned char (*Media_read)(Media *media,
unsigned int address,
void *data,
unsigned int length,
MediaCallback callback,
void *argument);
typedef unsigned char (*Media_cancelIo)(Media *media);
typedef unsigned char (*Media_lock)(Media *media,
unsigned int start,
unsigned int end,
unsigned int *pActualStart,
unsigned int *pActualEnd);
typedef unsigned char (*Media_unlock)(Media *media,
unsigned int start,
unsigned int end,
unsigned int *pActualStart,
unsigned int *pActualEnd);
typedef unsigned char (*Media_ioctl)(Media *media,
unsigned char ctrl,
void *buff);
typedef unsigned char (*Media_flush)(Media *media);
typedef void (*Media_handler)(Media *media);
//! \brief Media transfer
//! \see TransferCallback
typedef struct {
void *data; //!< Pointer to the data buffer
unsigned int address; //!< Address where to read/write the data
unsigned int length; //!< Size of the data to read/write
MediaCallback callback; //!< Callback to invoke when the transfer done
void *argument; //!< Callback argument
} MEDTransfer;
//! \brief Media object
//! \see MEDTransfer
struct _Media {
Media_write write; //!< Write method
Media_read read; //!< Read method
Media_cancelIo cancelIo; //!< Cancel pending IO method
Media_lock lock; //!< lock method if possible
Media_unlock unlock; //!< unlock method if possible
Media_flush flush; //!< Flush method
Media_handler handler; //!< Interrupt handler
unsigned int blockSize; //!< Block size in bytes (1, 512, 1K, 2K ...)
unsigned int baseAddress; //!< Base address of media in number of blocks
unsigned int size; //!< Size of media in number of blocks
MEDTransfer transfer; //!< Current transfer operation
void *interface; //!< Pointer to the physical interface used
unsigned char bReserved:4,
mappedRD:1, //!< Mapped to memory space to read
mappedWR:1, //!< Mapped to memory space to write
#ifdef __cplusplus
protectd:1, //!< Protected media?
#else
protected:1, //!< Protected media?
#endif
removable:1; //!< Removable/Fixed media?
unsigned char state; //!< Status of media
unsigned short reserved;
};
/// Available medias.
extern Media medias[];
/// Number of medias which are effectively used.
/// Defined by Media, shared usage by USB MSD & FS ...
extern unsigned int numMedias;
//------------------------------------------------------------------------------
// Inline Functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \brief Writes data on a media
//! \param media Pointer to a Media instance
//! \param address Address at which to write
//! \param data Pointer to the data to write
//! \param length Size of the data buffer
//! \param callback Optional pointer to a callback function to invoke when
//! the write operation terminates
//! \param argument Optional argument for the callback function
//! \return Operation result code
//! \see TransferCallback
//------------------------------------------------------------------------------
static inline unsigned char MED_Write(Media *media,
unsigned int address,
void *data,
unsigned int length,
MediaCallback callback,
void *argument)
{
return media->write(media, address, data, length, callback, argument);
}
//------------------------------------------------------------------------------
//! \brief Reads a specified amount of data from a media
//! \param media Pointer to a Media instance
//! \param address Address of the data to read
//! \param data Pointer to the buffer in which to store the retrieved
//! data
//! \param length Length of the buffer
//! \param callback Optional pointer to a callback function to invoke when
//! the operation is finished
//! \param argument Optional pointer to an argument for the callback
//! \return Operation result code
//! \see TransferCallback
//------------------------------------------------------------------------------
static inline unsigned char MED_Read(Media *media,
unsigned int address,
void *data,
unsigned int length,
MediaCallback callback,
void *argument)
{
return media->read(media, address, data, length, callback, argument);
}
//------------------------------------------------------------------------------
//! \brief Locks all the regions in the given address range.
//! \param media Pointer to a Media instance
/// \param start Start address of lock range.
/// \param end End address of lock range.
/// \param pActualStart Start address of the actual lock range (optional).
/// \param pActualEnd End address of the actual lock range (optional).
/// \return 0 if successful; otherwise returns an error code.
//------------------------------------------------------------------------------
static inline unsigned char MED_Lock(Media *media,
unsigned int start,
unsigned int end,
unsigned int *pActualStart,
unsigned int *pActualEnd)
{
if( media->lock ) {
return media->lock(media, start, end, pActualStart, pActualEnd);
}
else {
return MED_STATUS_SUCCESS;
}
}
//------------------------------------------------------------------------------
//! \brief Unlocks all the regions in the given address range
//! \param media Pointer to a Media instance
/// \param start Start address of unlock range.
/// \param end End address of unlock range.
/// \param pActualStart Start address of the actual unlock range (optional).
/// \param pActualEnd End address of the actual unlock range (optional).
/// \return 0 if successful; otherwise returns an error code.
//------------------------------------------------------------------------------
static inline unsigned char MED_Unlock(Media *media,
unsigned int start,
unsigned int end,
unsigned int *pActualStart,
unsigned int *pActualEnd)
{
if( media->unlock ) {
return media->unlock(media, start, end, pActualStart, pActualEnd);
}
else {
return MED_STATUS_SUCCESS;
}
}
//------------------------------------------------------------------------------
//! \brief
//! \param media Pointer to the Media instance to use
//------------------------------------------------------------------------------
static inline unsigned char MED_Flush(Media *media)
{
if (media->flush) {
return media->flush(media);
}
else {
return MED_STATUS_SUCCESS;
}
}
//------------------------------------------------------------------------------
//! \brief Invokes the interrupt handler of the specified media
//! \param media Pointer to the Media instance to use
//------------------------------------------------------------------------------
static inline void MED_Handler(Media *media)
{
if (media->handler) {
media->handler(media);
}
}
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void MED_HandleAll(Media *medias, unsigned char numMedias);
#endif // _MEDIA_H
+129
View File
@@ -0,0 +1,129 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../opentx.h"
volatile uint16_t Analog_values[NUMBER_ANALOG];
#if defined(TARANIS_STICKS)
const char ana_direction[NUMBER_ANALOG] = {1, 1, 0, 1 ,0 ,1 ,0, 0, 0};
#endif
// Settings for mode register ADC_MR
// USEQ off - silicon problem, doesn't work
// TRANSFER = 1
// TRACKTIM = 4 (5 clock periods)
// ANACH = 0
// SETTLING = 1 (not used if ANACH = 0)
// STARTUP = 1 (8 clock periods)
// PRESCAL = 3.6 MHz clock (between 1 and 20MHz)
// FREERUN = 0
// FWUP = 0
// SLEEP = 0
// LOWRES = 0
// TRGSEL = 0
// TRGEN = 0 (software trigger only)
void adcInit()
{
register Adc *padc ;
register uint32_t timer ;
timer = ( Master_frequency / (3600000*2) ) << 8 ;
// Enable peripheral clock ADC = bit 29
PMC->PMC_PCER0 |= 0x20000000L ; // Enable peripheral clock to ADC
padc = ADC ;
padc->ADC_MR = 0x14110000 | timer ; // 0001 0100 0001 0001 xxxx xxxx 0000 0000
padc->ADC_ACR = ADC_ACR_TSON ; // Turn on temp sensor
#if defined(REVA)
padc->ADC_CHER = 0x0000E23E ; // channels 1,2,3,4,5,9,13,14,15
#else
padc->ADC_CHER = 0x0000E33E ; // channels 1,2,3,4,5,8,9,13,14,15
#endif
padc->ADC_CGR = 0 ; // Gain = 1, all channels
padc->ADC_COR = 0 ; // Single ended, 0 offset, all channels
}
// Read 8 (9 for REVB) ADC channels
// Documented bug, must do them 1 by 1
void adcRead()
{
register Adc *padc;
register uint32_t y;
register uint32_t x;
padc = ADC;
y = padc->ADC_ISR; // Clear EOC flags
for (y = NUMBER_ANALOG+1; --y > 0;) {
padc->ADC_CR = 2; // Start conversion
x = 0;
while ((padc->ADC_ISR & 0x01000000) == 0) {
// wait for DRDY flag
if (++x > 1000000) {
break; // Software timeout
}
}
x = padc->ADC_LCDR; // Clear DRSY flag
}
// Next bit may be done using the PDC
Analog_values[0] = ADC->ADC_CDR1;
Analog_values[1] = ADC->ADC_CDR2;
Analog_values[2] = ADC->ADC_CDR3;
Analog_values[3] = ADC->ADC_CDR4;
Analog_values[4] = ADC->ADC_CDR5;
Analog_values[5] = ADC->ADC_CDR9;
Analog_values[6] = ADC->ADC_CDR13;
Analog_values[7] = ADC->ADC_CDR14;
#if !defined(REVA)
Analog_values[8] = ADC->ADC_CDR8 ;
#endif
temperature = (((int32_t)temperature * 7) + ((((int32_t)ADC->ADC_CDR15 - 838) * 621) >> 11)) >> 3; // Filter it
if (get_tmr10ms() >= 100 && temperature > maxTemperature) {
maxTemperature = temperature;
}
// adc direction correct
#if defined(TARANIS_STICKS)
uint32_t i ;
for (i=0; i<NUMBER_ANALOG; i++) {
if (ana_direction[i]) {
Analog_values[i] = 4096-Analog_values[i];
}
}
#endif
}
+177
View File
@@ -0,0 +1,177 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../../opentx.h"
void setSampleRate(uint32_t frequency)
{
register Tc *ptc ;
register uint32_t timer ;
timer = Master_frequency / (8 * frequency) ; // MCK/8 and 100 000 Hz
if (timer > 65535)
timer = 65535 ;
if (timer < 2)
timer = 2 ;
ptc = TC0 ; // Tc block 0 (TC0-2)
ptc->TC_CHANNEL[1].TC_CCR = TC_CCR0_CLKDIS ; // Stop clock
ptc->TC_CHANNEL[1].TC_RC = timer ; // 100 000 Hz
ptc->TC_CHANNEL[1].TC_RA = timer >> 1 ;
ptc->TC_CHANNEL[1].TC_CCR = 5 ; // Enable clock and trigger it (may only need trigger)
}
// Start TIMER1 at 100000Hz, used for DACC trigger
void dacTimerStart()
{
register Tc *ptc ;
register uint32_t timer ;
// Enable peripheral clock TC0 = bit 23 thru TC5 = bit 28
PMC->PMC_PCER0 |= 0x01000000L ; // Enable peripheral clock to TC1
timer = Master_frequency / 800000 ; // MCK/8 and 100 000 Hz
ptc = TC0 ; // Tc block 0 (TC0-2)
ptc->TC_BCR = 0 ; // No sync
ptc->TC_BMR = 0 ;
ptc->TC_CHANNEL[1].TC_CMR = 0x00008000 ; // Waveform mode
ptc->TC_CHANNEL[1].TC_RC = timer ; // 100 000 Hz
ptc->TC_CHANNEL[1].TC_RA = timer >> 1 ;
ptc->TC_CHANNEL[1].TC_CMR = 0x0009C001 ; // 0000 0000 0000 1001 1100 0000 0000 0001
// MCK/8, set @ RA, Clear @ RC waveform
ptc->TC_CHANNEL[1].TC_CCR = 5 ; // Enable clock and trigger it (may only need trigger)
// Sound_g.Frequency = 1000 ;
}
// Configure DAC0 (or DAC1 for REVA)
// Not sure why PB14 has not be allocated to the DAC, although it is an EXTRA function
// So maybe it is automatically done
void dacInit()
{
dacTimerStart() ;
PMC->PMC_PCER0 |= 0x40000000L ; // Enable peripheral clock to DAC
register Dacc *dacptr = DACC;
#if defined(REVA)
dacptr->DACC_MR = 0x0B010215L ; // 0000 1011 0000 0001 0000 0010 0001 0101
dacptr->DACC_CHER = 2 ; // Enable channel 1
#else
dacptr->DACC_MR = 0x0B000215L ; // 0000 1011 0000 0001 0000 0010 0001 0101
dacptr->DACC_CHER = 1 ; // Enable channel 0
#endif
dacptr->DACC_CDR = 2048 ; // Half amplitude
dacptr->DACC_PTCR = DACC_PTCR_TXTEN ;
NVIC_EnableIRQ(DACC_IRQn) ;
}
bool dacQueue(AudioBuffer *buffer)
{
dacStart();
return false;
}
extern "C" void DAC_IRQHandler()
{
AudioBuffer *nextBuffer = audioQueue.getNextFilledBuffer();
if (nextBuffer) {
DACC->DACC_TNPR = CONVERT_PTR(nextBuffer->data);
DACC->DACC_TNCR = nextBuffer->size/2;
}
else {
dacStop();
}
}
// Sound routines
void audioInit()
{
register Pio *pioptr ;
dacInit() ;
pioptr = PIOA ;
#if defined(REVA)
pioptr->PIO_CODR = 0x00010000L ; // Set bit A16 OFF
pioptr->PIO_PER = 0x00010000L ; // Enable bit A16 (Stock buzzer)
pioptr->PIO_OER = 0x00010000L ; // Set bit A16 as output
#else
pioptr->PIO_CODR = 0x02000000L ; // Set bit A25 OFF
pioptr->PIO_PER = 0x02000000L ; // Enable bit A25 (Stock buzzer)
pioptr->PIO_OER = 0x02000000L ; // Set bit A25 as output
#endif
}
void audioEnd()
{
DACC->DACC_IDR = DACC_IDR_ENDTX ;
DACC->DACC_IDR = DACC_IDR_TXBUFE ;
NVIC_DisableIRQ(DACC_IRQn) ;
TWI0->TWI_IDR = TWI_IDR_TXCOMP ;
NVIC_DisableIRQ(TWI0_IRQn) ;
PMC->PMC_PCER0 &= ~0x00080000L ; // Disable peripheral clock to TWI0
PMC->PMC_PCER0 &= ~0x40000000L ; // Disable peripheral clock to DAC
}
static const int8_t volumeScale[VOLUME_LEVEL_MAX+1] =
{
0, 2, 4, 6, 8, 10, 13, 17, 22, 27, 33, 40,
64, 82, 96, 105, 112, 117, 120, 122, 124, 125, 126, 127
} ;
void setVolume(uint8_t volume)
{
coprocVolumeRequired = volumeScale[min<uint8_t>(volume, VOLUME_LEVEL_MAX)];
__disable_irq() ;
coprocCheck() ;
__enable_irq() ;
}
#if 0
void getVolume()
{
coprocVolumeReadPending = 1 ;
__disable_irq() ;
coprocCheck() ;
__enable_irq() ;
}
#endif
+60
View File
@@ -0,0 +1,60 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef audio_driver_h
#define audio_driver_h
void audioInit( void ) ;
void audioEnd( void ) ;
void setSampleRate( uint32_t frequency ) ;
inline void dacStart()
{
PMC->PMC_PCER0 |= 0x40000000L ; // Enable peripheral clock to DAC
DACC->DACC_IER = DACC_IER_ENDTX ;
}
inline void dacStop()
{
DACC->DACC_IDR = DACC_IDR_ENDTX ; // Disable interrupt
}
#define VOLUME_LEVEL_MAX 23
#define VOLUME_LEVEL_DEF 12
void setVolume(uint8_t volume);
#endif
+292
View File
@@ -0,0 +1,292 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../opentx.h"
void btSetBaudrate(uint32_t index)
{
uint32_t baudrate = (index==0 ? 115200 : (index==1 ? 9600 : 19200));
UART3_Configure(baudrate, Master_frequency);
}
void btInit()
{
btSetBaudrate(g_eeGeneral.btBaudrate);
}
OS_FlagID btFlag;
Fifo<32> btTxFifo;
Fifo<32> btRxFifo;
struct t_serial_tx btTx ;
uint8_t btTxBuffer[32] ;
struct t_serial_tx * Current_bt ;
uint32_t txPdcBt(struct t_serial_tx *data)
{
#ifndef SIMU
Uart *pUart = BT_USART ;
if (pUart->UART_TNCR == 0) {
Current_bt = data;
data->ready = 1;
pUart->UART_TPR = (uint32_t) data->buffer;
pUart->UART_TCR = data->size;
pUart->UART_PTCR = US_PTCR_TXTEN;
pUart->UART_IER = UART_IER_TXBUFE;
NVIC_EnableIRQ(UART1_IRQn);
return 1; // Sent OK
}
#endif
return 0 ; // Busy
}
extern "C" void UART1_IRQHandler()
{
Uart *pUart = BT_USART ;
if ( pUart->UART_SR & UART_SR_TXBUFE ) {
pUart->UART_IDR = UART_IDR_TXBUFE ;
pUart->UART_PTCR = US_PTCR_TXTDIS ;
Current_bt->ready = 0 ;
}
if ( pUart->UART_SR & UART_SR_RXRDY ) {
btRxFifo.push(pUart->UART_RHR);
}
}
uint16_t rxBtuart()
{
uint8_t result;
if (!btRxFifo.pop(result))
return 0xffff;
return result;
}
void btSendBuffer()
{
btTx.buffer = btTxBuffer;
txPdcBt(&btTx);
while (btTx.ready == 1) {
CoTickDelay(1); // 2ms for now
}
btTx.size = 0;
}
#define BT_POLL_TIMEOUT 500
uint32_t btChangeBaudrate( uint32_t baudIndex )
{
uint16_t x ;
uint32_t y ;
uint16_t rxchar ;
x = 4 ; // 9600
if ( baudIndex == 0 )
{
x = 8 ; // 115200
}
else if ( baudIndex == 2 )
{
x = 5 ; // 19200
}
btTxBuffer[0] = 'A' ;
btTxBuffer[1] = 'T' ;
btTxBuffer[2] = '+' ;
btTxBuffer[3] = 'B' ;
btTxBuffer[4] = 'A' ;
btTxBuffer[5] = 'U' ;
btTxBuffer[6] = 'D' ;
btTxBuffer[7] = '0' + x ;
btTx.size = 8 ;
btSendBuffer() ;
x = 'O' ;
for( y = 0 ; y < BT_POLL_TIMEOUT ; y += 1 ) {
if ( ( rxchar = rxBtuart() ) != 0xFFFF ) {
if ( rxchar == x ) {
if ( x == 'O' ) {
x = 'K' ;
}
else {
break ; // Found "OK"
}
}
}
else {
CoTickDelay(1) ; // 2mS
}
}
if ( y < BT_POLL_TIMEOUT ) {
return 1 ;
}
else {
return 0 ;
}
}
uint32_t btPollDevice()
{
uint16_t x ;
uint32_t y ;
uint16_t rxchar ;
x = 'O' ;
btTxBuffer[0] = 'A' ;
btTxBuffer[1] = 'T' ;
btTx.size = 2 ;
btSendBuffer() ;
for( y = 0 ; y < BT_POLL_TIMEOUT ; y++) {
if ( ( rxchar = rxBtuart() ) != 0xFFFF ) {
if ( rxchar == x ) {
if ( x == 'O' ) {
x = 'K' ;
}
else {
break ; // Found "OK"
}
}
}
else {
CoTickDelay(1) ; // 2mS
}
}
if ( y < BT_POLL_TIMEOUT ) {
return 1 ;
}
else {
return 0 ;
}
}
/*
Commands to BT module
AT+VERSION Returns the software version of the module
AT+BAUDx Sets the baud rate of the module:
1 1200
2 2400
3 4800
4 9600 (Default)
5 19200
6 38400
7 57600
8 115200
9 230400
AT+NAME<name here> Sets the name of the module
Any name can be specified up to 20 characters
AT+PINxxxx Sets the pairing password of the device
Any 4 digit number can be used, the default pincode is 1234
AT+PN Sets the parity of the module
So we could send AT+VERSION at different baudrates until we get a response
Then we can change the baudrate to the required value.
Or maybe just AT and get OK back
*/
uint32_t btStatus;
void btTask(void* pdata)
{
uint8_t byte;
btFlag = CoCreateFlag(true, false);
btTx.size = 0;
// Look for BT module baudrate, try 115200, and 9600
// Already initialised to g_eeGeneral.bt_baudrate
// 0 : 115200, 1 : 9600, 2 : 19200
uint32_t x = g_eeGeneral.btBaudrate;
btStatus = btPollDevice() ; // Do we get a response?
for (int y=0; y<2; y++) {
if (btStatus == 0) {
x += 1 ;
if (x > 2) {
x = 0 ;
}
btSetBaudrate(x) ;
CoTickDelay(1) ; // 2mS
btStatus = btPollDevice() ; // Do we get a response?
}
}
if (btStatus) {
btStatus = x + 1 ;
if ( x != g_eeGeneral.btBaudrate ) {
x = g_eeGeneral.btBaudrate ;
// Need to change Bt Baudrate
btChangeBaudrate( x ) ;
btStatus += (x+1) * 10 ;
btSetBaudrate( x ) ;
}
}
else {
btInit();
}
CoTickDelay(1) ;
btPollDevice(); // Do we get a response?
while (1) {
uint32_t x = CoWaitForSingleFlag(btFlag, 10); // Wait for data in Fifo
if (x == E_OK) {
// We have some data in the Fifo
while (btTxFifo.pop(byte)) {
btTxBuffer[btTx.size++] = byte;
if (btTx.size > 31) {
btSendBuffer();
}
}
}
else if (btTx.size) {
btSendBuffer();
}
}
}
void btPushByte(uint8_t data)
{
btTxFifo.push(data);
CoSetFlag(btFlag); // Tell the Bt task something to do
}
+651
View File
@@ -0,0 +1,651 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
// TODO merge this file with board_sky9x.h
#ifndef board_h
#define board_h
#include <stdint.h>
#include "chip.h"
#if defined(REVA)
#include "AT91SAM3S2.h"
#else
#include "AT91SAM3S4.h"
#endif
#if !defined(SIMU)
#include "core_cm3.h"
#endif
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \par
/// This page lists several definition related to the board description.
///
/// Definitions
/// - BOARD_NAME
/// Name of the board.
#define BOARD_NAME "AT91SAM3S-EK"
/// Board definition.
#define at91sam3sek
/// Family definition (already defined).
#define at91sam3s
/// Core definition
#define cortexm3
// TODO remove these definitions
//#define BOARD_REV_A
#define BOARD_REV_B
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \par sam3s_ek_opfreq "SAM3S-EK - Operating frequencies"
/// This page lists several definition related to the board operating frequency
/// (when using the initialization done by board_lowlevel.c).
///
/// !Definitions
/// - BOARD_MAINOSC
/// - BOARD_MCK
/// Frequency of the board main oscillator.
#define BOARD_MAINOSC 12000000
/// Master clock frequency (when using board_lowlevel.c).
// #define BOARD_MCK 64000000
//------------------------------------------------------------------------------
// ADC
//------------------------------------------------------------------------------
/// Startup time max, return from Idle mode (in µs)
#define ADC_STARTUP_TIME_MAX 15
/// Track and hold Acquisition Time min (in ns)
#define ADC_TRACK_HOLD_TIME_MIN 1200
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// USB attributes configuration descriptor (bus or self powered, remote wakeup)
//#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_SELFPOWERED_RWAKEUP
#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_SELFPOWERED_NORWAKEUP
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \par sam3s_ek_piodef "SAM3S-EK - PIO definitions"
/// This pages lists all the pio definitions contained in board.h. The constants
/// are named using the following convention: PIN_* for a constant which defines
/// a single Pin instance (but may include several PIOs sharing the same
/// controller), and PINS_* for a list of Pin instances.
///
/// !ADC
/// - PIN_ADC0_AD0
/// - PIN_ADC0_AD1
/// - PIN_ADC0_AD2
/// - PIN_ADC0_AD3
/// - PIN_ADC0_AD4
/// - PIN_ADC0_AD5
/// - PIN_ADC0_AD6
/// - PIN_ADC0_AD7
/// - PINS_ADC0
///
/// !UART
/// - PINS_UART
///
/// !EBI
/// - PIN_EBI_DATA_BUS
/// - PIN_EBI_NCS0
/// - PIN_EBI_NRD
/// - PIN_EBI_NWE
/// - PIN_EBI_ADDR_BUS
/// - PIN_EBI_PSRAM_NBS
/// - PIN_EBI_A1
/// - PIN_EBI_LCD_RS
///
/// !LEDs
/// - PIN_LED_0
/// - PIN_LED_1
/// - PIN_LED_2
/// - PINS_LEDS
///
/// !MCI
/// - PINS_MCI
///
/// !Push buttons
/// - PIN_PUSHBUTTON_1
/// - PIN_PUSHBUTTON_2
/// - PINS_PUSHBUTTONS
/// - PUSHBUTTON_BP1
/// - PUSHBUTTON_BP2
///
/// !PWMC
/// - PIN_PWMC_PWMH0
/// - PIN_PWMC_PWML0
/// - PIN_PWMC_PWMH1
/// - PIN_PWMC_PWML1
/// - PIN_PWMC_PWMH2
/// - PIN_PWMC_PWML2
/// - PIN_PWMC_PWMH3
/// - PIN_PWMC_PWML3
/// - PIN_PWM_LED0
/// - PIN_PWM_LED1
/// - PIN_PWM_LED2
/// - CHANNEL_PWM_LED0
/// - CHANNEL_PWM_LED1
/// - CHANNEL_PWM_LED2
///
/// !SPI
/// - PIN_SPI_MISO
/// - PIN_SPI_MOSI
/// - PIN_SPI_SPCK
/// - PINS_SPI
/// - PIN_SPI_NPCS0_PA11
///
/// ! SSC
/// - PIN_SSC_TD
/// - PIN_SSC_TK
/// - PIN_SSC_TF
/// - PINS_SSC_CODEC
///
/// ! PCK0
/// - PIN_PCK0
///
/// !TWI
/// - PIN_TWI_TWD0
/// - PIN_TWI_TWCK0
/// - PINS_TWI
///
/// !USART0
/// - PIN_USART0_RXD
/// - PIN_USART0_TXD
/// - PIN_USART0_CTS
/// - PIN_USART0_RTS
/// - PIN_USART0_SCK
///
/// !USB
/// - PIN_USB_PULLUP
///
/// ADC_AD0 pin definition.
#define PIN_ADC0_AD0 {1 << 21, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
/// ADC_AD1 pin definition.
#define PIN_ADC0_AD1 {1 << 30, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
/// ADC_AD2 pin definition.
#define PIN_ADC0_AD2 {1 << 3, PIOB, ID_PIOB, PIO_INPUT, PIO_DEFAULT}
/// ADC_AD3 pin definition.
#define PIN_ADC0_AD3 {1 << 4, PIOB, ID_PIOB, PIO_INPUT, PIO_DEFAULT}
/// ADC_AD4 pin definition.
#define PIN_ADC0_AD4 {1 << 15, PIOC, ID_PIOC, PIO_INPUT, PIO_DEFAULT}
/// ADC_AD5 pin definition.
#define PIN_ADC0_AD5 {1 << 16, PIOC, ID_PIOC, PIO_INPUT, PIO_DEFAULT}
/// ADC_AD6 pin definition.
#define PIN_ADC0_AD6 {1 << 17, PIOC, ID_PIOC, PIO_INPUT, PIO_DEFAULT}
/// ADC_AD7 pin definition.
#define PIN_ADC0_AD7 {1 << 18, PIOC, ID_PIOC, PIO_INPUT, PIO_DEFAULT}
/// Pins ADC
#define PINS_ADC PIN_ADC0_AD0, PIN_ADC0_AD1, PIN_ADC0_AD2, PIN_ADC0_AD3, PIN_ADC0_AD4, PIN_ADC0_AD5, PIN_ADC0_AD6, PIN_ADC0_AD7
/** UART pins (UTXD0 and URXD0) definitions, PA9,10. */
#define PINS_UART {0x00000600, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/// EBI
#define PIN_EBI_DATA_BUS {0xFF, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_PULLUP}
#define PIN_EBI_NRD {1 << 11, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_PULLUP}
#define PIN_EBI_NWE {1 << 8, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_PULLUP}
#define PIN_EBI_NCS0 {1 << 20, PIOB, ID_PIOB, PIO_PERIPH_A, PIO_PULLUP}
#define PIN_EBI_PSRAM_ADDR_BUS {0x3f00fff, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_PULLUP}
#define PIN_EBI_PSRAM_NBS {1 << 7, PIOB, ID_PIOB, PIO_PERIPH_B, PIO_PULLUP}, \
{1 << 15, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_PULLUP}
#define PIN_EBI_A1 {1 << 19, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_PULLUP}
#define PIN_EBI_NCS1 {1 << 15, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_PULLUP} /* LCD CS pin */
#define PIN_EBI_LCD_RS {1 << 19, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_PULLUP} /* LCD RS pin */
#ifdef BOARD_REV_A
/** LED #0 pin definition. */
#define PIN_LED_0 {1 << 20, PIOC, ID_PIOC, PIO_OUTPUT_1, PIO_DEFAULT}
/** LED #1 pin definition. */
#define PIN_LED_1 {1 << 21, PIOC, ID_PIOC, PIO_OUTPUT_1, PIO_DEFAULT}
/** LED #2 pin definition. */
#define PIN_LED_2 {1 << 22, PIOC, ID_PIOC, PIO_OUTPUT_1, PIO_DEFAULT}
#endif
#ifdef BOARD_REV_B
/** LED #0 pin definition. */
#define PIN_LED_0 {1 << 19, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/** LED #1 pin definition. */
#define PIN_LED_1 {1 << 20, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
/** LED #2 pin definition. */
#define PIN_LED_2 {1 << 20, PIOC, ID_PIOC, PIO_OUTPUT_1, PIO_DEFAULT}
#endif
/** List of all LEDs definitions. */
#define PINS_LEDS PIN_LED_0, PIN_LED_1, PIN_LED_2
/** MCI pins definition. */
#define PINS_MCI {0x3fUL << 26, PIOA, ID_PIOA, PIO_PERIPH_C, PIO_PULLUP}
/** MCI pin Card Detect. */
#define PIN_MCI_CD {PIO_PB7, PIOB, ID_PIOB, PIO_INPUT, PIO_PULLUP}
/** Push button #0 definition. Attributes = pull-up + debounce + interrupt on rising edge. */
#define PIN_PUSHBUTTON_1 {1 << 3, PIOB, ID_PIOB, PIO_INPUT, PIO_PULLUP | PIO_DEBOUNCE}
/** Push button #1 definition. Attributes = pull-up + debounce + interrupt on falling edge. */
#define PIN_PUSHBUTTON_2 {1 << 12, PIOC, ID_PIOC, PIO_INPUT, PIO_PULLUP | PIO_DEBOUNCE}
/** List of all push button definitions. */
#define PINS_PUSHBUTTONS PIN_PUSHBUTTON_1, PIN_PUSHBUTTON_2
/** Push button #1 index. */
#define PUSHBUTTON_BP1 0
/** Push button #2 index. */
#define PUSHBUTTON_BP2 1
/// Simulated joystick LEFT index.
#define JOYSTICK_LEFT 0
/// Simulated joystick RIGHT index.
#define JOYSTICK_RIGHT 1
/** PWMC PWM0 pin definition. */
#define PIN_PWMC_PWMH0 {1 << 18, PIOC, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT}
#define PIN_PWMC_PWML0 {1 << 19, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
/** PWMC PWM1 pin definition. */
#define PIN_PWMC_PWMH1 {1 << 19, PIOC, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT}
#define PIN_PWMC_PWML1 {1 << 20, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
/** PWMC PWM2 pin definition. */
#define PIN_PWMC_PWMH2 {1 << 20, PIOC, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT}
#define PIN_PWMC_PWML2 {1 << 16, PIOA, ID_PIOA, PIO_PERIPH_C, PIO_DEFAULT}
/** PWMC PWM3 pin definition. */
#define PIN_PWMC_PWMH3 {1 << 21, PIOC, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT}
#define PIN_PWMC_PWML3 {1 << 15, PIOA, ID_PIOA, PIO_PERIPH_C, PIO_DEFAULT}
/** PWM pin definition for LED0 */
#define PIN_PWM_LED0 PIN_PWMC_PWMH0, PIN_PWMC_PWML0
/** PWM pin definition for LED1 */
#define PIN_PWM_LED1 PIN_PWMC_PWMH2, PIN_PWMC_PWML2
/** PWM pin definition for LED2 */
#define PIN_PWM_LED2 PIN_PWMC_PWMH3, PIN_PWMC_PWML3
/** PWM channel for LED0 */
#define CHANNEL_PWM_LED0 0
/** PWM channel for LED1 */
#define CHANNEL_PWM_LED1 2
/** PWM channel for LED2 */
#define CHANNEL_PWM_LED2 3
/** SPI MISO pin definition. */
#define PIN_SPI_MISO {1 << 12, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/** SPI MOSI pin definition. */
#define PIN_SPI_MOSI {1 << 13, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/** SPI SPCK pin definition. */
#define PIN_SPI_SPCK {1 << 14, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/** SPI chip select pin definition. */
#define PIN_SPI_NPCS0_PA11 {1 << 11, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/** List of SPI pin definitions (MISO, MOSI & SPCK). */
#define PINS_SPI PIN_SPI_MISO, PIN_SPI_MOSI, PIN_SPI_SPCK
/// SSC pins definition.
#define PIN_SSC_TD {0x1 << 26, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PIN_SSC_TK {0x1 << 28, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PIN_SSC_TF {0x1 << 30, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PINS_SSC_CODEC PIN_SSC_TD, PIN_SSC_TK, PIN_SSC_TF
/// PCK0
#define PIN_PCK0 {0x1 << 21, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
/// TWI pins definition.
#define TWI_V3XX
#define PIN_TWI_TWD0 {0x1 << 9, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PIN_TWI_TWCK0 {0x1 << 10, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PINS_TWI0 PIN_TWI_TWD0, PIN_TWI_TWCK0
#define PIN_TWI_TWD1 {0x1 << 24, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PIN_TWI_TWCK1 {0x1 << 25, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PINS_TWI1 PIN_TWI_TWD1, PIN_TWI_TWCK1
/// USART0
#define PIN_USART0_RXD {0x1 << 19, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PIN_USART0_TXD {0x1 << 18, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PIN_USART0_CTS {0x1 << 8, PIOB, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT}
#define PIN_USART0_RTS {0x1 << 7, PIOB, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT}
#define PIN_USART0_SCK {0x1 << 17, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
/// USART1
#define PIN_USART1_RXD {0x1 << 21, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PIN_USART1_TXD {0x1 << 22, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PIN_USART1_CTS {0x1 << 25, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PIN_USART1_RTS {0x1 << 24, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
#define PIN_USART1_EN {0x1 << 23, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
/// USB VBus monitoring pin definition.
#ifdef BOARD_REV_A
#define PIN_USB_VBUS {1 << 23, PIOC, ID_PIOC, PIO_INPUT, PIO_DEFAULT}
#endif
#ifdef BOARD_REV_B
#define PIN_USB_VBUS {1 << 21, PIOC, ID_PIOC, PIO_INPUT, PIO_DEFAULT}
#endif
#define usbPlugged() (PIOC->PIO_PDSR & PIO_PC25)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \par sam3s_ek_extcomp "SAM3S-EK - External components"
/// This page lists the definitions related to external on-board components
/// located in the board.h file for the AT91SAM3S-EK.
///
/// !AT45 Dataflash Card
/// - BOARD_AT45_A_SPI_BASE
/// - BOARD_AT45_A_SPI_ID
/// - BOARD_AT45_A_SPI_PINS
/// - BOARD_AT45_A_SPI
/// - BOARD_AT45_A_NPCS
/// - BOARD_AT45_A_NPCS_PIN
///
/// !AT45 Dataflash (serial onboard DataFlash)
/// - BOARD_AT45_B_SPI_BASE
/// - BOARD_AT45_B_SPI_ID
/// - BOARD_AT45_B_SPI_PINS
/// - BOARD_AT45_B_SPI
/// - BOARD_AT45_B_NPCS
/// - BOARD_AT45_B_NPCS_PIN
///
/// !AT26 Serial Flash
/// - BOARD_AT26_A_SPI_BASE
/// - BOARD_AT26_A_SPI_ID
/// - BOARD_AT26_A_SPI_PINS
/// - BOARD_AT26_A_SPI
/// - BOARD_AT26_A_NPCS
/// - BOARD_AT26_A_NPCS_PIN
///
/// !SD Card
/// - MCI2_INTERFACE
/// - BOARD_SD_MCI_BASE
/// - BOARD_SD_MCI_ID
/// - BOARD_SD_PINS
/// - BOARD_SD_SLOT
///
/// !PSRAM
/// - BOARD_PSRAM_PINS
///
/// !LCD
/// - BOARD_LCD_ILI9325
/// - BOARD_LCD_PINS
/// - BOARD_BACKLIGHT_PIN
/// - BOARD_LCD_BASE
/// - BOARD_LCD_RS
/// - BOARD_LCD_WIDTH
/// - BOARD_LCD_HEIGHT
///
/// !TouchScreen
/// - BOARD_TSC_ADS7843
/// - PIN_TCS_IRQ
/// - PIN_TCS_BUSY
/// - BOARD_TSC_SPI_BASE
/// - BOARD_TSC_SPI_ID
/// - BOARD_TSC_SPI_PINS
/// - BOARD_TSC_NPCS
/// - BOARD_TSC_NPCS_PIN
///
/// Base address of SPI peripheral connected to the dataflash.
//#define BOARD_AT45_A_SPI_BASE SPI0
///// Identifier of SPI peripheral connected to the dataflash.
//#define BOARD_AT45_A_SPI_ID ID_SPI0
///// Pins of the SPI peripheral connected to the dataflash.
//#define BOARD_AT45_A_SPI_PINS PINS_SPI0
///// Dataflahs SPI number.
//#define BOARD_AT45_A_SPI 0
///// Chip select connected to the dataflash.
//#define BOARD_AT45_A_NPCS 3
///// Chip select pin connected to the dataflash.
//#define BOARD_AT45_A_NPCS_PIN PIN_SPI0_NPCS3
/// Base address of SPI peripheral connected to the dataflash.
//#define BOARD_AT45_B_SPI_BASE SPI1
///// Identifier of SPI peripheral connected to the dataflash.
//#define BOARD_AT45_B_SPI_ID ID_SPI1
///// Pins of the SPI peripheral connected to the dataflash.
//#define BOARD_AT45_B_SPI_PINS PINS_SPI1
///// Dataflahs SPI number.
//#define BOARD_AT45_B_SPI 1
///// Chip select connected to the dataflash.
//#define BOARD_AT45_B_NPCS 3
///// Chip select pin connected to the dataflash.
//#define BOARD_AT45_B_NPCS_PIN PIN_SPI1_NPCS3
/// Base address of SPI peripheral connected to the serialflash.
//#define BOARD_AT26_A_SPI_BASE SPI0
///// Identifier of SPI peripheral connected to the serialflash.
//#define BOARD_AT26_A_SPI_ID ID_SPI0
///// Pins of the SPI peripheral connected to the serialflash.
//#define BOARD_AT26_A_SPI_PINS PINS_SPI0
///// Serialflash SPI number.
//#define BOARD_AT26_A_SPI 0
///// Chip select connected to the serialflash.
//#define BOARD_AT26_A_NPCS 3
///// Chip select pin connected to the serialflash.
//#define BOARD_AT26_A_NPCS_PIN PIN_SPI0_NPCS3
/// ISO7816
/// - PIN_SMARTCARD_CONNECT
/// - PIN_ISO7816_RSTMC
/// - PINS_ISO7816
/// Smartcard detection pin
//#define PIN_SMARTCARD_CONNECT {1 << 5, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
/// PIN used for reset the smartcard
//#define PIN_ISO7816_RSTMC {1 << 7, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
/// Pins used for connect the smartcard
//#define PINS_ISO7816 PIN_USART0_TXD, PIN_USART0_SCK, PIN_ISO7816_RSTMC
/// Dma channel number
#define BOARD_MCI_DMA_CHANNEL 0
/// MCI0 DMA hardware handshaking ID
#define DMA_HW_SRC_REQ_ID_MCI0 AT91C_HDMA_SRC_PER_0
#define DMA_HW_DEST_REQ_ID_MCI0 AT91C_HDMA_DST_PER_0
/// MCI1 DMA hardware handshaking ID
#define DMA_HW_SRC_REQ_ID_MCI1 AT91C_HDMA_SRC_PER_13
#define DMA_HW_DEST_REQ_ID_MCI1 AT91C_HDMA_DST_PER_13
/// SD DMA hardware handshaking ID
#define BOARD_SD_DMA_HW_SRC_REQ_ID DMA_HW_SRC_REQ_ID_MCI0
#define BOARD_SD_DMA_HW_DEST_REQ_ID DMA_HW_DEST_REQ_ID_MCI0
/// HS MCI interface
#define MCI2_INTERFACE
/// Base address of the MCI peripheral connected to the SD card.
#define BOARD_SD_MCI_BASE MCI0//MCI
///// Peripheral identifier of the MCI connected to the SD card.
#define BOARD_SD_MCI_ID AT91C_ID_MCI0 ID_MCI0 //ID_MCI
///// MCI pins that shall be configured to access the SD card.
#define BOARD_SD_PINS PINS_MCI
///// MCI slot to which the SD card is connected to.
#define BOARD_SD_SLOT MCI_SD_SLOTA
///// MCI Card Detect pin.
#define BOARD_SD_PIN_CD PIN_MCI_CD
#define SD_CARD_PRESENT() ( (PIOB->PIO_PDSR & PIO_PB7) == 0 )
// States for initialising card
#define SD_ST_ERR -1
#define SD_ST_STARTUP 0
#define SD_ST_EMPTY 1
#define SD_ST_INIT1 2
#define SD_ST_INIT2 3
#define SD_ST_IDLE 4
#define SD_ST_READY 5
#define SD_ST_IDENT 6
#define SD_ST_STBY 7
#define SD_ST_TRAN 8
#define SD_ST_DATA 9
#define SD_ST_MOUNTED 10
extern uint32_t Cmd_A41_resp;
extern int32_t Card_state;
extern volatile uint32_t Card_initialized;
extern uint32_t Card_CSD[4];
extern uint32_t transSpeed;
#define OCR_SD_CCS (1UL << 30)
#define SD_CSD(csd, bitfield, bits) ((csd[3-(bitfield)/32] >> ((bitfield)%32)) & ((1 << (bits)) - 1))
#define SD_CSD_TRAN_SPEED(pSd) SD_CSD(pSd, 96, 8) ///< Max. data transfer rate
#define SD_CSD_C_SIZE(pSd) ((SD_CSD(pSd, 72, 2) << 10) + \
(SD_CSD(pSd, 64, 8) << 2) + \
SD_CSD(pSd, 62, 2)) ///< Device size
#define SD_CSD_C_SIZE_HC(csd) ((SD_CSD(csd, 64, 6) << 16) + \
(SD_CSD(csd, 56, 8) << 8) + \
SD_CSD(csd, 48, 8)) ///< Device size v2.0 High Capacity
#define SD_CSD_C_SIZE_MULT(pSd) SD_CSD(pSd, 47, 3) ///< Device size multiplier
#define SD_CSD_MULT(pSd) (1 << (SD_CSD_C_SIZE_MULT(pSd) + 2))
#define SD_CSD_READ_BL_LEN(pSd) SD_CSD(pSd, 80, 4) ///< Max. read data block length
#define SD_CSD_BLKLEN(pSd) (1 << (SD_CSD_READ_BL_LEN(pSd) - 9))
#define SD_CSD_BLOCKNR(pSd) ((SD_CSD_C_SIZE(pSd) + 1) * SD_CSD_MULT(pSd)) * SD_CSD_BLKLEN(pSd)
#define SD_CSD_BLOCKNR_HC(pSd) ((SD_CSD_C_SIZE_HC(pSd) + 1) * 1024)
#if !defined(SIMU)
#define SD_IS_HC() (Cmd_A41_resp & OCR_SD_CCS)
#define SD_GET_BLOCKNR() (SD_IS_HC() ? (SD_CSD_BLOCKNR_HC(Card_CSD)) : (SD_CSD_BLOCKNR(Card_CSD)))
#define SD_GET_SPEED() (transSpeed)
#define SD_GET_SIZE_MB() (SD_GET_BLOCKNR() / 2048)
#endif
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \par sam3s_ek_mem "SAM3S-EK - Memories"
/// This page lists definitions related to internal & external on-board memories.
///
/// !Embedded Flash
/// - BOARD_FLASH_EFC
/// Internal SRAM address
#define AT91C_ISRAM AT91C_IRAM
#define AT91C_ISRAM_SIZE 0x00008000
#define AT91C_IFLASH_SIZE (0x40000)
#define AT91C_IFLASH_PAGE_SIZE (256) // Internal FLASH 0 Page Size: 256 bytes
#define AT91C_IFLASH_NB_OF_PAGES (1024) // Internal FLASH 0 Number of Pages: 512
#define AT91C_IFLASH_LOCK_REGION_SIZE (16384) // Internal FLASH 0 Lock Region Size: 16 Kbytes
#define AT91C_IFLASH_NB_OF_LOCK_BITS (16) // Internal FLASH 0 Number of Lock Bits: 16
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \section sam3s_ek_extcomp "SAM3S-EK - External components"
/// This page lists the definitions related to external on-board components
/// located in the board.h file for the SAM3S-EK.
///
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \par sam3s_ek_chipdef "SAM3S-EK - Individual chip definition"
/// This page lists the definitions related to different chip's definition
/// located in the board.h file for the SAM3S-EK.
/// DBGU
#define BOARD_DBGU_ID ID_DBGU
/// Rtc
#define BOARD_RTC_ID ID_RTC
/// Twi eeprom
#define BOARD_ID_TWI_EEPROM ID_TWI1
#define BOARD_BASE_TWI_EEPROM TWI1
#define BOARD_PINS_TWI_EEPROM PINS_TWI1
/// USART
#define BOARD_PIN_USART_RXD PIN_USART1_RXD
#define BOARD_PIN_USART_TXD PIN_USART1_TXD
#define BOARD_PIN_USART_CTS PIN_USART1_CTS
#define BOARD_PIN_USART_RTS PIN_USART1_RTS
#define BOARD_PIN_USART_EN PIN_USART1_EN
#define BOARD_USART_BASE USART1
#define BOARD_ID_USART ID_USART1
// BlueTooth
#define BT_USART UART1
#define BT_ID ID_UART1
//------------------------------------------------------------------------------
#define PIN_EBI_NANDOE {1 << 9, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_PULLUP}
#define PIN_EBI_NANDWE {1 << 10, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_PULLUP}
#define PIN_EBI_NANDCLE {1 << 17, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_PULLUP}
#define PIN_EBI_NANDALE {1 << 16, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_PULLUP}
#define PIN_EBI_NANDIO {0x000000FF, PIOC, ID_PIOC, PIO_PERIPH_A, PIO_PULLUP}
/// Nandflash chip enable pin definition.
#define BOARD_NF_CE_PIN {1 << 14, PIOC, ID_PIOC, PIO_OUTPUT_1, PIO_DEFAULT}
/// Nandflash ready/busy pin definition.
#define BOARD_NF_RB_PIN {1 << 18, PIOC, ID_PIOC, PIO_INPUT, PIO_PULLUP}
/// Nandflash controller peripheral pins definition.
#define PINS_NANDFLASH PIN_EBI_NANDIO, BOARD_NF_CE_PIN, BOARD_NF_RB_PIN, PIN_EBI_NANDOE, \
PIN_EBI_NANDWE, PIN_EBI_NANDCLE, PIN_EBI_NANDALE
/// Address for transferring command bytes to the nandflash.
#define BOARD_NF_COMMAND_ADDR 0x60400000
/// Address for transferring address bytes to the nandflash.
#define BOARD_NF_ADDRESS_ADDR 0x60200000
/// Address for transferring data bytes to the nandflash.
#define BOARD_NF_DATA_ADDR 0x60000000
extern uint32_t Master_frequency ;
struct t_serial_tx
{
uint8_t *buffer ;
uint16_t size ;
volatile uint16_t ready ;
};
#endif
+229
View File
@@ -0,0 +1,229 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* \par Purpose
*
* Provides the low-level initialization function that gets called on chip startup.
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "board.h"
/*----------------------------------------------------------------------------
* Local definitions
*----------------------------------------------------------------------------*/
/** Define clock timeout */
#define CLOCK_TIMEOUT 5000
/** Bit 29 must always be set to 1 when programming the CKGR_PLLAR register.*/
#define PMC_PLLA_SET_BIT29 (0x1 << 29)
/** Specifies the number of Slow Clock cycles x8 before the LOCKA bit is set in PMC_SR after CKGR_PLLAR is written.*/
#define PMC_PLLA_COUNT (0xBF << 8)
/** The PLLA Clock frequency is the PLLA input frequency multiplied by 8*/
#define PMC_PLLA_MULTIPIER (0x07 << 16)
/** PLLA Divider is bypassed.*/
#define PMC_PLLA_DIV (0x01)
void revert_osc( void ) ;
/*----------------------------------------------------------------------------
* Local functions
* returns master_frequency
*----------------------------------------------------------------------------*/
// *** WARNING, this is called BEFORE .data and .bss have been initialised
// *** GLOBAL variables are NOT useable
static uint32_t BOARD_ConfigurePmc(void)
{
/* TODO: configurate PLL in new way */
//#if 0
// uint32_t timeout = 0;
// /** 1: Checking the Main Oscillator Frequency (Optional) and Initialize main oscillator */
// /** 1.1 Initialize main oscillator */
// // TODO:
// /** 2. Setting PLL and Divider*/
// /** 2.1 Initialize PLLA*/
// PMC->CKGR_PLLAR = ( PMC_PLLA_SET_BIT29 |
// PMC_PLLA_MULTIPIER |
// PMC_PLLA_COUNT |
// PMC_PLLA_DIV
// );
// timeout = 0;
// /** 2.2 Wait for the LOCKA bit to be set by polling the status register.*/
// while (!(PMC->PMC_SR & PMC_SR_LOCKA) && (timeout++ < CLOCK_TIMEOUT));
// /** 2.3 wait for the MCKRDY bit to be set by polling the status register*/
// timeout = 0;
// while (!(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT));
// /** 3. Selection of Master Clock and Processor Clock*/
// PMC->PMC_MCKR |= PMC_MCKR_PRES_CLK_2;
// /** 3.1 wait for the MCKRDY bit to be set by polling the status register*/
// timeout = 0;
// while (!(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT));
// /** 3.2 PLLA Clock is selected */
// PMC->PMC_MCKR = PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK;
// /** 3.3 wait for the MCKRDY bit to be set by polling the status register*/
// timeout = 0;
// while (!(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT));
//#endif
#if 1 // old as sam3u
#define AT91C_CKGR_MUL_SHIFT 16
//#define AT91C_CKGR_OUT_SHIFT 14
#define AT91C_CKGR_PLLCOUNT_SHIFT 8
#define AT91C_CKGR_DIV_SHIFT 0
// Settings at 72MHz/2 = 36MHz
#define BOARD_OSCOUNT (CKGR_MOR_MOSCXTST & (0x8 << 8))
#define BOARD_PLLR ((1 << 29) | (0x5 << AT91C_CKGR_MUL_SHIFT) \
| (0x1 << AT91C_CKGR_PLLCOUNT_SHIFT) | (0x2 << AT91C_CKGR_DIV_SHIFT))
#define BOARD_MCKR (PMC_MCKR_CSS_PLLA_CLK)
// Define clock timeout
#undef CLOCK_TIMEOUT
#define CLOCK_TIMEOUT 0xFFFFFFFF
register uint32_t timeout = 0 ;
register Pmc *pmcptr ;
pmcptr = PMC ;
/* Enable NRST reset
************************************/
//AT91C_BASE_RSTC->RSTC_RMR |= AT91C_RSTC_URSTEN;
/* Select external slow clock
****************************/
// if ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST) {
// SUPC->SUPC_CR = SUPC_CR_XTALSEL_CRYSTAL_SEL | ((uint32_t)0xA5 << 24);
// timeout = 0;
// while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL_CRYST) );
// }
/* Initialize main oscillator
****************************/
if(!(pmcptr->CKGR_MOR & CKGR_MOR_MOSCSEL))
{
pmcptr->CKGR_MOR = (0x37 << 16) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN;
timeout = 0;
while (!(pmcptr->PMC_SR & PMC_SR_MOSCXTS) && (++timeout < CLOCK_TIMEOUT));
}
/* Switch to 3-20MHz Xtal oscillator */
pmcptr->CKGR_MOR = (0x37 << 16) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL;
timeout = 0;
while (!(pmcptr->PMC_SR & PMC_SR_MOSCSELS) && (++timeout < CLOCK_TIMEOUT));
pmcptr->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS) | PMC_MCKR_CSS_MAIN_CLK;
timeout = 0;
while (!(pmcptr->PMC_SR & PMC_SR_MCKRDY) && (++timeout < CLOCK_TIMEOUT));
/* Initialize PLLA 72 MHz */
pmcptr->CKGR_PLLAR = BOARD_PLLR;
timeout = 0;
while (!(pmcptr->PMC_SR & PMC_SR_LOCKA) && (++timeout < CLOCK_TIMEOUT));
/* Initialize UTMI for USB usage, can be disabled if not using USB for the sake of saving power*/
//AT91C_BASE_CKGR->CKGR_UCKR |= (AT91C_CKGR_UPLLCOUNT & (3 << 20)) | AT91C_CKGR_UPLLEN;
//timeout = 0;
//while (!(PMC->PMC_SR & AT91C_PMC_LOCKU) && (timeout++ < CLOCK_TIMEOUT));
/* Switch to fast clock
**********************/
// PMC->PMC_MCKR = (BOARD_MCKR & ~PMC_MCKR_CSS) | PMC_MCKR_CSS_MAIN_CLK;
// timeout = 0;
// while (!(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT));
// Switch to PLLA as main clock 36MHz
PMC->PMC_MCKR = BOARD_MCKR;
timeout = 0;
while (!(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT));
#endif
return 36000000L ; // Master_frequency
}
void revert_osc()
{
register uint32_t timeout = 0 ;
register Pmc *pmcptr ;
pmcptr = PMC ;
// Switch back to the internal oscillator
pmcptr->CKGR_MOR = (0x37 << 16) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN ;
timeout = 0;
while (!(pmcptr->PMC_SR & PMC_SR_MOSCSELS) && (++timeout < CLOCK_TIMEOUT));
pmcptr->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS) | PMC_MCKR_CSS_SLOW_CLK;
timeout = 0;
while (!(pmcptr->PMC_SR & PMC_SR_MCKRDY) && (++timeout < CLOCK_TIMEOUT));
pmcptr->CKGR_PLLAR = 1 << 29 ; // Stop PLLA
}
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/**
* \brief Performs the low-level initialization of the chip. This includes EFC,
* master clock and watchdog configuration.
*/
/*----------------------------------------------------------------------------*/
uint32_t SystemInit (void)
{
/** Set 2 cycle (1 WS) for Embedded Flash Access */
// Max clock is 38 MHz (1.8V VVDCORE)
EFC->EEFC_FMR = (1 << 8) ;
/** Configure PMC */
return BOARD_ConfigurePmc();
}
+844
View File
@@ -0,0 +1,844 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../../opentx.h"
#if defined(DEBUG) && !defined(SIMU)
void DEBUG_UART_Configure( uint32_t baudrate, uint32_t masterClock);
void DEBUG_UART_Stop();
#else
#define DEBUG_UART_Stop()
#define DEBUG_UART_Configure(...)
#endif
uint16_t ResetReason;
uint32_t Master_frequency ;
volatile uint32_t Tenms ;
volatile uint8_t lcdLock;
volatile uint32_t lcdInputs;
/** Console baudrate 9600. */
#define CONSOLE_BAUDRATE 9600
/** Usart Hw interface used by the console (UART0). */
#define CONSOLE_USART UART0
/** Usart Hw ID used by the console (UART0). */
#define CONSOLE_ID ID_UART0
/** Pins description corresponding to Rxd,Txd, (UART pins) */
#define CONSOLE_PINS {PINS_UART}
/** Second serial baudrate 9600. */
#define SECOND_BAUDRATE 9600
/** Usart Hw interface used by the console (UART0). */
#define SECOND_USART USART0
/** Usart Hw ID used by the console (UART0). */
#define SECOND_ID ID_USART0
/** Pins description corresponding to Rxd,Txd, (UART pins) */
#define SECOND_PINS {PINS_USART0}
extern "C" void sam_boot( void ) ;
// Prototype
// Free pins (PA16 is stock buzzer)
// PA23, PA24, PA25, PB7, PB13
// PC20, PC21(labelled 17), PC22, PC24
// REVB
// PA25, use for stock buzzer
// PB14, PB6
// PC21, PC19, PC15 (PPM2 output)
inline void config_free_pins()
{
#if defined(REVA)
register Pio * pioptr = PIOA ;
pioptr->PIO_PER = 0x03800000L ; // Enable bits A25,24,23
pioptr->PIO_ODR = 0x03800000L ; // Set as input
pioptr->PIO_PUER = 0x03800000L ; // Enable pullups
pioptr = PIOB ;
pioptr->PIO_PER = 0x00002080L ; // Enable bits B13, 7
pioptr->PIO_ODR = 0x00002080L ; // Set as input
pioptr->PIO_PUER = 0x00002080L ; // Enable pullups
pioptr = PIOC ;
pioptr->PIO_PER = 0x01700000L ; // Enable bits C24,22,21,20
pioptr->PIO_ODR = 0x01700000L ; // Set as input
pioptr->PIO_PUER = 0x01700000L ; // Enable pullups
#else
configure_pins( PIO_PB14, PIN_ENABLE | PIN_INPUT | PIN_PORTB | PIN_PULLUP ) ;
#endif
}
// Assumes PMC has already enabled clocks to ports
inline void setup_switches()
{
#if defined(REVA)
register Pio *pioptr = PIOA ;
pioptr->PIO_PER = 0xF8008184 ; // Enable bits
pioptr->PIO_ODR = 0xF8008184 ; // Set bits input
pioptr->PIO_PUER = 0xF8008184 ; // Set bits with pullups
pioptr = PIOB ;
pioptr->PIO_PER = 0x00000010 ; // Enable bits
pioptr->PIO_ODR = 0x00000010 ; // Set bits input
pioptr->PIO_PUER = 0x00000010 ; // Set bits with pullups
pioptr = PIOC ;
pioptr->PIO_PER = 0x10014900 ; // Enable bits
pioptr->PIO_ODR = 0x10014900 ; // Set bits input
pioptr->PIO_PUER = 0x10014900 ; // Set bits with pullups
#else
configure_pins( 0x01808087, PIN_ENABLE | PIN_INPUT | PIN_PORTA | PIN_PULLUP ) ;
configure_pins( 0x00000030, PIN_ENABLE | PIN_INPUT | PIN_PORTB | PIN_PULLUP ) ;
configure_pins( 0x91114900, PIN_ENABLE | PIN_INPUT | PIN_PORTC | PIN_PULLUP ) ;
#endif
}
#ifdef SIMU
#define stop_trainer_capture()
#define rotencEnd()
#define sam_boot()
#else
inline void UART3_Configure( uint32_t baudrate, uint32_t masterClock)
{
// const Pin pPins[] = CONSOLE_PINS;
register Uart *pUart = BT_USART;
/* Configure PIO */
configure_pins( (PIO_PB2 | PIO_PB3), PIN_PERIPHERAL | PIN_INPUT | PIN_PER_A | PIN_PORTB | PIN_NO_PULLUP ) ;
/* Configure PMC */
PMC->PMC_PCER0 = 1 << BT_ID;
/* Reset and disable receiver & transmitter */
pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX
| UART_CR_RXDIS | UART_CR_TXDIS;
/* Configure mode */
pUart->UART_MR = 0x800 ; // NORMAL, No Parity
/* Configure baudrate */
/* Asynchronous, no oversampling */
pUart->UART_BRGR = ( (masterClock / baudrate) + 8 ) / 16;
/* Disable PDC channel */
pUart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
/* Enable receiver and transmitter */
pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
#if 0
pUart->UART_IER = UART_IER_RXRDY ;
NVIC_EnableIRQ(UART1_IRQn) ;
#endif
}
void UART3_Stop()
{
BT_USART->UART_IDR = UART_IDR_RXRDY ;
NVIC_DisableIRQ(UART1_IRQn) ;
}
// USART0 configuration
// Work in Progress, UNTESTED
// Uses PA5 and PA6 (RXD and TXD)
inline void UART2_Configure( uint32_t baudrate, uint32_t masterClock)
{
//// const Pin pPins[] = CONSOLE_PINS;
register Usart *pUsart = SECOND_USART;
/* Configure PIO */
configure_pins( (PIO_PA5 | PIO_PA6), PIN_PERIPHERAL | PIN_INPUT | PIN_PER_A | PIN_PORTA | PIN_NO_PULLUP ) ;
// /* Configure PMC */
PMC->PMC_PCER0 = 1 << SECOND_ID;
// /* Reset and disable receiver & transmitter */
pUsart->US_CR = US_CR_RSTRX | US_CR_RSTTX
| US_CR_RXDIS | US_CR_TXDIS;
// /* Configure mode */
pUsart->US_MR = 0x000008C0 ; // NORMAL, No Parity, 8 bit
// /* Configure baudrate */
// /* Asynchronous, no oversampling */
pUsart->US_BRGR = (masterClock / baudrate) / 16;
// /* Disable PDC channel */
pUsart->US_PTCR = US_PTCR_RXTDIS | US_PTCR_TXTDIS;
// /* Enable receiver and transmitter */
pUsart->US_CR = US_CR_RXEN | US_CR_TXEN;
}
// Starts TIMER0 at full speed (MCK/2) for delay timing
// @ 36MHz this is 18MHz
// This was 6 MHz, we may need to slow it to TIMER_CLOCK2 (MCK/8=4.5 MHz)
inline void start_timer0()
{
register Tc *ptc ;
// Enable peripheral clock TC0 = bit 23 thru TC5 = bit 28
PMC->PMC_PCER0 |= 0x00800000L ; // Enable peripheral clock to TC0
ptc = TC0 ; // Tc block 0 (TC0-2)
ptc->TC_BCR = 0 ; // No sync
ptc->TC_BMR = 2 ;
ptc->TC_CHANNEL[0].TC_CMR = 0x00008001 ; // Waveform mode MCK/8 for 36MHz osc.
ptc->TC_CHANNEL[0].TC_RC = 0xFFF0 ;
ptc->TC_CHANNEL[0].TC_RA = 0 ;
ptc->TC_CHANNEL[0].TC_CMR = 0x00008040 ; // 0000 0000 0000 0000 1000 0000 0100 0000, stop at regC
ptc->TC_CHANNEL[0].TC_CCR = 5 ; // Enable clock and trigger it (may only need trigger)
}
// TIMER2 at 200Hz, provides 5mS for sound and 10mS tick on interrupt
// Starts TIMER2 at 200Hz, commentd out drive of TIOA2 (A26, EXT2)
inline void start_timer2()
{
register Tc *ptc ;
register uint32_t timer ;
// Enable peripheral clock TC0 = bit 23 thru TC5 = bit 28
PMC->PMC_PCER0 |= 0x02000000L ; // Enable peripheral clock to TC2
timer = Master_frequency / 12800 / 2; // MCK/128 and 200 Hz
ptc = TC0 ; // Tc block 0 (TC0-2)
ptc->TC_BCR = 0 ; // No sync
ptc->TC_BMR = 0 ;
ptc->TC_CHANNEL[2].TC_CMR = 0x00008000 ; // Waveform mode
ptc->TC_CHANNEL[2].TC_RC = timer ; // 10 Hz
ptc->TC_CHANNEL[2].TC_RA = timer >> 1 ;
ptc->TC_CHANNEL[2].TC_CMR = 0x0009C003 ; // 0000 0000 0000 1001 1100 0000 0000 0011
ptc->TC_CHANNEL[2].TC_CCR = 5 ; // Enable clock and trigger it (may only need trigger)
NVIC_EnableIRQ(TC2_IRQn) ;
TC0->TC_CHANNEL[2].TC_IER = TC_IER0_CPCS ;
}
// Start TIMER3 for input capture
inline void start_timer3()
{
register Tc *ptc ;
// Enable peripheral clock TC0 = bit 23 thru TC5 = bit 28
PMC->PMC_PCER0 |= 0x04000000L ; // Enable peripheral clock to TC3
ptc = TC1 ; // Tc block 1 (TC3-5)
ptc->TC_BCR = 0 ; // No sync
ptc->TC_BMR = 2 ;
ptc->TC_CHANNEL[0].TC_CMR = 0x00000000 ; // Capture mode
ptc->TC_CHANNEL[0].TC_CMR = 0x00090005 ; // 0000 0000 0000 1001 0000 0000 0000 0101, XC0, A rise, b fall
ptc->TC_CHANNEL[0].TC_CCR = 5 ; // Enable clock and trigger it (may only need trigger)
configure_pins( PIO_PC23, PIN_PERIPHERAL | PIN_INPUT | PIN_PER_B | PIN_PORTC | PIN_PULLUP ) ;
NVIC_SetPriority( TC3_IRQn, 14 ) ; // Low priority interrupt
NVIC_EnableIRQ(TC3_IRQn) ;
ptc->TC_CHANNEL[0].TC_IER = TC_IER0_LDRAS ;
}
// Start Timer4 to provide 0.5uS clock for input capture
void start_timer4()
{
register Tc *ptc ;
register uint32_t timer ;
timer = Master_frequency / (2*2000000) ; // MCK/2 and 2MHz
// Enable peripheral clock TC0 = bit 23 thru TC5 = bit 28
PMC->PMC_PCER0 |= 0x08000000L ; // Enable peripheral clock to TC4
ptc = TC1 ; // Tc block 1 (TC3-5)
ptc->TC_BCR = 0 ; // No sync
ptc->TC_BMR = 0 ;
ptc->TC_CHANNEL[1].TC_CMR = 0x00008000 ; // Waveform mode
ptc->TC_CHANNEL[1].TC_RC = timer ;
ptc->TC_CHANNEL[1].TC_RA = timer >> 1 ;
ptc->TC_CHANNEL[1].TC_CMR = 0x0009C000 ; // 0000 0000 0000 1001 1100 0000 0100 0000
// MCK/2, set @ RA, Clear @ RC waveform
ptc->TC_CHANNEL[1].TC_CCR = 5 ; // Enable clock and trigger it (may only need trigger)
}
// Timer3 used for PPM_IN pulse width capture. Counter running at 16MHz / 8 = 2MHz
// equating to one count every half millisecond. (2 counts = 1ms). Control channel
// count delta values thus can range from about 1600 to 4400 counts (800us to 2200us),
// corresponding to a PPM signal in the range 0.8ms to 2.2ms (1.5ms at center).
// (The timer is free-running and is thus not reset to zero at each capture interval.)
// Timer 4 generates the 2MHz clock to clock Timer 3
extern "C" void TC3_IRQHandler() //capture ppm in at 2MHz
{
static uint16_t lastCapt ;
uint16_t capture = TC1->TC_CHANNEL[0].TC_RA ;
(void) TC1->TC_CHANNEL[0].TC_SR ; // Acknowledge the interrupt
uint16_t val = ((uint16_t)(capture - lastCapt)) / 2;
// G: We process g_ppmIns immediately here, to make servo movement as smooth as possible
// while under trainee control
if (val>4000 && val<19000) { // G: Prioritize reset pulse. (Needed when less than 8 incoming pulses)
ppmInState = 1; // triggered
}
else {
if (ppmInState && ppmInState<=8)
{
if (val>800 && val<2200) // if valid pulse-width range
{
g_ppmIns[ppmInState++ - 1] =
(int16_t)(val - 1500)*(g_eeGeneral.PPM_Multiplier+10)/10; //+-500 != 512, but close enough.
}
else
ppmInState = 0; // not triggered
}
}
lastCapt = capture;
}
void init_trainer_capture()
{
start_timer4() ;
start_timer3() ;
}
void stop_trainer_capture()
{
TC1->TC_CHANNEL[0].TC_IDR = TC_IDR0_LDRAS ;
NVIC_DisableIRQ(TC3_IRQn) ;
}
void interrupt5ms()
{
static uint32_t pre_scale ; // Used to get 10 Hz counter
HAPTIC_HEARTBEAT();
AUDIO_HEARTBEAT();
if ( ++pre_scale >= 2 ) {
BUZZER_HEARTBEAT();
pre_scale = 0 ;
per10ms();
}
}
extern "C" void TC2_IRQHandler()
{
register uint32_t dummy;
/* Clear status bit to acknowledge interrupt */
dummy = TC0->TC_CHANNEL[2].TC_SR;
(void) dummy ; // Discard value - prevents compiler warning
interrupt5ms();
}
// PWM used for PPM generation, and LED Backlight
// Output pin PB5 not used, PA17 used as PWMH3 peripheral C
// PWM peripheral ID = 31 (0x80000000)
// Ensure PB5 is three state/input, used on REVB for MENU KEY
// Configure PWM3 as PPM drive,
// PWM0 is LED backlight PWM on PWMH0
// This is PC18 peripheral B, Also enable PC22 peripheral B, this is PPM-JACK (PWML3)
//
// REVB board:
// PWML2, output as peripheral C on PA16, is for HAPTIC
// For testing, just drive it out with PWM
// PWML1 for PPM2 output as peripheral B on PC15
// For testing, just drive it out with PWM
void init_pwm()
{
register Pwm *pwmptr ;
register uint32_t timer ;
PMC->PMC_PCER0 |= ( 1 << ID_PWM ) ; // Enable peripheral clock to PWM
MATRIX->CCFG_SYSIO |= 0x00000020L ; // Disable TDO let PB5 work!
/* Configure PIO */
#if defined(REVA)
register Pio *pioptr = PIOB ;
pioptr->PIO_PER = 0x00000020L ; // Enable bit B5
pioptr->PIO_ODR = 0x00000020L ; // set as input
#else
configure_pins( PIO_PA16, PIN_PERIPHERAL | PIN_INPUT | PIN_PER_C | PIN_PORTA | PIN_NO_PULLUP ) ;
#endif
configure_pins( PIO_PC18, PIN_PERIPHERAL | PIN_INPUT | PIN_PER_B | PIN_PORTC | PIN_NO_PULLUP ) ;
#if !defined(REVA)
configure_pins( PIO_PC22, PIN_PERIPHERAL | PIN_INPUT | PIN_PER_B | PIN_PORTC | PIN_NO_PULLUP ) ;
#endif
// Configure clock - depends on MCK frequency
timer = Master_frequency / 2000000 ;
timer |= ( Master_frequency / ( 32* 10000 ) ) << 16 ;
timer &= 0x00FF00FF ;
pwmptr = PWM ;
pwmptr->PWM_CLK = 0x05000000 | timer ; // MCK for DIVA, DIVA = 18 gives 0.5uS clock period @35MHz // MCK/32 / timer = 10000Hz for CLKB
// PWM0 for LED backlight
pwmptr->PWM_CH_NUM[0].PWM_CMR = 0x0000000C ; // CLKB
pwmptr->PWM_CH_NUM[0].PWM_CPDR = 100 ; // Period
pwmptr->PWM_CH_NUM[0].PWM_CPDRUPD = 100 ; // Period
pwmptr->PWM_CH_NUM[0].PWM_CDTY = 40 ; // Duty
pwmptr->PWM_CH_NUM[0].PWM_CDTYUPD = 40 ; // Duty
pwmptr->PWM_ENA = PWM_ENA_CHID0 ; // Enable channel 0
#if !defined(REVA)
// PWM2 for HAPTIC drive 100Hz test
pwmptr->PWM_CH_NUM[2].PWM_CMR = 0x0000000C ; // CLKB
pwmptr->PWM_CH_NUM[2].PWM_CPDR = 100 ; // Period
pwmptr->PWM_CH_NUM[2].PWM_CPDRUPD = 100 ; // Period
pwmptr->PWM_CH_NUM[2].PWM_CDTY = 40 ; // Duty
pwmptr->PWM_CH_NUM[2].PWM_CDTYUPD = 40 ; // Duty
pwmptr->PWM_OOV &= ~0x00040000 ; // Force low
pwmptr->PWM_OSS = 0x00040000 ; // Force low
// pwmptr->PWM_ENA = PWM_ENA_CHID2 ; // Enable channel 2 // TODO on REVA?
#endif
}
// LCD i/o pins
// LCD_RES PC27
// LCD_CS1 PC26
// LCD_E PC12
// LCD_RnW PC13
// LCD_A0 PC15
// LCD_D0 PC0
// LCD_D1 PC7
// LCD_D2 PC6
// LCD_D3 PC5
// LCD_D4 PC4
// LCD_D5 PC3
// LCD_D6 PC2
// LCD_D7 PC1
#define LCD_DATA 0x000000FFL
#if defined(REVA)
#define LCD_A0 0x00008000L
#else
#define LCD_A0 0x00000080L
#endif
#define LCD_RnW 0x00002000L
#define LCD_E 0x00001000L
#define LCD_CS1 0x04000000L
#define LCD_RES 0x08000000L
void configure_pins( uint32_t pins, uint16_t config )
{
register Pio *pioptr ;
pioptr = PIOA + ( ( config & PIN_PORT_MASK ) >> 6) ;
if ( config & PIN_PULLUP )
{
pioptr->PIO_PPDDR = pins ;
pioptr->PIO_PUER = pins ;
}
else
{
pioptr->PIO_PUDR = pins ;
}
if ( config & PIN_PULLDOWN )
{
pioptr->PIO_PUDR = pins ;
pioptr->PIO_PPDER = pins ;
}
else
{
pioptr->PIO_PPDDR = pins ;
}
if ( config & PIN_HIGH )
{
pioptr->PIO_SODR = pins ;
}
else
{
pioptr->PIO_CODR = pins ;
}
if ( config & PIN_INPUT )
{
pioptr->PIO_ODR = pins ;
}
else
{
pioptr->PIO_OER = pins ;
}
if ( config & PIN_PERI_MASK_L )
{
pioptr->PIO_ABCDSR[0] |= pins ;
}
else
{
pioptr->PIO_ABCDSR[0] &= ~pins ;
}
if ( config & PIN_PERI_MASK_H )
{
pioptr->PIO_ABCDSR[1] |= pins ;
}
else
{
pioptr->PIO_ABCDSR[1] &= ~pins ;
}
if ( config & PIN_ENABLE )
{
pioptr->PIO_PER = pins ;
}
else
{
pioptr->PIO_PDR = pins ;
}
}
void boardInit()
{
register Pio *pioptr ;
ResetReason = RSTC->RSTC_SR;
MATRIX->CCFG_SYSIO |= 0x000000F0L ; // Disable syspins, enable B4,5,6,7
PMC->PMC_PCER0 = (1<<ID_PIOC)|(1<<ID_PIOB)|(1<<ID_PIOA)|(1<<ID_UART0) ; // Enable clocks to PIOB and PIOA and PIOC and UART0
#if defined(REVA)
// On REVB, PA21 is used as AD8, and measures current consumption.
pioptr = PIOA ;
pioptr->PIO_PER = PIO_PA21 ; // Enable bit A21 (EXT3)
pioptr->PIO_OER = PIO_PA21 ; // Set bit A21 as output
pioptr->PIO_SODR = PIO_PA21 ; // Set bit A21 ON
#else
pwrInit() ;
#endif
// pioptr->PIO_PUER = 0x80000000 ; // Enable pullup on bit A31 (EXIT)
// pioptr->PIO_PER = 0x80000000 ; // Enable bit A31
pioptr = PIOC ;
pioptr->PIO_PER = PIO_PC25 ; // Enable bit C25 (USB-detect)
// pioptr->PIO_OER = 0x80000000L ; // Set bit C31 as output
// pioptr->PIO_SODR = 0x80000000L ; // Set bit C31
#if defined(REVA)
// Configure RF_power (PC17) and PPM-jack-in (PC19), neither need pullups
pioptr->PIO_PER = 0x000A0000L ; // Enable bit C19, C17
pioptr->PIO_ODR = 0x000A0000L ; // Set bits C19 and C17 as input
#endif
config_free_pins() ;
// Next section configures the key inputs on the LCD data
#if defined(REVA)
pioptr->PIO_PER = 0x0000003DL ; // Enable bits 2,3,4,5, 0
pioptr->PIO_OER = PIO_PC0 ; // Set bit 0 output
pioptr->PIO_ODR = 0x0000003CL ; // Set bits 2, 3, 4, 5 input
pioptr->PIO_PUER = 0x0000003CL ; // Set bits 2, 3, 4, 5 with pullups
#else
pioptr->PIO_PER = 0x0000003BL ; // Enable bits 1,3,4,5, 0
pioptr->PIO_OER = PIO_PC0 ; // Set bit 0 output
pioptr->PIO_ODR = 0x0000003AL ; // Set bits 1, 3, 4, 5 input
pioptr->PIO_PUER = 0x0000003AL ; // Set bits 1, 3, 4, 5 with pullups
#endif
pioptr = PIOB ;
#if defined(REVA)
pioptr->PIO_PUER = PIO_PB6 ; // Enable pullup on bit B6 (MENU)
pioptr->PIO_PER = PIO_PB6 ; // Enable bit B6
#else
pioptr->PIO_PUER = PIO_PB5 ; // Enable pullup on bit B5 (MENU)
pioptr->PIO_PER = PIO_PB5 ; // Enable bit B5
#endif
setup_switches() ;
// Enable PCK2 on PB3, This is for testing of Timer 2 working
// It will be used as serial data to the Bluetooth module
pioptr->PIO_ABCDSR[0] |= PIO_PB3 ; // Peripheral B
pioptr->PIO_ABCDSR[1] &= ~PIO_PB3 ; // Peripheral B
pioptr->PIO_PDR = PIO_PB3 ; // Assign to peripheral
PMC->PMC_SCER |= 0x0400 ; // PCK2 enabled
PMC->PMC_PCK[2] = 2 ; // PCK2 is PLLA
DEBUG_UART_Configure( 9600, Master_frequency ) ;
UART2_Configure( 9600, Master_frequency ) ; // Testing
UART3_Configure( 9600, Master_frequency ) ; // TODO not needed, done after ...
start_timer2() ;
start_timer0() ;
adcInit() ;
init_pwm() ;
__enable_irq() ;
audioInit() ;
coprocInit() ;
eepromInit();
rotencInit();
init_SDcard();
}
#endif
uint8_t temperature = 0; // Raw temp reading
uint8_t maxTemperature = 0 ; // Raw temp reading
#define RX_UART_BUFFER_SIZE 32
struct t_rxUartBuffer
{
uint8_t fifo[RX_UART_BUFFER_SIZE] ;
uint8_t *outPtr ;
} ;
struct t_rxUartBuffer TelemetryInBuffer[2] ;
uint32_t TelemetryActiveBuffer ;
void startPdcUsartReceive()
{
register Usart *pUsart = SECOND_USART;
TelemetryInBuffer[0].outPtr = TelemetryInBuffer[0].fifo ;
TelemetryInBuffer[1].outPtr = TelemetryInBuffer[1].fifo ;
#ifndef SIMU
// TODO because of the 64bits cast ...
pUsart->US_RPR = (uint32_t)TelemetryInBuffer[0].fifo ;
pUsart->US_RNPR = (uint32_t)TelemetryInBuffer[1].fifo ;
#endif
pUsart->US_RCR = RX_UART_BUFFER_SIZE ;
pUsart->US_RNCR = RX_UART_BUFFER_SIZE ;
pUsart->US_PTCR = US_PTCR_RXTEN ;
TelemetryActiveBuffer = 0 ;
}
void endPdcUsartReceive()
{
register Usart *pUsart = SECOND_USART;
pUsart->US_PTCR = US_PTCR_RXTDIS ;
}
void rxPdcUsart( void (*pChProcess)(uint8_t x) )
{
#if !defined(SIMU)
register Usart *pUsart = SECOND_USART;
uint8_t *ptr ;
uint8_t *endPtr ;
// uint32_t bufIndex ;
// uint32_t i ;
uint32_t j ;
//Find out where the DMA has got to
__disable_irq() ;
pUsart->US_PTCR = US_PTCR_RXTDIS ; // Freeze DMA
ptr = (uint8_t *)pUsart->US_RPR ;
j = pUsart->US_RNCR ;
pUsart->US_PTCR = US_PTCR_RXTEN ; // DMA active again
__enable_irq() ;
endPtr = ptr - 1 ;
ptr = TelemetryInBuffer[TelemetryActiveBuffer].outPtr ;
if ( j == 0 ) // First buf is full
{
endPtr = &TelemetryInBuffer[TelemetryActiveBuffer].fifo[RX_UART_BUFFER_SIZE-1] ; // last byte
}
while ( ptr <= endPtr )
{
(*pChProcess)(*ptr++) ;
}
TelemetryInBuffer[TelemetryActiveBuffer].outPtr = ptr ;
if ( j == 0 ) // First buf is full
{
TelemetryInBuffer[TelemetryActiveBuffer].outPtr = TelemetryInBuffer[TelemetryActiveBuffer].fifo ;
pUsart->US_RNPR = (uint32_t)TelemetryInBuffer[TelemetryActiveBuffer].fifo ;
pUsart->US_RNCR = RX_UART_BUFFER_SIZE ;
TelemetryActiveBuffer ^= 1 ; // Other buffer is active
rxPdcUsart( pChProcess ) ; // Get any chars from second buffer
}
#endif
}
uint32_t txPdcUsart( uint8_t *buffer, uint32_t size )
{
register Usart *pUsart = SECOND_USART;
if ( pUsart->US_TNCR == 0 )
{
#ifndef SIMU
pUsart->US_TNPR = (uint32_t)buffer ;
#endif
pUsart->US_TNCR = size ;
pUsart->US_PTCR = US_PTCR_TXTEN ;
return 1 ;
}
return 0 ;
}
uint32_t txPdcPending()
{
register Usart *pUsart = SECOND_USART;
uint32_t x ;
__disable_irq() ;
pUsart->US_PTCR = US_PTCR_TXTDIS ; // Freeze DMA
x = pUsart->US_TNCR ; // Total
x += pUsart->US_TCR ; // Still to send
pUsart->US_PTCR = US_PTCR_TXTEN ; // DMA active again
__enable_irq() ;
return x ;
}
void end_bt_tx_interrupt()
{
Uart *pUart = BT_USART ;
pUart->UART_IDR = UART_IDR_TXBUFE ;
NVIC_DisableIRQ(UART1_IRQn) ;
}
void usbBootloader()
{
// This might be replaced by a software reset
// Any interrupts that have been enabled must be disabled here
// BEFORE calling sam_boot()
rotencEnd();
endPdcUsartReceive() ; // Terminate any serial reception
end_bt_tx_interrupt() ;
stop_trainer_capture() ;
end_spi() ;
audioEnd() ;
TC0->TC_CHANNEL[2].TC_IDR = TC_IDR0_CPCS ;
TC0->TC_CHANNEL[0].TC_CCR = TC_CCR0_CLKDIS ;
TC0->TC_CHANNEL[1].TC_CCR = TC_CCR0_CLKDIS ;
TC0->TC_CHANNEL[2].TC_CCR = TC_CCR0_CLKDIS ;
TC1->TC_CHANNEL[0].TC_CCR = TC_CCR0_CLKDIS ;
TC1->TC_CHANNEL[1].TC_CCR = TC_CCR0_CLKDIS ;
TC1->TC_CHANNEL[2].TC_CCR = TC_CCR0_CLKDIS ;
PWM->PWM_DIS = PWM_DIS_CHID0 | PWM_DIS_CHID1 | PWM_DIS_CHID2 | PWM_DIS_CHID3 ; // Disable all
NVIC_DisableIRQ(TC2_IRQn) ;
disable_ppm(0);
disable_ppm(1);
// PWM->PWM_IDR1 = PWM_IDR1_CHID3 ;
// NVIC_DisableIRQ(PWM_IRQn) ;
disable_ssc() ;
#if !defined(SIMU)
DEBUG_UART_Stop();
UART3_Stop();
#endif
sam_boot() ;
}
#if !defined(REVA)
uint16_t getCurrent()
{
static uint16_t Current ;
static uint32_t Current_sum ;
static uint8_t Current_count ;
Current_sum += anaIn(8); // TODO enum
if (++Current_count >= 50) {
Current = Current_sum / 5 ;
Current_sum = 0 ;
Current_count = 0 ;
}
uint32_t current_scale = 488 + g_eeGeneral.currentCalib ;
return (current_scale * Current) / 8192;
}
#endif
uint8_t getTemperature()
{
return temperature + g_eeGeneral.temperatureCalib;
}
#define STICK_LV_GAIN 0x01
#define STICK_LH_GAIN 0x02
#define STICK_RV_GAIN 0x04
#define STICK_RH_GAIN 0x08
#define GAIN_LV 0x00080000
#define GAIN_LH 0x00000020
#define GAIN_RV 0x20000000
#define GAIN_RH 0x00000008
#define OFF_LV 0x00000200
#define OFF_LH 0x00000004
#define OFF_RV 0x00004000
#define OFF_RH 0x00000002
void setSticksGain(uint8_t gains)
{
register Adc *padc ;
uint32_t gain ;
uint32_t offset ;
gain = 0 ;
offset = 0 ;
padc = ADC ;
if ( gains & STICK_LV_GAIN ) {
gain |= GAIN_LV ;
offset |= OFF_LV ;
}
if ( gains & STICK_LH_GAIN ) {
gain |= GAIN_LH ;
offset |= OFF_LH ;
}
if ( gains & STICK_RV_GAIN ) {
gain |= GAIN_RV ;
offset |= OFF_RV ;
}
if ( gains & STICK_RH_GAIN ) {
gain |= GAIN_RH ;
offset |= OFF_RH ;
}
padc->ADC_CGR = gain;
padc->ADC_COR = offset;
}
+261
View File
@@ -0,0 +1,261 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef board_sky9x_h
#define board_sky9x_h
#include <stdio.h>
#include "board.h"
#include "audio_driver.h"
extern uint16_t ResetReason;
#if defined(REVA)
#define GPIO_BUTTON_MENU PIOB->PIO_PDSR
#define GPIO_BUTTON_EXIT PIOA->PIO_PDSR
#define GPIO_BUTTON_UP PIOC->PIO_PDSR
#define GPIO_BUTTON_DOWN PIOC->PIO_PDSR
#define GPIO_BUTTON_RIGHT PIOC->PIO_PDSR
#define GPIO_BUTTON_LEFT PIOC->PIO_PDSR
#define PIN_BUTTON_MENU 0x00000040
#define PIN_BUTTON_EXIT 0x80000000
#define PIN_BUTTON_UP 0x00000004
#define PIN_BUTTON_DOWN 0x00000008
#define PIN_BUTTON_RIGHT 0x00000010
#define PIN_BUTTON_LEFT 0x00000020
#else
#define GPIO_BUTTON_MENU PIOB->PIO_PDSR
#define GPIO_BUTTON_EXIT PIOC->PIO_PDSR
#define GPIO_BUTTON_UP PIOC->PIO_PDSR
#define GPIO_BUTTON_DOWN PIOC->PIO_PDSR
#define GPIO_BUTTON_RIGHT PIOC->PIO_PDSR
#define GPIO_BUTTON_LEFT PIOC->PIO_PDSR
#define PIN_BUTTON_MENU 0x00000020
#define PIN_BUTTON_EXIT 0x01000000
#define PIN_BUTTON_UP 0x00000002
#define PIN_BUTTON_DOWN 0x00000020
#define PIN_BUTTON_RIGHT 0x00000010
#define PIN_BUTTON_LEFT 0x00000008
#endif
#define GPIO_TRIM_LH_L PIOA->PIO_PDSR
#define GPIO_TRIM_LV_DN PIOA->PIO_PDSR
#define GPIO_TRIM_RV_UP PIOA->PIO_PDSR
#define GPIO_TRIM_RH_L PIOA->PIO_PDSR
#define GPIO_TRIM_LH_R PIOB->PIO_PDSR
#define GPIO_TRIM_LV_UP PIOC->PIO_PDSR
#define GPIO_TRIM_RV_DN PIOC->PIO_PDSR
#define GPIO_TRIM_RH_R PIOC->PIO_PDSR
#if defined(REVA)
#define PIN_TRIM_LH_L 0x00000080
#define PIN_TRIM_LV_DN 0x08000000
#define PIN_TRIM_RV_UP 0x40000000
#define PIN_TRIM_RH_L 0x20000000
#define PIN_TRIM_LH_R 0x00000010
#define PIN_TRIM_LV_UP 0x10000000
#define PIN_TRIM_RV_DN 0x00000400
#define PIN_TRIM_RH_R 0x00000200
#else
#define PIN_TRIM_LH_L 0x00800000
#define PIN_TRIM_LV_DN 0x01000000
#define PIN_TRIM_RV_UP 0x00000002
#define PIN_TRIM_RH_L 0x00000001
#define PIN_TRIM_LH_R 0x00000010
#define PIN_TRIM_LV_UP 0x10000000
#define PIN_TRIM_RV_DN 0x00000400
#define PIN_TRIM_RH_R 0x00000200
#endif
void usbMassStorage();
#define PIN_ENABLE 0x001
#define PIN_PERIPHERAL 0x000
#define PIN_INPUT 0x002
#define PIN_OUTPUT 0x000
#define PIN_PULLUP 0x004
#define PIN_NO_PULLUP 0x000
#define PIN_PULLDOWN 0x008
#define PIN_NO_PULLDOWN 0x000
#define PIN_PERI_MASK_L 0x010
#define PIN_PERI_MASK_H 0x020
#define PIN_PER_A 0x000
#define PIN_PER_B 0x010
#define PIN_PER_C 0x020
#define PIN_PER_D 0x030
#define PIN_PORT_MASK 0x0C0
#define PIN_PORTA 0x000
#define PIN_PORTB 0x040
#define PIN_PORTC 0x080
#define PIN_LOW 0x000
#define PIN_HIGH 0x100
void configure_pins( uint32_t pins, uint16_t config );
uint16_t getCurrent();
extern uint8_t temperature ; // Raw temp reading
extern uint8_t maxTemperature ; // Raw temp reading
uint8_t getTemperature();
#define strcpy_P strcpy
#define strcat_P strcat
#if !defined(REVA)
extern uint16_t Current_analogue;
extern uint16_t Current_max;
extern uint32_t Current_accumulator;
extern uint32_t Current_used;
extern uint16_t sessionTimer;
#endif
#if defined(REVC)
#define BOOTLOADER_REQUEST() (usbPlugged())
#else
#define BOOTLOADER_REQUEST() (pwrCheck() == e_power_usb)
#endif
#define SLAVE_MODE() (pwrCheck() == e_power_trainer)
#define JACK_PPM_OUT() PIOC->PIO_PDR = PIO_PC22
#define JACK_PPM_IN() PIOC->PIO_PER = PIO_PC22
void setSticksGain(uint8_t gains);
// Keys driver
extern uint32_t readKeys();
extern uint32_t readTrims();
#define TRIMS_PRESSED() (readTrims())
#define KEYS_PRESSED() (~readKeys())
#define DBLKEYS_PRESSED_RGT_LFT(i) ((in & (0x20 + 0x40)) == (0x20 + 0x40))
#define DBLKEYS_PRESSED_UP_DWN(i) ((in & (0x10 + 0x08)) == (0x10 + 0x08))
#define DBLKEYS_PRESSED_RGT_UP(i) ((in & (0x20 + 0x10)) == (0x20 + 0x10))
#define DBLKEYS_PRESSED_LFT_DWN(i) ((in & (0x40 + 0x08)) == (0x40 + 0x08))
// Pulses driver
#define init_no_pulses(port) init_main_ppm(3000, 0)
#define disable_no_pulses(port) disable_ppm(0)
void init_main_ppm(uint32_t period, uint32_t out_enable);
#define init_ppm(port) init_main_ppm(3000, 1)
void disable_ppm(uint32_t port);
void init_ssc();
void disable_ssc();
#define init_pxx(port) init_main_ppm(5000, 0); init_ssc()
#define disable_pxx(port) disable_ssc()
#define init_dsm2(port) init_main_ppm(5000, 0); init_ssc()
#define disable_dsm2(port) disable_ssc()
// SD driver
#if defined(SIMU)
#define sdInit()
#define sdDone()
#else
#define sdPoll10ms()
void sdMountPoll();
extern "C" {
void init_SDcard();
void sdInit();
void sdDone();
uint32_t sd_card_ready();
uint32_t sdMounted();
}
#endif
// WDT driver
#if !defined(SIMU)
#define wdt_disable()
#define wdt_enable(x) WDT->WDT_MR = 0x3FFF207F
#define wdt_reset() WDT->WDT_CR = 0xA5000001
#endif
// Backlight driver
#define setBacklight(xx) (PWM->PWM_CH_NUM[0].PWM_CDTYUPD = xx)
#define __BACKLIGHT_ON (PWM->PWM_CH_NUM[0].PWM_CDTY = g_eeGeneral.backlightBright)
#define __BACKLIGHT_OFF (PWM->PWM_CH_NUM[0].PWM_CDTY = 100)
#define IS_BACKLIGHT_ON() (PWM->PWM_CH_NUM[0].PWM_CDTY != 100)
// ADC driver
void adcInit();
void adcRead(void);
//extern uint16_t Analog_values[];
// Buzzer driver
void buzzerSound(uint8_t duration);
void buzzerHeartbeat();
#define BUZZER_HEARTBEAT buzzerHeartbeat
// Coproc driver
void coprocInit();
void coprocWriteData(uint8_t *data, uint32_t size);
void coprocReadData(bool onlytemp=false);
void coprocCheck();
extern int8_t coprocVolumeRequired;
extern uint8_t coprocVolumeReadPending;
extern uint8_t Coproc_read;
extern int8_t Coproc_valid;
extern int8_t Coproc_temp;
extern int8_t Coproc_maxtemp;
// Haptic driver
void hapticOff(void) ;
void hapticOn(uint32_t pwmPercent);
// BlueTooth driver
#if defined(BLUETOOTH)
void btInit();
void btTask(void* pdata);
void btPushByte(uint8_t data);
#endif
// Power driver
void pwrInit();
void pwrOff();
uint32_t pwrCheck();
#define UNEXPECTED_SHUTDOWN() (g_eeGeneral.unexpectedShutdown)
// EEPROM driver
void eepromInit();
// Rotary Encoder driver
void rotencInit();
void rotencEnd();
#if ROTARY_ENCODERS > 0
#define rotencDown() (!(PIOB->PIO_PDSR & 0x40))
#else
#define rotencDown() 0
#endif
#endif
+75
View File
@@ -0,0 +1,75 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../opentx.h"
volatile uint8_t buzzerCount ;
#if defined(REVA)
void buzzerOn()
{
PIOA->PIO_SODR = 0x00010000L ; // Set bit A16 ON
}
void buzzerOff()
{
PIOA->PIO_CODR = 0x00010000L ; // Set bit A16 ON
}
#else
void buzzerOn()
{
PIOA->PIO_SODR = 0x02000000L ; // Set bit A25 ON
}
void buzzerOff()
{
PIOA->PIO_CODR = 0x02000000L ; // Set bit A25 ON
}
#endif
void buzzerSound(uint8_t duration)
{
buzzerOn();
buzzerCount = duration;
}
void buzzerHeartbeat()
{
if (buzzerCount) {
if (--buzzerCount == 0)
buzzerOff();
}
}
+130
View File
@@ -0,0 +1,130 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
/// !Purpose
///
/// Definition of AT91SAM3S4 characteristics and features
///
/// !Usage
/// -# For ARM core feature, see "AT91SAM3S4 - ARM core features".
/// -# For IP features, see "AT91SAM3S4 - IP features".
/// -# For misc, see "AT91SAM3S4 - Misc".
//------------------------------------------------------------------------------
#ifndef CHIP_H
#define CHIP_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "AT91SAM3S4 - ARM core features"
/// This page lists several characteristics related to the ARM core
///
//ARM core features
/// ARM core definition.
#define cortexm3
/// family definition.
#define at91sam3s
//------------------------------------------------------------------------------
/// \page "AT91SAM3S4 - IP features"
/// This page lists several characteristics related to the embedded IP
///
//IP FEATURES
// EFC GPNVM number
#define CHIP_EFC_NUM_GPNVMS 3
/// Indicates chip has an Enhanced EFC.
#define CHIP_FLASH_EEFC
// DMA channels number
#define CHIP_DMA_CHANNEL_NUM 4
// Indicate chip's MCI interface.
#define MCI2_INTERFACE
// Indicate chip SSC has DMA interface.
#define CHIP_SSC_DMA
// Indicate chip SPI has DMA interface.
#define CHIP_SPI_DMA
/// Indicates chip has an UDP Full Speed.
#define CHIP_USB_UDP
/// Indicates chip has an internal pull-up.
#define CHIP_USB_PULLUP_INTERNAL
/// Number of USB endpoints
#define CHIP_USB_NUMENDPOINTS 8
/// Endpoints max paxcket size
#define CHIP_USB_ENDPOINTS_MAXPACKETSIZE(i) \
((i == 0) ? 64 : \
((i == 1) ? 64 : \
((i == 2) ? 64 : \
((i == 3) ? 64 : \
((i == 4) ? 512 : \
((i == 5) ? 512 : \
((i == 6) ? 64 : \
((i == 7) ? 64 : 0 ))))))))
/// Endpoints Number of Bank
#define CHIP_USB_ENDPOINTS_BANKS(i) \
((i == 0) ? 1 : \
((i == 1) ? 2 : \
((i == 2) ? 2 : \
((i == 3) ? 1 : \
((i == 4) ? 2 : \
((i == 5) ? 2 : \
((i == 6) ? 2 : \
((i == 7) ? 2 : 0 ))))))))
//------------------------------------------------------------------------------
/// \page "AT91SAM3S4 - Misc "
/// This page lists misc features
///
//Misc
#endif //#ifndef CHIP_H
+280
View File
@@ -0,0 +1,280 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../../opentx.h"
int8_t coprocVolumeRequired ;
uint8_t coprocVolumeReadPending ;
uint8_t coprocReadDataPending ;
uint8_t coprocWriteDataPending ;
uint8_t CoProc_appgo_pending ;
uint8_t Volume_read ;
uint8_t Coproc_read ;
int8_t Coproc_temp ;
int8_t Coproc_maxtemp=-127 ;
int8_t Coproc_valid ;
bool get_onlytemp;
static uint8_t *Twi_read_address ;
static uint8_t TwiOperation ;
#define TWI_NONE 0
#define TWI_READ_VOL 1
#define TWI_WRITE_VOL 2
#define TWI_READ_COPROC 3
#define TWI_COPROC_APPGO 4
#define TWI_WAIT_STOP 5
#define TWI_WRITE_COPROC 6
// Commands to the coprocessor bootloader/application
#define TWI_CMD_PAGEUPDATE 0x01 // TWI Command to program a flash page
#define TWI_CMD_EXECUTEAPP 0x02 // TWI Command to jump to the application program
#define TWI_CMD_SETREAD_ADDRESS 0x03 // TWI Command to set address to read from
#define TWI_CMD_WRITE_DATA 0x04 // TWI Command send data to the application
#define COPROC_RX_BUXSIZE 22
uint8_t Co_proc_status[COPROC_RX_BUXSIZE] ;
uint8_t *coprocWriteDataPtr ;
uint32_t coprocWriteDataSize ;
// This is called from an interrupt routine, or
// interrupts must be disabled while it is called
// from elsewhere.
void coprocCheck()
{
if ( TWI0->TWI_IMR & TWI_IMR_TXCOMP )
{
return ; // Busy
}
if ( coprocVolumeRequired >= 0 ) // Set volume to this value
{
TWI0->TWI_MMR = 0x002F0000 ; // Device 5E (>>1) and master is writing
TwiOperation = TWI_WRITE_VOL ;
TWI0->TWI_THR = coprocVolumeRequired ; // Send data
coprocVolumeRequired = -1 ;
TWI0->TWI_IER = TWI_IER_TXCOMP ;
TWI0->TWI_CR = TWI_CR_STOP ; // Stop Tx
}
else if (coprocReadDataPending)
{
Coproc_valid = 0 ;
coprocReadDataPending = 0 ;
TWI0->TWI_MMR = 0x00351000 ; // Device 35 and master is reading
TwiOperation = TWI_READ_COPROC ;
#ifndef SIMU
TWI0->TWI_RPR = (uint32_t)&Co_proc_status[0] ;
#endif
TWI0->TWI_RCR = COPROC_RX_BUXSIZE - 1 ;
if ( TWI0->TWI_SR & TWI_SR_RXRDY )
{
(void) TWI0->TWI_RHR ;
}
TWI0->TWI_PTCR = TWI_PTCR_RXTEN ; // Start transfers
TWI0->TWI_CR = TWI_CR_START ; // Start Rx
TWI0->TWI_IER = TWI_IER_RXBUFF | TWI_IER_TXCOMP ;
}
else if (coprocVolumeReadPending)
{
coprocVolumeReadPending = 0 ;
TWI0->TWI_MMR = 0x002F1000 ; // Device 5E (>>1) and master is reading
TwiOperation = TWI_READ_VOL ;
Twi_read_address = &Volume_read ;
TWI0->TWI_CR = TWI_CR_START | TWI_CR_STOP ; // Start and stop Tx
TWI0->TWI_IER = TWI_IER_TXCOMP ;
}
else if ( CoProc_appgo_pending )
{
CoProc_appgo_pending = 0 ;
TWI0->TWI_MMR = 0x00350000 ; // Device 35 and master is writing
TwiOperation = TWI_COPROC_APPGO ;
TWI0->TWI_THR = TWI_CMD_EXECUTEAPP ; // Send appgo command
TWI0->TWI_IER = TWI_IER_TXCOMP ;
TWI0->TWI_CR = TWI_CR_STOP ; // Stop Tx
}
else if ( coprocWriteDataPending )
{
coprocWriteDataPending = 0 ;
TWI0->TWI_MMR = 0x00350000 ; // Device 35 and master is writing
TwiOperation = TWI_WRITE_COPROC ;
#ifndef SIMU
TWI0->TWI_TPR = (uint32_t)coprocWriteDataPtr ;
#endif
TWI0->TWI_TCR = coprocWriteDataSize ;
TWI0->TWI_THR = TWI_CMD_WRITE_DATA ; // Send write command
TWI0->TWI_PTCR = TWI_PTCR_TXTEN ; // Start data transfer
TWI0->TWI_IER = TWI_IER_TXBUFE | TWI_IER_TXCOMP ;
}
}
void coprocReadData(bool onlytemp)
{
get_onlytemp = onlytemp;
coprocReadDataPending = 1 ;
__disable_irq() ;
coprocCheck() ;
__enable_irq() ;
}
void coprocWriteData(uint8_t *data, uint32_t size)
{
coprocWriteDataPtr = data;
coprocWriteDataSize = size;
coprocWriteDataPending = 1;
__disable_irq();
coprocCheck();
__enable_irq();
}
#if 0
void appgo_coprocessor()
{
CoProc_appgo_pending = 1 ;
__disable_irq() ;
coprocCheck() ;
__enable_irq() ;
}
#endif
// Set up for volume control (TWI0)
// Need PA3 and PA4 set to peripheral A
void coprocInit()
{
register Pio *pioptr ;
register uint32_t timing ;
PMC->PMC_PCER0 |= 0x00080000L ; // Enable peripheral clock to TWI0
/* Configure PIO */
pioptr = PIOA ;
pioptr->PIO_ABCDSR[0] &= ~0x00000018 ; // Peripheral A
pioptr->PIO_ABCDSR[1] &= ~0x00000018 ; // Peripheral A
pioptr->PIO_PDR = 0x00000018 ; // Assign to peripheral
timing = Master_frequency * 5 / 1000000 ; // 5uS high and low
timing += 15 - 4 ;
timing /= 16 ;
timing |= timing << 8 ;
TWI0->TWI_CWGR = 0x00040000 | timing ; // TWI clock set
TWI0->TWI_CR = TWI_CR_MSEN | TWI_CR_SVDIS ; // Master mode enable
TWI0->TWI_MMR = 0x002F0000 ; // Device 5E (>>1) and master is writing
NVIC_EnableIRQ(TWI0_IRQn) ;
}
#if !defined(SIMU)
extern "C" void TWI0_IRQHandler()
{
if ( TwiOperation == TWI_READ_VOL )
{
if ( TWI0->TWI_SR & TWI_SR_RXRDY )
{
*Twi_read_address = TWI0->TWI_RHR ; // Read data
}
}
if ( TwiOperation == TWI_READ_COPROC )
{
if ( TWI0->TWI_SR & TWI_SR_RXBUFF )
{
TWI0->TWI_IDR = TWI_IDR_RXBUFF ;
TwiOperation = TWI_WAIT_STOP ;
TWI0->TWI_CR = TWI_CR_STOP ; // Stop Rx
TWI0->TWI_RCR = 1 ; // Last byte
return ;
}
else
{
Coproc_valid = -1 ;
}
}
if ( TwiOperation == TWI_WAIT_STOP )
{
Coproc_valid = 1 ;
Coproc_read = Co_proc_status[0] ;
if ( Coproc_read & 0x80 ) {
// Bootloader
CoProc_appgo_pending = 1 ; // Action application
}
else {
// Got data from tiny app
// Set the date and time
struct gtm utm;
if (!get_onlytemp) {
utm.tm_sec = Co_proc_status[1] ;
utm.tm_min = Co_proc_status[2] ;
utm.tm_hour = Co_proc_status[3] ;
utm.tm_mday = Co_proc_status[4] ;
utm.tm_mon = Co_proc_status[5] - 1;
utm.tm_year = (Co_proc_status[6] + ( Co_proc_status[7] << 8 )) - 1900;
g_rtcTime = gmktime(&utm);
}
Coproc_temp = Co_proc_status[8];
if (Coproc_temp > Coproc_maxtemp)
Coproc_maxtemp=Coproc_temp;
}
TWI0->TWI_PTCR = TWI_PTCR_RXTDIS ; // Stop transfers
if ( TWI0->TWI_SR & TWI_SR_RXRDY ) {
(void) TWI0->TWI_RHR ; // Discard any rubbish data
}
}
// if ( TwiOperation == TWI_WRITE_VOL )
// {
// }
if ( TwiOperation == TWI_WRITE_COPROC )
{
if ( TWI0->TWI_SR & TWI_SR_TXBUFE )
{
TWI0->TWI_IDR = TWI_IDR_TXBUFE ;
TWI0->TWI_CR = TWI_CR_STOP ; // Stop Tx
TWI0->TWI_PTCR = TWI_PTCR_TXTDIS ; // Stop transfers
TwiOperation = TWI_NONE ;
return ;
}
}
TWI0->TWI_IDR = TWI_IDR_TXCOMP | TWI_IDR_TXBUFE | TWI_IDR_RXBUFF ;
TWI0->TWI_PTCR = TWI_PTCR_TXTDIS | TWI_PTCR_RXTDIS ; // Stop transfers
if ( TWI0->TWI_SR & TWI_SR_NACK )
{
}
TwiOperation = TWI_NONE ;
coprocCheck() ;
}
#endif
+831
View File
@@ -0,0 +1,831 @@
/**************************************************************************//**
* @file core_cm3.c
* @brief CMSIS Cortex-M3 Core Peripheral Access Layer Source File
* @version V1.30
* @date 30. October 2009
*
* @note
* Copyright (C) 2009 ARM Limited. All rights reserved.
*
* @par
* ARM Limited (ARM) is supplying this software for use with Cortex-M
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* @par
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#include <stdint.h>
/* define compiler specific symbols */
#if defined ( __CC_ARM )
#define __ASM __asm /*!< asm keyword for ARM Compiler */
#define __INLINE __inline /*!< inline keyword for ARM Compiler */
#elif defined ( __ICCARM__ )
#define __ASM __asm /*!< asm keyword for IAR Compiler */
#define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */
#elif defined ( __GNUC__ )
#define __ASM __asm /*!< asm keyword for GNU Compiler */
#define __INLINE inline /*!< inline keyword for GNU Compiler */
#elif defined ( __TASKING__ )
#define __ASM __asm /*!< asm keyword for TASKING Compiler */
#define __INLINE inline /*!< inline keyword for TASKING Compiler */
#endif
uint32_t __get_PSP(void) ;
void __set_PSP(uint32_t topOfProcStack) ;
uint32_t __get_MSP(void) ;
void __set_MSP(uint32_t mainStackPointer) ;
uint32_t __REV16(uint16_t value) ;
int32_t __REVSH(int16_t value) ;
uint32_t __RBIT(uint32_t value) ;
uint8_t __LDREXB(uint8_t *addr) ;
uint16_t __LDREXH(uint16_t *addr) ;
uint32_t __LDREXW(uint32_t *addr) ;
uint32_t __STREXB(uint8_t value, uint8_t *addr) ;
uint32_t __STREXH(uint16_t value, uint16_t *addr) ;
uint32_t __STREXW(uint32_t value, uint32_t *addr) ;
uint32_t __get_BASEPRI(void) ;
void __set_BASEPRI(uint32_t basePri) ;
uint32_t __get_PRIMASK(void) ;
void __set_PRIMASK(uint32_t priMask) ;
uint32_t __get_FAULTMASK(void) ;
void __set_FAULTMASK(uint32_t faultMask) ;
uint32_t __get_CONTROL(void) ;
void __set_CONTROL(uint32_t control) ;
uint32_t __REV(uint32_t value) ;
void revert_osc( void ) ;
void sam_boot( void ) ;
/* ################### Compiler specific Intrinsics ########################### */
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/* ARM armcc specific functions */
/**
* @brief Return the Process Stack Pointer
*
* @return ProcessStackPointer
*
* Return the actual process stack pointer
*/
__ASM uint32_t __get_PSP(void)
{
mrs r0, psp
bx lr
}
/**
* @brief Set the Process Stack Pointer
*
* @param topOfProcStack Process Stack Pointer
*
* Assign the value ProcessStackPointer to the MSP
* (process stack pointer) Cortex processor register
*/
__ASM void __set_PSP(uint32_t topOfProcStack)
{
msr psp, r0
bx lr
}
/**
* @brief Return the Main Stack Pointer
*
* @return Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
__ASM uint32_t __get_MSP(void)
{
mrs r0, msp
bx lr
}
/**
* @brief Set the Main Stack Pointer
*
* @param topOfMainStack Main Stack Pointer
*
* Assign the value mainStackPointer to the MSP
* (main stack pointer) Cortex processor register
*/
__ASM void __set_MSP(uint32_t mainStackPointer)
{
msr msp, r0
bx lr
}
/**
* @brief Reverse byte order in unsigned short value
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in unsigned short value
*/
__ASM uint32_t __REV16(uint16_t value)
{
rev16 r0, r0
bx lr
}
/**
* @brief Reverse byte order in signed short value with sign extension to integer
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in signed short value with sign extension to integer
*/
__ASM int32_t __REVSH(int16_t value)
{
revsh r0, r0
bx lr
}
#if (__ARMCC_VERSION < 400000)
/**
* @brief Remove the exclusive lock created by ldrex
*
* Removes the exclusive lock which is created by ldrex.
*/
__ASM void __CLREX(void)
{
clrex
}
/**
* @brief Return the Base Priority value
*
* @return BasePriority
*
* Return the content of the base priority register
*/
__ASM uint32_t __get_BASEPRI(void)
{
mrs r0, basepri
bx lr
}
/**
* @brief Set the Base Priority value
*
* @param basePri BasePriority
*
* Set the base priority register
*/
__ASM void __set_BASEPRI(uint32_t basePri)
{
msr basepri, r0
bx lr
}
/**
* @brief Return the Priority Mask value
*
* @return PriMask
*
* Return state of the priority mask bit from the priority mask register
*/
__ASM uint32_t __get_PRIMASK(void)
{
mrs r0, primask
bx lr
}
/**
* @brief Set the Priority Mask value
*
* @param priMask PriMask
*
* Set the priority mask bit in the priority mask register
*/
__ASM void __set_PRIMASK(uint32_t priMask)
{
msr primask, r0
bx lr
}
/**
* @brief Return the Fault Mask value
*
* @return FaultMask
*
* Return the content of the fault mask register
*/
__ASM uint32_t __get_FAULTMASK(void)
{
mrs r0, faultmask
bx lr
}
/**
* @brief Set the Fault Mask value
*
* @param faultMask faultMask value
*
* Set the fault mask register
*/
__ASM void __set_FAULTMASK(uint32_t faultMask)
{
msr faultmask, r0
bx lr
}
/**
* @brief Return the Control Register value
*
* @return Control value
*
* Return the content of the control register
*/
__ASM uint32_t __get_CONTROL(void)
{
mrs r0, control
bx lr
}
/**
* @brief Set the Control Register value
*
* @param control Control value
*
* Set the control register
*/
__ASM void __set_CONTROL(uint32_t control)
{
msr control, r0
bx lr
}
#endif /* __ARMCC_VERSION */
#elif (defined (__ICCARM__)) /*------------------ ICC Compiler -------------------*/
/* IAR iccarm specific functions */
#pragma diag_suppress=Pe940
/**
* @brief Return the Process Stack Pointer
*
* @return ProcessStackPointer
*
* Return the actual process stack pointer
*/
uint32_t __get_PSP(void)
{
__ASM("mrs r0, psp");
__ASM("bx lr");
}
/**
* @brief Set the Process Stack Pointer
*
* @param topOfProcStack Process Stack Pointer
*
* Assign the value ProcessStackPointer to the MSP
* (process stack pointer) Cortex processor register
*/
void __set_PSP(uint32_t topOfProcStack)
{
__ASM("msr psp, r0");
__ASM("bx lr");
}
/**
* @brief Return the Main Stack Pointer
*
* @return Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
uint32_t __get_MSP(void)
{
__ASM("mrs r0, msp");
__ASM("bx lr");
}
/**
* @brief Set the Main Stack Pointer
*
* @param topOfMainStack Main Stack Pointer
*
* Assign the value mainStackPointer to the MSP
* (main stack pointer) Cortex processor register
*/
void __set_MSP(uint32_t topOfMainStack)
{
__ASM("msr msp, r0");
__ASM("bx lr");
}
/**
* @brief Reverse byte order in unsigned short value
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in unsigned short value
*/
uint32_t __REV16(uint16_t value)
{
__ASM("rev16 r0, r0");
__ASM("bx lr");
}
/**
* @brief Reverse bit order of value
*
* @param value value to reverse
* @return reversed value
*
* Reverse bit order of value
*/
uint32_t __RBIT(uint32_t value)
{
__ASM("rbit r0, r0");
__ASM("bx lr");
}
/**
* @brief LDR Exclusive (8 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 8 bit values)
*/
uint8_t __LDREXB(uint8_t *addr)
{
__ASM("ldrexb r0, [r0]");
__ASM("bx lr");
}
/**
* @brief LDR Exclusive (16 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 16 bit values
*/
uint16_t __LDREXH(uint16_t *addr)
{
__ASM("ldrexh r0, [r0]");
__ASM("bx lr");
}
/**
* @brief LDR Exclusive (32 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 32 bit values
*/
uint32_t __LDREXW(uint32_t *addr)
{
__ASM("ldrex r0, [r0]");
__ASM("bx lr");
}
/**
* @brief STR Exclusive (8 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 8 bit values
*/
uint32_t __STREXB(uint8_t value, uint8_t *addr)
{
__ASM("strexb r0, r0, [r1]");
__ASM("bx lr");
}
/**
* @brief STR Exclusive (16 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 16 bit values
*/
uint32_t __STREXH(uint16_t value, uint16_t *addr)
{
__ASM("strexh r0, r0, [r1]");
__ASM("bx lr");
}
/**
* @brief STR Exclusive (32 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 32 bit values
*/
uint32_t __STREXW(uint32_t value, uint32_t *addr)
{
__ASM("strex r0, r0, [r1]");
__ASM("bx lr");
}
#pragma diag_default=Pe940
#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
/* GNU gcc specific functions */
/**
* @brief Return the Process Stack Pointer
*
* @return ProcessStackPointer
*
* Return the actual process stack pointer
*/
/*extern uint32_t __get_PSP(void) __attribute__( ( naked ) ); */
uint32_t __get_PSP(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, psp\n\t"
"MOV r0, %0 \n\t"
"BX lr \n\t" : "=r" (result) );
return(result);
}
/**
* @brief Set the Process Stack Pointer
*
* @param topOfProcStack Process Stack Pointer
*
* Assign the value ProcessStackPointer to the MSP
* (process stack pointer) Cortex processor register
*/
/*void __set_PSP(uint32_t topOfProcStack) __attribute__( ( naked ) ); */
void __set_PSP(uint32_t topOfProcStack)
{
__ASM volatile ("MSR psp, %0\n\t"
"BX lr \n\t" : : "r" (topOfProcStack) );
}
/**
* @brief Return the Main Stack Pointer
*
* @return Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
/*uint32_t __get_MSP(void) __attribute__( ( naked ) ); */
uint32_t __get_MSP(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, msp\n\t"
"MOV r0, %0 \n\t"
"BX lr \n\t" : "=r" (result) );
return(result);
}
/**
* @brief Set the Main Stack Pointer
*
* @param topOfMainStack Main Stack Pointer
*
* Assign the value mainStackPointer to the MSP
* (main stack pointer) Cortex processor register
*/
/*void __set_MSP(uint32_t topOfMainStack) __attribute__( ( naked ) ); */
void __set_MSP(uint32_t topOfMainStack)
{
__ASM volatile ("MSR msp, %0\n\t"
"BX lr \n\t" : : "r" (topOfMainStack) );
}
/**
* @brief Return the Base Priority value
*
* @return BasePriority
*
* Return the content of the base priority register
*/
uint32_t __get_BASEPRI(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, basepri_max" : "=r" (result) );
return(result);
}
/**
* @brief Set the Base Priority value
*
* @param basePri BasePriority
*
* Set the base priority register
*/
void __set_BASEPRI(uint32_t value)
{
__ASM volatile ("MSR basepri, %0" : : "r" (value) );
}
/**
* @brief Return the Priority Mask value
*
* @return PriMask
*
* Return state of the priority mask bit from the priority mask register
*/
uint32_t __get_PRIMASK(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, primask" : "=r" (result) );
return(result);
}
/**
* @brief Set the Priority Mask value
*
* @param priMask PriMask
*
* Set the priority mask bit in the priority mask register
*/
void __set_PRIMASK(uint32_t priMask)
{
__ASM volatile ("MSR primask, %0" : : "r" (priMask) );
}
/**
* @brief Return the Fault Mask value
*
* @return FaultMask
*
* Return the content of the fault mask register
*/
uint32_t __get_FAULTMASK(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, faultmask" : "=r" (result) );
return(result);
}
/**
* @brief Set the Fault Mask value
*
* @param faultMask faultMask value
*
* Set the fault mask register
*/
void __set_FAULTMASK(uint32_t faultMask)
{
__ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) );
}
/**
* @brief Return the Control Register value
*
* @return Control value
*
* Return the content of the control register
*/
uint32_t __get_CONTROL(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, control" : "=r" (result) );
return(result);
}
/**
* @brief Set the Control Register value
*
* @param control Control value
*
* Set the control register
*/
void __set_CONTROL(uint32_t control)
{
__ASM volatile ("MSR control, %0" : : "r" (control) );
}
/**
* @brief Reverse byte order in integer value
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in integer value
*/
uint32_t __REV(uint32_t value)
{
uint32_t result=0;
__ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief Reverse byte order in unsigned short value
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in unsigned short value
*/
uint32_t __REV16(uint16_t value)
{
uint32_t result=0;
__ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief Reverse byte order in signed short value with sign extension to integer
*
* @param value value to reverse
* @return reversed value
*
* Reverse byte order in signed short value with sign extension to integer
*/
int32_t __REVSH(int16_t value)
{
uint32_t result=0;
__ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief Reverse bit order of value
*
* @param value value to reverse
* @return reversed value
*
* Reverse bit order of value
*/
uint32_t __RBIT(uint32_t value)
{
uint32_t result=0;
__ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief LDR Exclusive (8 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 8 bit value
*/
uint8_t __LDREXB(uint8_t *addr)
{
uint8_t result=0;
__ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/**
* @brief LDR Exclusive (16 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 16 bit values
*/
uint16_t __LDREXH(uint16_t *addr)
{
uint16_t result=0;
__ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/**
* @brief LDR Exclusive (32 bit)
*
* @param *addr address pointer
* @return value of (*address)
*
* Exclusive LDR command for 32 bit values
*/
uint32_t __LDREXW(uint32_t *addr)
{
uint32_t result=0;
__ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/**
* @brief STR Exclusive (8 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 8 bit values
*/
uint32_t __STREXB(uint8_t value, uint8_t *addr)
{
uint32_t result=0;
__ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
return(result);
}
/**
* @brief STR Exclusive (16 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 16 bit values
*/
uint32_t __STREXH(uint16_t value, uint16_t *addr)
{
uint32_t result=0;
__ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
return(result);
}
/**
* @brief STR Exclusive (32 bit)
*
* @param value value to store
* @param *addr address pointer
* @return successful / failed
*
* Exclusive STR command for 32 bit values
*/
uint32_t __STREXW(uint32_t value, uint32_t *addr)
{
uint32_t result=0;
__ASM volatile ("strex %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
}
void sam_boot()
{
revert_osc() ;
__ASM(" mov.w r1, #8388608");
__ASM(" movw r0, #60680");
__ASM(" movt r0, #57344");
__ASM(" str r1, [r0, #0]"); // Set the VTOR
__ASM("mov.w r3, #0");
__ASM("movt r3, #128");
__ASM("ldr r0, [r3, #0]");
__ASM("msr msp, r0");
__ASM("ldr r0, [r3, #4]");
__ASM("mov.w r3, #1");
__ASM("orr r0, r3");
__ASM("bx r0");
}
#elif (defined (__TASKING__)) /*------------------ TASKING Compiler ---------------------*/
/* TASKING carm specific functions */
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all instrinsics,
* Including the CMSIS ones.
*/
#endif
File diff suppressed because it is too large Load Diff
+147
View File
@@ -0,0 +1,147 @@
/****************************************************************************
* Copyright (c) 2011 by Michael Fischer. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
****************************************************************************
* History:
*
* 09.04.2011 mifi First Version
* 29.04.2011 mifi Call SystemInit, and set the Vector Table Offset
* before copy of data and bss segment.
****************************************************************************/
#define __CRT_C__
#include <stdint.h>
/*=========================================================================*/
/* DEFINE: All extern Data */
/*=========================================================================*/
/*
* The next data are defined by the linker script.
*/
extern unsigned long _stext;
extern unsigned long _etext;
extern unsigned long _sdata;
extern unsigned long _edata;
extern unsigned long _sbss;
extern unsigned long _ebss;
extern unsigned long _estack;
/* This is the main */
extern int main (void);
/*=========================================================================*/
/* DEFINE: Prototypes */
/*=========================================================================*/
extern uint32_t SystemInit (void) ; // __attribute__((weak));
/*=========================================================================*/
/* DEFINE: All code exported */
/*=========================================================================*/
/***************************************************************************/
/* SystemInit */
/* */
/* SystemInit is a function which is provided by the CMSIS interface. */
/* If this function is not available, we need a function here to prevent */
/* an error of the linker. Therefore this function is declared as weak. */
/***************************************************************************/
//uint32_t SystemInit (void)
//{
//} /* SystemInit */
extern uint32_t Master_frequency ;
/***************************************************************************/
/* ResetHandler */
/* */
/* This function is used for the C runtime initialisation, */
/* for handling the .data and .bss segments. */
/***************************************************************************/
void ResetHandler (void)
{
{
register uint32_t *pSrc;
register uint32_t *pDest;
register uint32_t m_freq ;
/*
* Call the SystemInit code from CMSIS interface if available.
* SystemInit is a week function which can be override
* by an external function.
*/
m_freq = SystemInit();
/*
* Set the "Vector Table Offset Register". From the ARM
* documentation, we got the following information:
*
* Use the Vector Table Offset Register to determine:
* - if the vector table is in RAM or code memory
* - the vector table offset.
*/
*((uint32_t*)0xE000ED08) = (uint32_t)&_stext;
/*
* Copy the initialized data of the ".data" segment
* from the flash to the are in the ram.
*/
pSrc = &_etext;
pDest = &_sdata;
while(pDest < &_edata)
{
*pDest++ = *pSrc++;
}
/*
* Clear the ".bss" segment.
*/
pDest = &_sbss;
while(pDest < &_ebss)
{
*pDest++ = 0;
}
Master_frequency = m_freq ;
}
/*
* And now the main function can be called.
* Scotty, energie...
*/
main();
/*
* In case there are problems with the
* "warp drive", stop here.
*/
while(1) {};
} /* ResetHandler */
/*** EOF ***/
+109
View File
@@ -0,0 +1,109 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../opentx.h"
#include <stdarg.h>
#if !defined(SIMU)
extern Fifo<512> debugRxFifo;
/*
* Outputs a character on the UART line.
*
* This function is synchronous (i.e. uses polling).
* c Character to send.
*/
void debugPutc(const char c)
{
Uart *pUart = CONSOLE_USART;
/* Wait for the transmitter to be ready */
while ( (pUart->UART_SR & UART_SR_TXEMPTY) == 0 ) ;
/* Send character */
pUart->UART_THR = c;
}
/**
* Configures a UART peripheral with the specified parameters.
*
* baudrate Baudrate at which the UART should operate (in Hz).
* masterClock Frequency of the system master clock (in Hz).
* uses PA9 and PA10, RXD2 and TXD2
*/
void DEBUG_UART_Configure( uint32_t baudrate, uint32_t masterClock)
{
register Uart *pUart = CONSOLE_USART;
/* Configure PIO */
configure_pins( (PIO_PA9 | PIO_PA10), PIN_PERIPHERAL | PIN_INPUT | PIN_PER_A | PIN_PORTA | PIN_NO_PULLUP ) ;
/* Configure PMC */
PMC->PMC_PCER0 = 1 << CONSOLE_ID;
/* Reset and disable receiver & transmitter */
pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX
| UART_CR_RXDIS | UART_CR_TXDIS;
/* Configure mode */
pUart->UART_MR = 0x800 ; // NORMAL, No Parity
/* Configure baudrate */
/* Asynchronous, no oversampling */
pUart->UART_BRGR = (masterClock / baudrate) / 16;
/* Disable PDC channel */
pUart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
/* Enable receiver and transmitter */
pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
pUart->UART_IER = UART_IER_RXRDY ;
NVIC_EnableIRQ(UART0_IRQn) ;
}
void DEBUG_UART_Stop()
{
CONSOLE_USART->UART_IDR = UART_IDR_RXRDY ;
NVIC_DisableIRQ(UART0_IRQn) ;
}
extern "C" void UART0_IRQHandler()
{
debugRxFifo.push(CONSOLE_USART->UART_RHR);
}
#endif
File diff suppressed because it is too large Load Diff
+276
View File
@@ -0,0 +1,276 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../../opentx.h"
extern volatile uint32_t Spi_complete; // TODO in the driver ?
uint32_t spi_PDC_action( register uint8_t *command, register uint8_t *tx, register uint8_t *rx, register uint32_t comlen, register uint32_t count )
{
#ifndef SIMU
register Spi *spiptr ;
register uint32_t condition ;
static uint8_t discard_rx_command[4] ;
// PMC->PMC_PCER0 |= 0x00200000L ; // Enable peripheral clock to SPI
Spi_complete = 0 ;
if ( comlen > 4 )
{
Spi_complete = 1 ;
return 0x4FFFF ;
}
condition = SPI_SR_TXEMPTY ;
spiptr = SPI ;
spiptr->SPI_CR = 1 ; // Enable
(void) spiptr->SPI_RDR ; // Dump any rx data
(void) spiptr->SPI_SR ; // Clear error flags
spiptr->SPI_RPR = (uint32_t)discard_rx_command ;
spiptr->SPI_RCR = comlen ;
if ( rx )
{
spiptr->SPI_RNPR = (uint32_t)rx ;
spiptr->SPI_RNCR = count ;
condition = SPI_SR_RXBUFF ;
}
spiptr->SPI_TPR = (uint32_t)command ;
spiptr->SPI_TCR = comlen ;
if ( tx )
{
spiptr->SPI_TNPR = (uint32_t)tx ;
}
else
{
spiptr->SPI_TNPR = (uint32_t)rx ;
}
spiptr->SPI_TNCR = count ;
spiptr->SPI_PTCR = SPI_PTCR_RXTEN | SPI_PTCR_TXTEN ; // Start transfers
// Wait for things to get started, avoids early interrupt
for ( count = 0 ; count < 1000 ; count += 1 )
{
if ( ( spiptr->SPI_SR & SPI_SR_TXEMPTY ) == 0 )
{
break ;
}
}
spiptr->SPI_IER = condition ;
#endif
return 0 ;
}
uint32_t spi_operation( register uint8_t *tx, register uint8_t *rx, register uint32_t count )
{
register Spi *spiptr;
register uint32_t result;
result = 0;
spiptr = SPI;
spiptr->SPI_CR = 1; // Enable
(void) spiptr->SPI_RDR; // Dump any rx data
while (count) {
result = 0;
while ((spiptr->SPI_SR & SPI_SR_TXEMPTY) == 0) {
// wait
if (++result > 10000) {
result = 0xFFFF;
break;
}
}
if (result > 10000) {
break;
}
spiptr->SPI_TDR = *tx++;
result = 0;
while ((spiptr->SPI_SR & SPI_SR_RDRF) == 0) {
// wait for received
if (++result > 10000) {
result = 0x2FFFF;
break;
}
}
if (result > 10000) {
break;
}
*rx++ = spiptr->SPI_RDR;
count -= 1;
}
if (result <= 10000) {
result = 0;
}
spiptr->SPI_CR = 2; // Disable
return result ;
}
uint32_t eeprom_write_one(uint8_t byte, uint8_t count)
{
#ifndef SIMU
register Spi *spiptr;
register uint32_t result;
spiptr = SPI;
spiptr->SPI_CR = 1; // Enable
(void) spiptr->SPI_RDR; // Dump any rx data
spiptr->SPI_TDR = byte;
result = 0;
while ((spiptr->SPI_SR & SPI_SR_RDRF) == 0) {
// wait for received
if (++result > 10000) {
break;
}
}
if (count == 0) {
spiptr->SPI_CR = 2; // Disable
return spiptr->SPI_RDR;
}
(void) spiptr->SPI_RDR; // Dump the rx data
spiptr->SPI_TDR = 0;
result = 0;
while ((spiptr->SPI_SR & SPI_SR_RDRF) == 0) {
// wait for received
if (++result > 10000) {
break;
}
}
spiptr->SPI_CR = 2; // Disable
return spiptr->SPI_RDR ;
#else
return !Spi_complete;
#endif
}
void eeprom_write_enable()
{
eeprom_write_one(6, 0);
}
uint32_t eeprom_read_status()
{
return eeprom_write_one(5, 1);
}
// SPI i/f to EEPROM (4Mb)
// Peripheral ID 21 (0x00200000)
// Connections:
// SS PA11 (peripheral A)
// MISO PA12 (peripheral A)
// MOSI PA13 (peripheral A)
// SCK PA14 (peripheral A)
// Set clock to 3 MHz, AT25 device is rated to 70MHz, 18MHz would be better
void eepromInit()
{
register Spi *spiptr ;
register uint32_t timer ;
register uint8_t *p ;
uint8_t spi_buf[4] ;
PMC->PMC_PCER0 |= 0x00200000L ; // Enable peripheral clock to SPI
/* Configure PIO */
configure_pins( 0x00007800, PIN_PERIPHERAL | PIN_INPUT | PIN_PER_A | PIN_PORTA | PIN_NO_PULLUP ) ;
spiptr = SPI ;
timer = ( Master_frequency / 3000000 ) << 8 ; // Baud rate 3Mb/s
spiptr->SPI_MR = 0x14000011 ; // 0001 0100 0000 0000 0000 0000 0001 0001 Master
spiptr->SPI_CSR[0] = 0x01180009 | timer ; // 0000 0001 0001 1000 xxxx xxxx 0000 1001
NVIC_EnableIRQ(SPI_IRQn) ;
p = spi_buf ;
// *p = 0x39 ; // Unprotect sector command
// *(p+1) = 0 ;
// *(p+2) = 0 ;
// *(p+3) = 0 ; // 3 bytes address
// spi_operation( p, spi_buf, 4 ) ;
eeprom_write_enable() ;
*p = 1 ; // Write status register command
*(p+1) = 0 ;
spi_operation( p, spi_buf, 2 ) ;
}
#ifndef SIMU
extern "C" void SPI_IRQHandler()
{
register Spi *spiptr ;
spiptr = SPI ;
SPI->SPI_IDR = 0x07FF ; // All interrupts off
spiptr->SPI_CR = 2 ; // Disable
(void) spiptr->SPI_RDR ; // Dump any rx data
(void) spiptr->SPI_SR ; // Clear error flags
spiptr->SPI_PTCR = SPI_PTCR_RXTDIS | SPI_PTCR_TXTDIS ; // Stop tramsfers
Spi_complete = 1 ; // Indicate completion
// Power save
// PMC->PMC_PCER0 &= ~0x00200000L ; // Disable peripheral clock to SPI
}
#endif
void end_spi()
{
SPI->SPI_CR = 2 ; // Disable
SPI->SPI_IDR = 0x07FF ; // All interrupts off
NVIC_DisableIRQ(SPI_IRQn) ;
}
#if 0
uint32_t unprotect_eeprom()
{
register uint8_t *p;
eeprom_write_enable();
p = Spi_tx_buf;
*p = 0x39; // Unprotect sector command
*(p + 1) = 0;
*(p + 2) = 0;
*(p + 3) = 0; // 3 bytes address
return spi_operation( p, Spi_rx_buf, 4 ) ;
}
#endif
+59
View File
@@ -0,0 +1,59 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../../opentx.h"
void hapticOff()
{
PWM->PWM_DIS = PWM_DIS_CHID2 ; // Disable channel 2
PWM->PWM_OOV &= ~0x00040000 ; // Force low
PWM->PWM_OSS |= 0x00040000 ; // Force low
}
// pwmPercent 0-100
void hapticOn( uint32_t pwmPercent )
{
register Pwm *pwmptr ;
pwmptr = PWM ;
if (pwmPercent > 100)
pwmPercent = 100 ;
pwmptr->PWM_CH_NUM[2].PWM_CDTYUPD = pwmPercent ; // Duty
pwmptr->PWM_ENA = PWM_ENA_CHID2 ; // Enable channel 2
pwmptr->PWM_OSC = 0x00040000 ; // Enable output
}
+224
View File
@@ -0,0 +1,224 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../../opentx.h"
// keys:
// KEY_EXIT PA31 (PC24)
// KEY_MENU PB6 (PB5)
// KEY_DOWN LCD5 PC3 (PC5)
// KEY_UP LCD6 PC2 (PC1)
// KEY_RIGHT LCD4 PC4 (PC4)
// KEY_LEFT LCD3 PC5 (PC3)
// Reqd. bit 6 LEFT, 5 RIGHT, 4 UP, 3 DOWN 2 EXIT 1 MENU
// LCD pins 5 DOWN, 4 RIGHT, 3 LEFT, 1 UP
uint32_t readKeys()
{
register uint32_t x;
register uint32_t result = 0;
x = lcdLock ? lcdInputs : PIOC->PIO_PDSR; // 6 LEFT, 5 RIGHT, 4 DOWN, 3 UP ()
#if defined(REVA)
if (x & PIN_BUTTON_RIGHT)
result |= 0x02 << KEY_RIGHT;
if (x & PIN_BUTTON_LEFT)
result |= 0x02 << KEY_LEFT;
if (x & PIN_BUTTON_UP)
result |= 0x02 << KEY_UP;
if (x & PIN_BUTTON_DOWN)
result |= 0x02 << KEY_DOWN;
if (GPIO_BUTTON_EXIT & PIN_BUTTON_EXIT)
result |= 0x02 << KEY_EXIT;
if (GPIO_BUTTON_MENU & 0x000000040)
result |= 0x02 << KEY_MENU;
#else
if (x & PIN_BUTTON_RIGHT)
result |= 0x02 << KEY_RIGHT;
if (x & PIN_BUTTON_UP)
result |= 0x02 << KEY_UP;
if (x & PIN_BUTTON_LEFT)
result |= 0x02 << KEY_LEFT;
if (x & PIN_BUTTON_DOWN)
result |= 0x02 << KEY_DOWN;
if (x & PIN_BUTTON_EXIT)
result |= 0x02 << KEY_EXIT;
if (GPIO_BUTTON_MENU & PIN_BUTTON_MENU)
result |= 0x02 << KEY_MENU;
#endif
// printf("readKeys(): %x => %x\n", x, result); fflush(stdout);
return result;
}
uint32_t readTrims()
{
register uint32_t a = PIOA->PIO_PDSR;
register uint32_t b = PIOB->PIO_PDSR;
register uint32_t c = PIOC->PIO_PDSR;
register uint32_t result = 0;
if (~a & PIN_TRIM_LH_L)
result |= 0x01;
if (~a & PIN_TRIM_LV_DN)
result |= 0x04;
if (~a & PIN_TRIM_RV_UP)
result |= 0x20;
if (~a & PIN_TRIM_RH_L)
result |= 0x40;
if (~b & PIN_TRIM_LH_R)
result |= 0x02;
if (~c & PIN_TRIM_LV_UP)
result |= 0x08;
if (~c & PIN_TRIM_RV_DN)
result |= 0x10;
if (~c & PIN_TRIM_RH_R)
result |= 0x80;
return result;
}
uint8_t keyDown()
{
return (~readKeys() & 0x7E) || rotencDown();
}
void readKeysAndTrims()
{
register uint32_t i;
#if ROTARY_ENCODERS > 0
keys[BTN_REa].input(rotencDown(), BTN_REa);
#endif
uint8_t enuk = KEY_MENU;
uint8_t in = ~readKeys();
for (i = 1; i < 7; i++) {
keys[enuk].input(in & (1 << i), (EnumKeys) enuk);
++enuk;
}
in = readTrims();
for (i = 1; i < 256; i <<= 1) {
keys[enuk].input(in & i, (EnumKeys) enuk);
++enuk;
}
}
bool switchState(EnumKeys enuk)
{
register uint32_t a;
register uint32_t c;
uint32_t xxx = 0;
if (enuk < (int) DIM(keys)) return keys[enuk].state() ? 1 : 0;
a = PIOA->PIO_PDSR ;
c = PIOC->PIO_PDSR ;
switch ((uint8_t) enuk) {
#if defined(REVA)
case SW_ELE:
xxx = a & 0x00000100; // ELE_DR PA8
#else
case SW_ELE:
xxx = c & 0x80000000; // ELE_DR PC31
#endif
break;
case SW_AIL:
xxx = a & 0x00000004; // AIL-DR PA2
break;
case SW_RUD:
xxx = a & 0x00008000; // RUN_DR PA15
break;
// INP_G_ID1 INP_E_ID2
// id0 0 1
// id1 1 1
// id2 1 0
case SW_ID0:
xxx = ~c & 0x00004000; // SW_IDL1 PC14
break;
case SW_ID1:
xxx = (c & 0x00004000);
if (xxx) xxx = (c & 0x00000800);
break;
case SW_ID2:
xxx = ~c & 0x00000800; // SW_IDL2 PC11
break;
#if 0
case SW_ID3:
result = (calibratedStick[POT1+EXTRA_3POS-1] < 0);
break;
case SW_ID4:
result = (calibratedStick[POT1+EXTRA_3POS-1] == 0);
break;
case SW_ID5:
result = (calibratedStick[POT1+EXTRA_3POS-1] > 0);
break;
#endif
case SW_GEA:
xxx = c & 0x00010000; // SW_GEAR PC16
break;
#if defined(REVA)
case SW_THR:
xxx = a & 0x10000000; // SW_TCUT PA28
#else
case SW_THR:
xxx = c & 0x00100000; // SW_TCUT PC20
#endif
break;
case SW_TRN:
xxx = c & 0x00000100; // SW-TRAIN PC8
break;
default:
break;
}
return xxx;
}
+299
View File
@@ -0,0 +1,299 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "opentx.h"
// LCD i/o pins
// LCD_RES PC27
// LCD_CS1 PC26
// LCD_E PC12
// LCD_RnW PC13
// LCD_A0 PC15
// LCD_D0 PC0
// LCD_D1 PC7
// LCD_D2 PC6
// LCD_D3 PC5
// LCD_D4 PC4
// LCD_D5 PC3
// LCD_D6 PC2
// LCD_D7 PC1
#define LCD_DATA 0x000000FFL
#if !defined(REVA)
#define LCD_A0 0x00000080L
#else
#define LCD_A0 0x00008000L
#endif
#define LCD_RnW 0x00002000L
#define LCD_E 0x00001000L
#define LCD_CS1 0x04000000L
#define LCD_RES 0x08000000L
// Lookup table for prototype board
#if defined(REVA)
const uint8_t Lcd_lookup[] =
{
0x00,0x01,0x80,0x81,0x40,0x41,0xC0,0xC1,0x20,0x21,0xA0,0xA1,0x60,0x61,0xE0,0xE1,
0x10,0x11,0x90,0x91,0x50,0x51,0xD0,0xD1,0x30,0x31,0xB0,0xB1,0x70,0x71,0xF0,0xF1,
0x08,0x09,0x88,0x89,0x48,0x49,0xC8,0xC9,0x28,0x29,0xA8,0xA9,0x68,0x69,0xE8,0xE9,
0x18,0x19,0x98,0x99,0x58,0x59,0xD8,0xD9,0x38,0x39,0xB8,0xB9,0x78,0x79,0xF8,0xF9,
0x04,0x05,0x84,0x85,0x44,0x45,0xC4,0xC5,0x24,0x25,0xA4,0xA5,0x64,0x65,0xE4,0xE5,
0x14,0x15,0x94,0x95,0x54,0x55,0xD4,0xD5,0x34,0x35,0xB4,0xB5,0x74,0x75,0xF4,0xF5,
0x0C,0x0D,0x8C,0x8D,0x4C,0x4D,0xCC,0xCD,0x2C,0x2D,0xAC,0xAD,0x6C,0x6D,0xEC,0xED,
0x1C,0x1D,0x9C,0x9D,0x5C,0x5D,0xDC,0xDD,0x3C,0x3D,0xBC,0xBD,0x7C,0x7D,0xFC,0xFD,
0x02,0x03,0x82,0x83,0x42,0x43,0xC2,0xC3,0x22,0x23,0xA2,0xA3,0x62,0x63,0xE2,0xE3,
0x12,0x13,0x92,0x93,0x52,0x53,0xD2,0xD3,0x32,0x33,0xB2,0xB3,0x72,0x73,0xF2,0xF3,
0x0A,0x0B,0x8A,0x8B,0x4A,0x4B,0xCA,0xCB,0x2A,0x2B,0xAA,0xAB,0x6A,0x6B,0xEA,0xEB,
0x1A,0x1B,0x9A,0x9B,0x5A,0x5B,0xDA,0xDB,0x3A,0x3B,0xBA,0xBB,0x7A,0x7B,0xFA,0xFB,
0x06,0x07,0x86,0x87,0x46,0x47,0xC6,0xC7,0x26,0x27,0xA6,0xA7,0x66,0x67,0xE6,0xE7,
0x16,0x17,0x96,0x97,0x56,0x57,0xD6,0xD7,0x36,0x37,0xB6,0xB7,0x76,0x77,0xF6,0xF7,
0x0E,0x0F,0x8E,0x8F,0x4E,0x4F,0xCE,0xCF,0x2E,0x2F,0xAE,0xAF,0x6E,0x6F,0xEE,0xEF,
0x1E,0x1F,0x9E,0x9F,0x5E,0x5F,0xDE,0xDF,0x3E,0x3F,0xBE,0xBF,0x7E,0x7F,0xFE,0xFF
} ;
#endif
void lcdSendCtl(uint8_t val)
{
register Pio *pioptr ;
// register uint32_t x ;
#if defined(REVA)
pioptr = PIOC ;
pioptr->PIO_CODR = LCD_CS1 ; // Select LCD
pioptr->PIO_CODR = LCD_A0 ; // Control
pioptr->PIO_CODR = LCD_RnW ; // Write
pioptr->PIO_ODSR = Lcd_lookup[val] ;
#else
pioptr = PIOC ;
pioptr->PIO_CODR = LCD_CS1 ; // Select LCD
PIOA->PIO_CODR = LCD_A0 ;
pioptr->PIO_CODR = LCD_RnW ; // Write
pioptr->PIO_ODSR = val ;
#endif
pioptr->PIO_SODR = LCD_E ; // Start E pulse
// Need a delay here (250nS)
TC0->TC_CHANNEL[0].TC_CCR = 5 ; // Enable clock and trigger it (may only need trigger)
while ( TC0->TC_CHANNEL[0].TC_CV < 9 ) // Value depends on MCK/2 (used 18MHz)
{
// Wait
}
pioptr->PIO_CODR = LCD_E ; // End E pulse
#if defined(REVA)
pioptr->PIO_SODR = LCD_A0 ; // Data
#else
PIOA->PIO_SODR = LCD_A0 ; // Data
#endif
pioptr->PIO_SODR = LCD_CS1 ; // Deselect LCD
}
void lcdInit()
{
register Pio *pioptr ;
// /home/thus/txt/datasheets/lcd/KS0713.pdf
// ~/txt/flieger/ST7565RV17.pdf from http://www.glyn.de/content.asp?wdid=132&sid=
#if defined(REVA)
pioptr = PIOC ;
pioptr->PIO_PER = 0x0C00B0FFL ; // Enable bits 27,26,15,13,12,7-0
pioptr->PIO_CODR = LCD_E | LCD_RnW | LCD_A0 ;
pioptr->PIO_SODR = LCD_RES | LCD_CS1 ;
pioptr->PIO_OER = 0x0C00B0FFL ; // Set bits 27,26,15,13,12,7-0 output
pioptr->PIO_OWER = 0x000000FFL ; // Allow write to ls 8 bits in ODSR
#else
configure_pins( LCD_A0, PIN_ENABLE | PIN_LOW | PIN_OUTPUT | PIN_PORTA | PIN_NO_PULLUP ) ;
pioptr = PIOC ;
pioptr->PIO_PER = 0x0C0030FFL ; // Enable bits 27,26,13,12,7-0
pioptr->PIO_CODR = LCD_E | LCD_RnW ;
pioptr->PIO_SODR = LCD_RES | LCD_CS1 ;
pioptr->PIO_OER = 0x0C0030FFL ; // Set bits 27,26,13,12,7-0 output
pioptr->PIO_OWER = 0x000000FFL ; // Allow write to ls 8 bits in ODSR
#endif
pioptr->PIO_CODR = LCD_RES ; // Reset LCD
TC0->TC_CHANNEL[0].TC_CCR = 5 ; // Enable clock and trigger it (may only need trigger)
while ( TC0->TC_CHANNEL[0].TC_CV < 200 ) // > 10us, Value depends on MCK/2 (used 18MHz)
{
// Wait
}
pioptr->PIO_SODR = LCD_RES ; // Remove LCD reset
TC0->TC_CHANNEL[0].TC_CCR = 5 ; // Enable clock and trigger it (may only need trigger)
while ( TC0->TC_CHANNEL[0].TC_CV < 27000 ) // 1500us, Value depends on MCK/2 (used 18MHz)
{
// Wait
}
lcdSendCtl(0xe2); //Initialize the internal functions
lcdSendCtl(0xae); //DON = 0: display OFF
lcdSendCtl(0xa1); //ADC = 1: reverse direction(SEG132->SEG1)
lcdSendCtl(0xA6); //REV = 0: non-reverse display
lcdSendCtl(0xA4); //EON = 0: normal display. non-entire
lcdSendCtl(0xA2); // Select LCD bias=0
lcdSendCtl(0xC0); //SHL = 0: normal direction (COM1->COM64)
lcdSendCtl(0x2F); //Control power circuit operation VC=VR=VF=1
lcdSendCtl(0x25); //Select int resistance ratio R2 R1 R0 =5
lcdSendCtl(0x81); //Set reference voltage Mode
lcdSendCtl(0x22); // 24 SV5 SV4 SV3 SV2 SV1 SV0 = 0x18
lcdSendCtl(0xAF); //DON = 1: display ON
// g_eeGeneral.contrast = 0x22;
#if defined(REVA)
pioptr->PIO_ODR = 0x0000003CL ; // Set bits 2, 3, 4, 5 input
pioptr->PIO_PUER = 0x0000003CL ; // Set bits 2, 3, 4, 5 with pullups
pioptr->PIO_ODSR = 0 ; // Drive D0 low
#else
pioptr->PIO_ODR = 0x0000003AL ; // Set bits 1, 3, 4, 5 input
pioptr->PIO_PUER = 0x0000003AL ; // Set bits 1, 3, 4, 5 with pullups
pioptr->PIO_ODSR = 0 ; // Drive D0 low
#endif
}
void lcdSetRefVolt(uint8_t val)
{
register Pio *pioptr ;
pioptr = PIOC ;
// read the inputs, and lock the LCD lines
lcdInputs = PIOC->PIO_PDSR; // 6 LEFT, 5 RIGHT, 4 DOWN, 3 UP ()
lcdLock = 1 ;
pioptr->PIO_OER = 0x0C00B0FFL ; // Set bits 27,26,15,13,12,7-0 output
lcdSendCtl(0x81);
if ( val == 0 )
{
val = 0x22 ;
}
lcdSendCtl(val);
#if defined(REVA)
pioptr->PIO_ODR = 0x0000003CL ; // Set bits 2, 3, 4, 5 input
pioptr->PIO_PUER = 0x0000003CL ; // Set bits 2, 3, 4, 5 with pullups
#else
pioptr->PIO_ODR = 0x0000003AL ; // Set bits 1, 3, 4, 5 input
pioptr->PIO_PUER = 0x0000003AL ; // Set bits 1, 3, 4, 5 with pullups
#endif
pioptr->PIO_ODSR = lcdInputs; // Drive D0 low
lcdLock = 0 ;
}
void lcdRefresh()
{
register Pio *pioptr;
register uint8_t *p = displayBuf;
register uint32_t y;
register uint32_t x;
register uint32_t z;
register uint32_t ebit;
#if defined(REVA)
register uint8_t *lookup;
lookup = (uint8_t *) Lcd_lookup;
#endif
ebit = LCD_E;
#if !defined(REVA)
pioptr = PIOA;
pioptr->PIO_PER = 0x00000080; // Enable bit 7 (LCD-A0)
pioptr->PIO_OER = 0x00000080;// Set bit 7 output
#endif
// read the inputs, and lock the LCD lines
lcdInputs = PIOC->PIO_PDSR; // 6 LEFT, 5 RIGHT, 4 DOWN, 3 UP ()
lcdLock = 1 ;
pioptr = PIOC;
#if defined(REVA)
pioptr->PIO_OER = 0x0C00B0FFL; // Set bits 27,26,15,13,12,7-0 output
#else
pioptr->PIO_OER = 0x0C0030FFL; // Set bits 27,26,15,13,12,7-0 output
#endif
for (y = 0; y < 8; y++) {
lcdSendCtl(g_eeGeneral.optrexDisplay ? 0 : 0x04);
lcdSendCtl(0x10); //column addr 0
lcdSendCtl(y | 0xB0); //page addr y
pioptr->PIO_CODR = LCD_CS1; // Select LCD
PIOA->PIO_SODR = LCD_A0; // Data
pioptr->PIO_CODR = LCD_RnW; // Write
#if defined(REVA)
x = lookup[*p];
#else
x = *p;
#endif
for (z = 0; z < LCD_W; z += 1) {
// The following 7 lines replaces by a lookup table
// x = __RBIT( *p++ ) ;
// x >>= 23 ;
// if ( x & 0x00000100 )
// {
// x |= 1 ;
// }
// pioptr->PIO_ODSR = x ;
pioptr->PIO_ODSR = x;
pioptr->PIO_SODR = ebit; // Start E pulse
// Need a delay here (250nS)
p += 1;
#if defined(REVA)
x = lookup[*p];
#else
x = *p;
#endif
// TC0->TC_CHANNEL[0].TC_CCR = 5 ; // Enable clock and trigger it (may only need trigger)
// while ( TC0->TC_CHANNEL[0].TC_CV < 3 ) // Value depends on MCK/2 (used 6MHz)
// {
// // Wait
// }
pioptr->PIO_CODR = ebit; // End E pulse
}
pioptr->PIO_SODR = LCD_CS1; // Deselect LCD
}
pioptr->PIO_ODSR = 0xFF ; // Drive lines high
#if defined(REVA)
pioptr->PIO_PUER = 0x0000003CL ; // Set bits 2, 3, 4, 5 with pullups
pioptr->PIO_ODR = 0x0000003CL ; // Set bits 2, 3, 4, 5 input
#else
pioptr->PIO_PUER = 0x0000003AL ; // Set bits 1, 3, 4, 5 with pullups
pioptr->PIO_ODR = 0x0000003AL ; // Set bits 1, 3, 4, 5 input
#endif
pioptr->PIO_ODSR = lcdInputs; // Drive D0 low
lcdLock = 0;
}
+230
View File
@@ -0,0 +1,230 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../opentx.h"
#ifndef SIMU
extern "C" {
#include "usb/device/massstorage/MSDDriver.h"
extern unsigned char MEDSdcard_Initialize(Media *media, unsigned char mciID);
}
/** Size of one block in bytes. */
#define BLOCK_SIZE 512
/** Size of the MSD IO buffer in bytes (6K, more the better). */
#define MSD_BUFFER_SIZE (12*BLOCK_SIZE)
/** LUN read/write buffer. */
unsigned char msdBuffer[MSD_BUFFER_SIZE];
unsigned int msdReadTotal=0, msdWriteTotal=0;
static void ConfigureUsbClock(void)
{
/* Enable PLLB for USB */
PMC->CKGR_PLLBR = CKGR_PLLBR_DIVB(1)
| CKGR_PLLBR_MULB(7)
| CKGR_PLLBR_PLLBCOUNT_Msk;
while((PMC->PMC_SR & PMC_SR_LOCKB) == 0); // TODO && (timeout++ < CLOCK_TIMEOUT));
/* USB Clock uses PLLB */
PMC->PMC_USB = PMC_USB_USBDIV(1) /* /2 */
| PMC_USB_USBS; /* PLLB */
}
/** Maximum number of LUNs which can be defined. */
#define MAX_LUNS 1
/** Media index for different disks */
#define DRV_SDMMC 0 /** SD card */
Media medias[MAX_LUNS];
/*----------------------------------------------------------------------------
* Local variables
*----------------------------------------------------------------------------*/
/** Device LUNs. */
MSDLun luns[MAX_LUNS];
int itoa(int val, char* buf)
{
const unsigned int radix = 10;
char* p;
unsigned int a; //every digit
int len;
char* b; //start of the digit char
char temp;
unsigned int u;
p = buf;
#if 0
if (val < 0)
{
*p++ = '-';
val = 0 - val;
}
#endif
u = (unsigned int)val;
b = p;
do
{
a = u % radix;
u /= radix;
*p++ = a + '0';
} while (u > 0);
len = (int)(p - buf);
*p-- = 0;
//swap
do
{
temp = *p;
*p = *b;
*b = temp;
--p;
++b;
} while (b < p);
return len;
}
uint8_t write_bytes(char *str, uint32_t bytes)
{
uint8_t len;
if (bytes < 1024*100) {
len = itoa(bytes / 1024, str);
str[len] = '.';
str[len+1] = '0' + ((bytes % 1024) / 103);
str[len+2] = 'K';
str[len+3] = '\0';
len += 3;
}
else if (bytes < 1024*1024) {
len = itoa(bytes / 1024, str);
str[len] = 'K';
str[len+1] = '\0';
len += 1;
}
else if (bytes < 1024*1024*100) {
len = itoa(bytes / (1024*1024), str);
str[len] = '.';
str[len+1] = '0' + ((bytes % (1024*1024)) / 104858);
str[len+2] = 'M';
str[len+3] = '\0';
len += 3;
}
else {
len = itoa(bytes / (1024*1024), str);
str[len] = 'M';
str[len+1] = '\0';
len += 1;
}
return len;
}
static void MSDCallbacks_Data( unsigned char flowDirection, unsigned int dataLength,
unsigned int fifoNullCount, unsigned int fifoFullCount )
{
if (flowDirection)
msdReadTotal += dataLength;
else
msdWriteTotal += dataLength;
strcpy(statusLineMsg, "USB Rd:");
uint8_t len = write_bytes(statusLineMsg+7, msdReadTotal);
strcpy(statusLineMsg+7+len, " Wr:");
write_bytes(statusLineMsg+7+len+4, msdWriteTotal);
showStatusLine();
}
void usbMassStorage()
{
static bool initialized = false;
if (usbPlugged() && sd_card_ready()) {
TRACE_DEBUG("usbMassStorage\n\r");
if (sdMounted()) {
Card_state = SD_ST_DATA;
audioQueue.stopSD();
closeLogs();
f_mount(0, 0); // unmount SD
}
if (!initialized) {
ConfigureUsbClock();
/* Initialize LUN */
MEDSdcard_Initialize(&(medias[DRV_SDMMC]), 0);
LUN_Init(&(luns[DRV_SDMMC]), &(medias[DRV_SDMMC]),
msdBuffer, MSD_BUFFER_SIZE,
0, 0, 0, 0,
MSDCallbacks_Data);
/* BOT driver initialization */
MSDDriver_Initialize(luns, 1);
// VBus_Configure();
USBD_Connect();
initialized = true;
}
/* Mass storage state machine */
for (uint8_t i=0; i<50; i++)
MSDDriver_StateMachine();
}
else {
msdReadTotal = 0;
msdWriteTotal = 0;
}
}
#endif
+219
View File
@@ -0,0 +1,219 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../../opentx.h"
extern uint16_t ppmStream[NUM_MODULES][20];
volatile uint32_t ppmStreamIndex[NUM_MODULES] = { MODULES_INIT(0) }; // Modified in interrupt routine
extern uint8_t pxxStream[NUM_MODULES][64]; // TODO not here, duplicated
extern uint8_t *pxxStreamPtr[NUM_MODULES]; // TODO not here, duplicated
extern uint8_t dsm2Stream[64]; // Likely more than we need
extern uint8_t *dsm2StreamPtr;
void init_main_ppm(uint32_t period, uint32_t out_enable)
{
register Pio *pioptr ;
register Pwm *pwmptr ;
setupPulsesPPM(0) ;
if ( out_enable )
{
pioptr = PIOA ;
pioptr->PIO_ABCDSR[0] &= ~PIO_PA17 ; // Peripheral C
pioptr->PIO_ABCDSR[1] |= PIO_PA17 ; // Peripheral C
pioptr->PIO_PDR = PIO_PA17 ; // Disable bit A17 Assign to peripheral
}
pwmptr = PWM ;
// PWM3 for PPM output
pwmptr->PWM_CH_NUM[3].PWM_CMR = 0x0000000B ; // CLKA
if (g_model.moduleData[0].ppmPulsePol)
pwmptr->PWM_CH_NUM[3].PWM_CMR |= 0x00000200 ; // CPOL
pwmptr->PWM_CH_NUM[3].PWM_CPDR = period ; // Period in half uS
pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period ; // Period in half uS
pwmptr->PWM_CH_NUM[3].PWM_CDTY = g_model.moduleData[0].ppmDelay*100+600; // Duty in half uS
pwmptr->PWM_CH_NUM[3].PWM_CDTYUPD = g_model.moduleData[0].ppmDelay*100+600; // Duty in half uS
pwmptr->PWM_ENA = PWM_ENA_CHID3 ; // Enable channel 3
pwmptr->PWM_IER1 = PWM_IER1_CHID3 ;
#if !defined(REVA)
configure_pins( PIO_PC15, PIN_PERIPHERAL | PIN_INPUT | PIN_PER_B | PIN_PORTC | PIN_NO_PULLUP ) ;
#endif
#if !defined(REVA)
// PWM1 for PPM2
pwmptr->PWM_CH_NUM[1].PWM_CMR = 0x0000000B ; // CLKB
if (g_model.moduleData[0].ppmPulsePol)
pwmptr->PWM_CH_NUM[1].PWM_CMR |= 0x00000200 ; // CPOL
pwmptr->PWM_CH_NUM[1].PWM_CPDR = period ; // Period
pwmptr->PWM_CH_NUM[1].PWM_CPDRUPD = period ; // Period
pwmptr->PWM_CH_NUM[1].PWM_CDTY = g_model.moduleData[0].ppmDelay*100+600 ; // Duty
pwmptr->PWM_CH_NUM[1].PWM_CDTYUPD = g_model.moduleData[0].ppmDelay*100+600 ; // Duty
pwmptr->PWM_ENA = PWM_ENA_CHID1 ; // Enable channel 1
#endif
pwmptr->PWM_IER1 = PWM_IER1_CHID1 ;
NVIC_EnableIRQ(PWM_IRQn) ;
}
void disable_ppm(uint32_t port)
{
register Pio *pioptr ;
if (port == 0) {
pioptr = PIOA ;
pioptr->PIO_PER = PIO_PA17 ; // Assign A17 to PIO
PWM->PWM_IDR1 = PWM_IDR1_CHID3 ;
}
else {
pioptr = PIOC ;
pioptr->PIO_PER = PIO_PC17 ; // Assign A17 to PIO
PWM->PWM_IDR1 = PWM_IDR1_CHID1 ;
NVIC_DisableIRQ(PWM_IRQn) ;
}
}
// Initialise the SSC to allow PXX output.
// TD is on PA17, peripheral A
void init_ssc()
{
register Ssc *sscptr ;
PMC->PMC_PCER0 |= 0x00400000L ; // Enable peripheral clock to SSC
configure_pins( PIO_PA17, PIN_PERIPHERAL | PIN_INPUT | PIN_PER_A | PIN_PORTA | PIN_NO_PULLUP ) ;
sscptr = SSC ;
sscptr->SSC_CMR = Master_frequency / (125000*2) ; // 8uS per bit
sscptr->SSC_TCMR = 0 ; // 0000 0000 0000 0000 0000 0000 0000 0000
sscptr->SSC_TFMR = 0x00000027 ; // 0000 0000 0000 0000 0000 0000 1010 0111 (8 bit data, lsb)
sscptr->SSC_CR = SSC_CR_TXEN ;
}
void disable_ssc()
{
register Pio *pioptr ;
register Ssc *sscptr ;
// Revert back to pwm output
pioptr = PIOA ;
pioptr->PIO_PER = PIO_PA17 ; // Assign A17 to PIO
sscptr = SSC ;
sscptr->SSC_CR = SSC_CR_TXDIS ;
}
#if !defined(SIMU)
extern "C" void PWM_IRQHandler(void)
{
register Pwm *pwmptr;
register Ssc *sscptr;
uint32_t period;
uint32_t reason;
pwmptr = PWM;
reason = pwmptr->PWM_ISR1 ;
if (reason & PWM_ISR1_CHID3) {
switch (s_current_protocol[0]) // Use the current, don't switch until set_up_pulses
{
case PROTO_PXX:
// Alternate periods of 15.5mS and 2.5 mS
period = pwmptr->PWM_CH_NUM[3].PWM_CPDR;
if (period == 5000) { // 2.5 mS
period = 15500 * 2;
}
else {
period = 5000;
}
pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period; // Period in half uS
if (period != 5000) { // 2.5 mS
setupPulses(0);
}
else {
// Kick off serial output here
sscptr = SSC;
sscptr->SSC_TPR = CONVERT_PTR(pxxStream[0]);
sscptr->SSC_TCR = (uint8_t *)pxxStreamPtr[0] - (uint8_t *)pxxStream[0];
sscptr->SSC_PTCR = SSC_PTCR_TXTEN; // Start transfers
}
break;
case PROTO_DSM2_LP45:
case PROTO_DSM2_DSM2:
case PROTO_DSM2_DSMX:
// Alternate periods of 19.5mS and 2.5 mS
period = pwmptr->PWM_CH_NUM[3].PWM_CPDR;
if (period == 5000) { // 2.5 mS
period = 19500 * 2;
}
else {
period = 5000;
}
pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period; // Period in half uS
if (period != 5000) { // 2.5 mS
setupPulses(0);
}
else {
// Kick off serial output here
sscptr = SSC;
sscptr->SSC_TPR = CONVERT_PTR(dsm2Stream);
sscptr->SSC_TCR = (uint8_t *)dsm2StreamPtr - (uint8_t *)dsm2Stream;
sscptr->SSC_PTCR = SSC_PTCR_TXTEN; // Start transfers
}
break;
default:
pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = ppmStream[0][ppmStreamIndex[0]++]; // Period in half uS
if (ppmStream[0][ppmStreamIndex[0]] == 0) {
ppmStreamIndex[0] = 0;
setupPulses(0);
}
break;
}
}
if (reason & PWM_ISR1_CHID1) {
pwmptr->PWM_CH_NUM[1].PWM_CPDRUPD = ppmStream[1][ppmStreamIndex[1]++] ; // Period in half uS
if (ppmStream[1][ppmStreamIndex[1]] == 0) {
ppmStreamIndex[1] = 0;
setupPulsesPPM(1);
}
}
}
#endif
+102
View File
@@ -0,0 +1,102 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../../opentx.h"
uint32_t pwrCheck()
{
#ifdef SIMU
return e_power_on;
#endif
#if defined(REVC)
if ( PIOC->PIO_PDSR & PIO_PC17 ) // Power on
{
return e_power_on ;
}
if ( PIOA->PIO_PDSR & PIO_PA8 ) // Trainer plugged in
{
return e_power_trainer ;
}
#elif defined(REVB)
if ( PIOC->PIO_PDSR & PIO_PC17 ) // Power on
{
return e_power_on ;
}
if (usbPlugged())
{
return e_power_usb ; // Detected USB
}
if ( PIOA->PIO_PDSR & PIO_PA8 ) // Trainer plugged in
{
return e_power_trainer ;
}
#else
if ( PIOC->PIO_PDSR & PIO_PC25 )
{
return e_power_usb ; // Detected USB
}
if ( PIOA->PIO_PDSR & PIO_PA8 ) // Trainer plugged in
{
return e_power_trainer ;
}
return e_power_on;
#endif
return e_power_off;
}
// turn off soft power
void pwrOff()
{
#if !defined(REVA)
configure_pins( PIO_PA8, PIN_ENABLE | PIN_OUTPUT | PIN_LOW | PIN_PORTA | PIN_NO_PULLUP ) ;
#endif
}
#if !defined(REVA)
void pwrInit()
{
// Configure RF_power (PC17)
configure_pins( PIO_PC17, PIN_ENABLE | PIN_INPUT | PIN_PORTC | PIN_NO_PULLUP | PIN_PULLDOWN ) ;
configure_pins( PIO_PA8, PIN_ENABLE | PIN_INPUT | PIN_PORTA | PIN_PULLUP ) ; // Enable bit A8 (Soft Power)
}
#endif
+73
View File
@@ -0,0 +1,73 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../opentx.h"
void rotencInit()
{
configure_pins( PIO_PC19 | PIO_PC21, PIN_ENABLE | PIN_INPUT | PIN_PORTC | PIN_PULLUP ) ; // 19 and 21 are rotary encoder
configure_pins( PIO_PB6, PIN_ENABLE | PIN_INPUT | PIN_PORTB | PIN_PULLUP ) ; // rotary encoder switch
PIOC->PIO_IER = PIO_PC19 | PIO_PC21 ;
NVIC_EnableIRQ(PIOC_IRQn) ;
}
void rotencEnd()
{
NVIC_DisableIRQ(PIOC_IRQn) ;
PIOC->PIO_IDR = PIO_PC19 | PIO_PC21 ;
}
volatile uint32_t Rotary_position ;
extern "C" void PIOC_IRQHandler()
{
register uint32_t dummy;
dummy = PIOC->PIO_ISR ; // Read and clear status register
(void) dummy ; // Discard value - prevents compiler warning
dummy = PIOC->PIO_PDSR ; // Read Rotary encoder (PC19, PC21)
dummy >>= 19 ;
dummy &= 0x05 ; // pick out the three bits
if ( dummy != ( Rotary_position & 0x05 ) ) {
if ( ( Rotary_position & 0x01 ) ^ ( ( dummy & 0x04) >> 2 ) )
incRotaryEncoder(0, -1);
else
incRotaryEncoder(0, +1);
Rotary_position &= ~0x45 ;
Rotary_position |= dummy ;
}
}
+64
View File
@@ -0,0 +1,64 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../opentx.h"
struct t_i2cTime
{
uint8_t setCode ;
uint8_t Time[7] ;
} I2CTime ;
void rtcSetTime(struct gtm * t)
{
g_rtcTime = gmktime(t); // update local timestamp and get wday calculated
g_ms100 = 0; // start of next second begins now
I2CTime.setCode = 0x74 ; // Tiny SET TIME CODE command
I2CTime.Time[0] = t->tm_sec ;
I2CTime.Time[1] = t->tm_min ;
I2CTime.Time[2] = t->tm_hour ;
I2CTime.Time[3] = t->tm_mday ;
I2CTime.Time[4] = t->tm_mon+1 ;
I2CTime.Time[5] = (uint8_t) (t->tm_year+1900);
I2CTime.Time[6] = (t->tm_year+1900) >> 8;
coprocWriteData((uint8_t *) &I2CTime, 8);
}
void rtcInit()
{
coprocReadData();
}
+144
View File
@@ -0,0 +1,144 @@
/****************************************************************************
* Copyright (c) 2011 by Michael Fischer. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*****************************************************************************
* History:
*
* 22.05.2011 mifi First Version
****************************************************************************/
/*
* In this linker script there is no heap available.
* The stack start at the end of the ram segment.
*/
/*
* Take a look in the "The GNU linker" manual, here you get
* the following information about the "MEMORY":
*
* "The MEMORY command describes the location and size of
* blocks of memory in the target."
*/
MEMORY
{
FLASH (rx) : ORIGIN = 0x00400000, LENGTH = 128K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 32K
}
/*
* And the "SECTION" is used for:
*
* "The SECTIONS command tells the linker how to map input
* sections into output sections, and how to place the output
* sections in memory.
*/
SECTIONS
{
/*
* The ".text" section is used for the code, and
* read only (.rodata) data. Even the vectors (.vectors)
* MUST be saved at the start of this section.
*/
.text :
{
_stext = .; /* Provide the name for the start of this section */
CREATE_OBJECT_SYMBOLS
KEEP(*(.vectors))
*(.text)
*(.text.*)
. = ALIGN(4); /* Align the start of the exidx part */
*(.ARM.exidx)
*(.ARM.exidx.*)
. = ALIGN(4); /* Align the start of the rodata part */
*(.rodata)
*(.rodata.*)
. = ALIGN(4); /* Align the end of the section */
} > FLASH = 0
_etext = .; /* Provide the name for the end of this section */
/*
* The ".data" section is used for initialized data
* and for functions (.fastrun) which should be copied
* from flash to ram. This functions will later be
* executed from ram instead of flash.
*/
.data : AT (_etext)
{
. = ALIGN(4); /* Align the start of the section */
_sdata = .; /* Provide the name for the start of this section */
*(.data)
*(.data.*)
. = ALIGN(4); /* Align the start of the fastrun part */
*(.fastrun)
*(.fastrun.*)
. = ALIGN(4); /* Align the end of the section */
} > RAM
_edata = .; /* Provide the name for the end of this section */
/*
* The ".bss" section is used for uninitialized data.
* This section will be cleared by the startup code.
*/
.bss :
{
. = ALIGN(4); /* Align the start of the section */
_sbss = .; /* Provide the name for the start of this section */
*(.bss)
*(.bss.*)
. = ALIGN(4); /* Align the end of the section */
} > RAM
_ebss = .; /* Provide the name for the end of this section */
/*
* The ".stack" section is our stack.
* Here this section starts at the end of the ram segment.
*/
_estack = ORIGIN(RAM) + LENGTH(RAM);
}
/*** EOF **/
+147
View File
@@ -0,0 +1,147 @@
/****************************************************************************
* Copyright (c) 2011 by Michael Fischer. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*****************************************************************************
* History:
*
* 22.05.2011 mifi First Version
****************************************************************************/
/*
* In this linker script there is no heap available.
* The stack start at the end of the ram segment.
*/
/*
* Take a look in the "The GNU linker" manual, here you get
* the following information about the "MEMORY":
*
* "The MEMORY command describes the location and size of
* blocks of memory in the target."
*/
MEMORY
{
FLASH (rx) : ORIGIN = 0x00400000, LENGTH = 256K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 48K
}
/*
* And the "SECTION" is used for:
*
* "The SECTIONS command tells the linker how to map input
* sections into output sections, and how to place the output
* sections in memory.
*/
SECTIONS
{
/*
* The ".text" section is used for the code, and
* read only (.rodata) data. Even the vectors (.vectors)
* MUST be saved at the start of this section.
*/
.text :
{
_stext = .; /* Provide the name for the start of this section */
CREATE_OBJECT_SYMBOLS
KEEP(*(.vectors))
*(.text)
*(.text.*)
. = ALIGN(4); /* Align the start of the exidx part */
*(.ARM.exidx)
*(.ARM.exidx.*)
. = ALIGN(4); /* Align the start of the rodata part */
*(.rodata)
*(.rodata.*)
. = ALIGN(4); /* Align the end of the section */
} > FLASH = 0
_etext = .; /* Provide the name for the end of this section */
/*
* The ".data" section is used for initialized data
* and for functions (.fastrun) which should be copied
* from flash to ram. This functions will later be
* executed from ram instead of flash.
*/
.data : AT (_etext)
{
. = ALIGN(4); /* Align the start of the section */
_sdata = .; /* Provide the name for the start of this section */
*(.data)
*(.data.*)
. = ALIGN(4); /* Align the start of the fastrun part */
*(.fastrun)
*(.fastrun.*)
. = ALIGN(4); /* Align the end of the section */
} > RAM
_edata = .; /* Provide the name for the end of this section */
/*
* The ".bss" section is used for uninitialized data.
* This section will be cleared by the startup code.
*/
.bss :
{
. = ALIGN(4); /* Align the start of the section */
_sbss = .; /* Provide the name for the start of this section */
*(.bss)
*(.bss.*)
. = ALIGN(4); /* Align the end of the section */
} > RAM
_ebss = .; /* Provide the name for the end of this section */
. = ALIGN(4); /* Align the end of the section */
__end = .;
_end = .;
/*
* The ".stack" section is our stack.
* Here this section starts at the end of the ram segment.
*/
_estack = ORIGIN(RAM) + LENGTH(RAM);
}
/*** EOF **/
+66
View File
@@ -0,0 +1,66 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#define MCI_INITIAL_SPEED 400000
void init_SDcard()
{
#ifndef SIMU
configure_pins( 0xFC000000, PIN_PERIPHERAL | PIN_INPUT | PIN_PER_C | PIN_PORTA | PIN_NO_PULLUP ) ;
configure_pins( PIO_PB7, PIN_INPUT | PIN_PORTB | PIN_NO_PULLUP | PIN_NO_PULLDOWN ) ;
unsigned short clkDiv;
Hsmci *pMciHw = HSMCI ;
/* Enable the MCI peripheral */
PMC->PMC_PCER0 |= 1 << ID_HSMCI ; // Enable peripheral clock to HSMCI
pMciHw->HSMCI_CR = HSMCI_CR_SWRST; /* Reset the MCI */
pMciHw->HSMCI_CR = HSMCI_CR_MCIDIS | HSMCI_CR_PWSDIS; /* Disable the MCI */
pMciHw->HSMCI_IDR = 0xFFFFFFFF; /* Disable all the interrupts */
pMciHw->HSMCI_DTOR = HSMCI_DTOR_DTOCYC_Msk | HSMCI_DTOR_DTOMUL_Msk ; /* Set the Data Timeout Register */
pMciHw->HSMCI_CSTOR = HSMCI_CSTOR_CSTOCYC_Msk | HSMCI_CSTOR_CSTOMUL_Msk ; /* CSTOR ? */
/* Set the Mode Register: 400KHz for MCK = 48MHz (CLKDIV = 58) */
clkDiv = 45; // (Master_frequency / (MCI_INITIAL_SPEED * 2)) - 1;
pMciHw->HSMCI_MR = clkDiv | (7 << 8) ;
/* Set the SDCard Register 1-bit, slot A */
pMciHw->HSMCI_SDCR = HSMCI_SDCR_SDCSEL_SLOTA | HSMCI_SDCR_SDCBUS_1 ;
/* Enable the MCI and the Power Saving */
pMciHw->HSMCI_CR = HSMCI_CR_MCIEN/* | HSMCI_CR_PWSEN */;
/* Configure MCI */
pMciHw->HSMCI_CFG = HSMCI_CFG_FIFOMODE | HSMCI_CFG_FERRCTRL;
#endif
}
+158
View File
@@ -0,0 +1,158 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file syscalls.c
*
* Implementation of newlib syscall.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
// #include "board.h"
#include <stdio.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
/*----------------------------------------------------------------------------
* Exported variables
*----------------------------------------------------------------------------*/
#undef errno
extern int errno;
extern int _end;
extern int _estack;
#define RAM_END (unsigned char *)&_estack
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
extern void _exit( int status ) ;
extern void _kill( int pid, int sig ) ;
extern int _getpid ( void ) ;
unsigned char *heap = (unsigned char *)&_end;
extern caddr_t _sbrk(int nbytes)
{
if (heap + nbytes < RAM_END-4096) {
unsigned char *prev_heap = heap;
heap += nbytes;
return (caddr_t) prev_heap;
}
else {
errno = ENOMEM;
return ((void*)-1);
}
}
extern int _gettimeofday(void *p1, void *p2)
{
return 0 ;
}
extern int _link( char *old, char *nw )
{
return -1 ;
}
extern int _unlink (const char *path)
{
return -1 ;
}
extern int _open(const char *name, int flags, int mode)
{
return -1 ;
}
extern int _close( int file )
{
return -1 ;
}
extern int _fstat( int file, struct stat *st )
{
st->st_mode = S_IFCHR ;
return 0 ;
}
extern int _isatty( int file )
{
return 1 ;
}
extern int _lseek( int file, int ptr, int dir )
{
return 0 ;
}
extern int _read(int file, char *ptr, int len)
{
return 0 ;
}
extern int _write( int file, char *ptr, int len )
{
int iIndex ;
// for ( ; *ptr != 0 ; ptr++ )
for ( iIndex=0 ; iIndex < len ; iIndex++, ptr++ )
{
// TODO UART_PutChar( *ptr ) ;
}
return iIndex ;
}
extern void _exit( int status )
{
printf( "Exiting with status %d.\n", status ) ;
for ( ; ; ) ;
}
extern void _kill( int pid, int sig )
{
return ;
}
extern int _getpid ( void )
{
return -1 ;
}
@@ -0,0 +1,162 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*
Title: USBConfigurationDescriptor implementation
About: Purpose
Implementation of the USBConfigurationDescriptor class.
*/
//-----------------------------------------------------------------------------
// Headers
//-----------------------------------------------------------------------------
#include "USBConfigurationDescriptor.h"
//-----------------------------------------------------------------------------
// Exported functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// Returns the total length of a configuration, i.e. including the
/// descriptors following it.
/// \param configuration Pointer to a USBConfigurationDescriptor instance.
/// \return Total length (in bytes) of the configuration.
//-----------------------------------------------------------------------------
unsigned int USBConfigurationDescriptor_GetTotalLength(
const USBConfigurationDescriptor *configuration)
{
return configuration->wTotalLength;
}
//-----------------------------------------------------------------------------
/// Returns the number of interfaces in a configuration.
/// \param configuration Pointer to a USBConfigurationDescriptor instance.
/// \return Number of interfaces in configuration.
//-----------------------------------------------------------------------------
unsigned char USBConfigurationDescriptor_GetNumInterfaces(
const USBConfigurationDescriptor *configuration)
{
return configuration->bNumInterfaces;
}
//-----------------------------------------------------------------------------
/// Indicates if the device is self-powered when in a given configuration.
/// \param configuration Pointer to a USBConfigurationDescriptor instance.
/// \return 1 if the device is self-powered when in the given configuration;
/// otherwise 0.
//-----------------------------------------------------------------------------
unsigned char USBConfigurationDescriptor_IsSelfPowered(
const USBConfigurationDescriptor *configuration)
{
if ((configuration->bmAttributes & (1 << 6)) != 0) {
return 1;
}
else {
return 0;
}
}
//-----------------------------------------------------------------------------
/// Parses the given Configuration descriptor (followed by relevant
/// interface, endpoint and class-specific descriptors) into three arrays.
/// *Each array must have its size equal or greater to the number of
/// descriptors it stores plus one*. A null-value is inserted after the last
/// descriptor of each type to indicate the array end.
///
/// Note that if the pointer to an array is null (0), nothing is stored in
/// it.
/// \param configuration Pointer to the start of the whole Configuration
/// descriptor.
/// \param interfaces Pointer to the Interface descriptor array.
/// \param endpoints Pointer to the Endpoint descriptor array.
/// \param others Pointer to the class-specific descriptor array.
//-----------------------------------------------------------------------------
void USBConfigurationDescriptor_Parse(
const USBConfigurationDescriptor *configuration,
USBInterfaceDescriptor **interfaces,
USBEndpointDescriptor **endpoints,
USBGenericDescriptor **others)
{
// Get size of configuration to parse
int size = USBConfigurationDescriptor_GetTotalLength(configuration);
size -= sizeof(USBConfigurationDescriptor);
// Start parsing descriptors
USBGenericDescriptor *descriptor = (USBGenericDescriptor *) configuration;
while (size > 0) {
// Get next descriptor
descriptor = USBGenericDescriptor_GetNextDescriptor(descriptor);
size -= USBGenericDescriptor_GetLength(descriptor);
// Store descriptor in correponding array
if (USBGenericDescriptor_GetType(descriptor)
== USBGenericDescriptor_INTERFACE) {
if (interfaces) {
*interfaces = (USBInterfaceDescriptor *) descriptor;
interfaces++;
}
}
else if (USBGenericDescriptor_GetType(descriptor)
== USBGenericDescriptor_ENDPOINT) {
if (endpoints) {
*endpoints = (USBEndpointDescriptor *) descriptor;
endpoints++;
}
}
else if (others) {
*others = descriptor;
others++;
}
}
// Null-terminate arrays
if (interfaces) {
*interfaces = 0;
}
if (endpoints) {
*endpoints = 0;
}
if (others) {
*others = 0;
}
}
@@ -0,0 +1,150 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
\unit
!!!Purpose
Definitions and methods for USB configuration descriptor structures
described by the USB specification.
!!!Usage
-# Declare USBConfigurationDescriptor instance as a part
of the configuration descriptors of a USB device.
-# To get useful information (field values) from the defined USB device
configuration descriptor, use
- USBConfigurationDescriptor_GetTotalLength
- USBConfigurationDescriptor_GetNumInterfaces
- USBConfigurationDescriptor_IsSelfPowered
-# To pase the defined USB device configuration descriptor, use
- USBConfigurationDescriptor_Parse
*/
#ifndef USBCONFIGURATIONDESCRIPTOR_H
#define USBCONFIGURATIONDESCRIPTOR_H
//-----------------------------------------------------------------------------
// Headers
//-----------------------------------------------------------------------------
#include "USBGenericDescriptor.h"
#include "USBInterfaceDescriptor.h"
#include "USBEndpointDescriptor.h"
//-----------------------------------------------------------------------------
// Definitions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// \page "USB device Attributes"
///
/// This page lists the codes of the usb attributes.
///
/// !Attributes
/// - USBConfigurationDescriptor_BUSPOWERED_NORWAKEUP
/// - USBConfigurationDescriptor_SELFPOWERED_NORWAKEUP
/// - USBConfigurationDescriptor_BUSPOWERED_RWAKEUP
/// - USBConfigurationDescriptor_SELFPOWERED_RWAKEUP
/// - USBConfigurationDescriptor_POWER
/// Device is bus-powered and not support remote wake-up.
#define USBConfigurationDescriptor_BUSPOWERED_NORWAKEUP 0x80
/// Device is self-powered and not support remote wake-up.
#define USBConfigurationDescriptor_SELFPOWERED_NORWAKEUP 0xC0
/// Device is bus-powered and supports remote wake-up.
#define USBConfigurationDescriptor_BUSPOWERED_RWAKEUP 0xA0
/// Device is self-powered and supports remote wake-up.
#define USBConfigurationDescriptor_SELFPOWERED_RWAKEUP 0xE0
/// Calculates the value of the power consumption field given the value in mA.
/// \param power The power consumption value in mA
/// \return The value that should be set to the field in descriptor
#define USBConfigurationDescriptor_POWER(power) (power / 2)
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Types
//-----------------------------------------------------------------------------
#ifdef __ICCARM__ // IAR
#pragma pack(1) // IAR
#define __attribute__(...) // IAR
#endif // IAR
//-----------------------------------------------------------------------------
/// USB standard configuration descriptor structure.
//-----------------------------------------------------------------------------
typedef struct {
/// Size of the descriptor in bytes.
unsigned char bLength;
/// Descriptor type (USBDESC_CONFIGURATION of "USB Descriptor types").
unsigned char bDescriptorType;
/// Length of all descriptors returned along with this configuration
/// descriptor.
unsigned short wTotalLength;
/// Number of interfaces in this configuration.
unsigned char bNumInterfaces;
/// Value for selecting this configuration.
unsigned char bConfigurationValue;
/// Index of the configuration string descriptor.
unsigned char iConfiguration;
/// Configuration characteristics.
unsigned char bmAttributes;
/// Maximum power consumption of the device when in this configuration.
unsigned char bMaxPower;
} __attribute__ ((packed)) USBConfigurationDescriptor; // GCC
#ifdef __ICCARM__ // IAR
#pragma pack() // IAR
#endif // IAR
//-----------------------------------------------------------------------------
// Exported functions
//-----------------------------------------------------------------------------
extern unsigned int USBConfigurationDescriptor_GetTotalLength(
const USBConfigurationDescriptor *configuration);
extern unsigned char USBConfigurationDescriptor_GetNumInterfaces(
const USBConfigurationDescriptor *configuration);
extern unsigned char USBConfigurationDescriptor_IsSelfPowered(
const USBConfigurationDescriptor *configuration);
extern void USBConfigurationDescriptor_Parse(
const USBConfigurationDescriptor *configuration,
USBInterfaceDescriptor **interfaces,
USBEndpointDescriptor **endpoints,
USBGenericDescriptor **others);
#endif //#ifndef USBCONFIGURATIONDESCRIPTOR_H
@@ -0,0 +1,125 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
\unit
!!!Purpose
Class for manipulating USB device descriptors.
!!!Usage
- Declare a USBDeviceDescriptor instance as the device descriptor of a
USB device.
*/
#ifndef USBDEVICEDESCRIPTOR_H
#define USBDEVICEDESCRIPTOR_H
#include <board.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USB release numbers"
///
/// This page lists the codes of USB release numbers.
///
/// !Code
/// - USBDeviceDescriptor_USB2_00
/// The device supports USB 2.00.
#define USBDeviceDescriptor_USB2_00 0x0200
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
#ifdef __ICCARM__ // IAR
#pragma pack(1) // IAR
#define __attribute__(...) // IAR
#endif // IAR
//------------------------------------------------------------------------------
/// USB standard device descriptor structure.
//------------------------------------------------------------------------------
typedef struct {
/// Size of this descriptor in bytes.
unsigned char bLength;
/// Descriptor type (USBGenericDescriptor_DEVICE).
unsigned char bDescriptorType;
/// USB specification release number in BCD format.
unsigned short bcdUSB;
/// Device class code.
unsigned char bDeviceClass;
/// Device subclass code.
unsigned char bDeviceSubClass;
/// Device protocol code.
unsigned char bDeviceProtocol;
/// Maximum packet size of endpoint 0 (in bytes).
unsigned char bMaxPacketSize0;
/// Vendor ID.
unsigned short idVendor;
/// Product ID.
unsigned short idProduct;
/// Device release number in BCD format.
unsigned short bcdDevice;
/// Index of the manufacturer string descriptor.
unsigned char iManufacturer;
/// Index of the product string descriptor.
unsigned char iProduct;
/// Index of the serial number string descriptor.
unsigned char iSerialNumber;
/// Number of possible configurations for the device.
unsigned char bNumConfigurations;
} __attribute__ ((packed)) USBDeviceDescriptor; // GCC
#if defined(CHIP_USB_OTGHS)
typedef struct {
/// Size of this descriptor in bytes.
unsigned char bLength;
/// Descriptor type (USBGenericDescriptor_OTG).
unsigned char bDescriptorType;
/// Attribute Fields D7…2: Reserved D1: HNP support D0: SRP support
unsigned char bmAttributes;
} __attribute__ ((packed)) USBOtgDescriptor; // GCC
#endif
#ifdef __ICCARM__ // IAR
#pragma pack() // IAR
#endif // IAR
#endif //#ifndef USBDEVICEDESCRIPTOR_H
@@ -0,0 +1,89 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
\unit
!!!Purpose
Class for manipulating USB device qualifier descriptors.
!!!Usage
- Declare a USBDeviceQualifierDescriptor instance as the device qualifier
descriptor of a USB device.
*/
#ifndef USBDEVICEQUALIFIERDESCRIPTOR_H
#define USBDEVICEQUALIFIERDESCRIPTOR_H
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
#ifdef __ICCARM__ // IAR
#pragma pack(1) // IAR
#define __attribute__(...) // IAR
#endif // IAR
//------------------------------------------------------------------------------
/// Alternate device descriptor indicating the capabilities of the device
/// in full-speed, if currently in high-speed; or in high-speed, if it is
/// currently in full-speed. Only relevant for devices supporting the
/// high-speed mode.
//------------------------------------------------------------------------------
typedef struct {
/// Size of the descriptor in bytes.
unsigned char bLength;
/// Descriptor type (USBDESC_DEVICE_QUALIFIER or "USB device types").
unsigned char bDescriptorType;
/// USB specification release number (in BCD format).
unsigned short bcdUSB;
/// Device class code.
unsigned char bDeviceClass;
/// Device subclass code.
unsigned char bDeviceSubClass;
/// Device protocol code.
unsigned char bDeviceProtocol;
/// Maximum packet size of endpoint 0.
unsigned char bMaxPacketSize0;
/// Number of possible configurations for the device.
unsigned char bNumConfigurations;
/// Reserved.
unsigned char bReserved;
} __attribute__ ((packed)) USBDeviceQualifierDescriptor; // GCC
#ifdef __ICCARM__ // IAR
#pragma pack() // IAR
#endif // IAR
#endif //#ifndef USBDEVICEQUALIFIERDESCRIPTOR_H
@@ -0,0 +1,109 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*
Title: USBEndpointDescriptor implementation
About: Purpose
Implementation of the USBEndpointDescriptor class.
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "USBEndpointDescriptor.h"
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Returns the number of an endpoint given its descriptor.
/// \param endpoint Pointer to a USBEndpointDescriptor instance.
/// \return Endpoint number.
//------------------------------------------------------------------------------
unsigned char USBEndpointDescriptor_GetNumber(
const USBEndpointDescriptor *endpoint)
{
return endpoint->bEndpointAddress & 0xF;
}
//------------------------------------------------------------------------------
/// Returns the direction of an endpoint given its descriptor.
/// \param endpoint Pointer to a USBEndpointDescriptor instance.
/// \return Endpoint direction (see <Endpoint directions>).
//------------------------------------------------------------------------------
unsigned char USBEndpointDescriptor_GetDirection(
const USBEndpointDescriptor *endpoint)
{
if ((endpoint->bEndpointAddress & 0x80) != 0) {
return USBEndpointDescriptor_IN;
}
else {
return USBEndpointDescriptor_OUT;
}
}
//------------------------------------------------------------------------------
/// Returns the type of an endpoint given its descriptor.
/// \param endpoint Pointer to a USBEndpointDescriptor instance.
/// \return Endpoint type (see <Endpoint types>).
//------------------------------------------------------------------------------
unsigned char USBEndpointDescriptor_GetType(
const USBEndpointDescriptor *endpoint)
{
return endpoint->bmAttributes & 0x3;
}
//------------------------------------------------------------------------------
/// Returns the maximum size of a packet (in bytes) on an endpoint given
/// its descriptor.
/// \param endpoint - Pointer to a USBEndpointDescriptor instance.
/// \return Maximum packet size of endpoint.
//------------------------------------------------------------------------------
unsigned short USBEndpointDescriptor_GetMaxPacketSize(
const USBEndpointDescriptor *endpoint)
{
return endpoint->wMaxPacketSize;
}
//------------------------------------------------------------------------------
/// Returns the polling interval on an endpoint given its descriptor.
/// \param endpoint - Pointer to a USBEndpointDescriptor instance.
/// \return Polling interval of endpoint.
//------------------------------------------------------------------------------
unsigned char USBEndpointDescriptor_GetInterval(
const USBEndpointDescriptor *endpoint)
{
return endpoint->bInterval;
}
@@ -0,0 +1,224 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
\unit
!!!Purpose
Definition of a class for handling USB endpoint descriptors.
!!!Usage
-# Declare USBEndpointDescriptor instance as a part of the
configuration descriptors of a USB device.
-# To get useful information (field values) from the defined USB device
endpoint descriptor (to configure hardware for endpoints, etc), use
- USBEndpointDescriptor_GetNumber
- USBEndpointDescriptor_GetDirection
- USBEndpointDescriptor_GetType
- USBEndpointDescriptor_GetMaxPacketSize
*/
#ifndef USBENDPOINTDESCRIPTOR_H
#define USBENDPOINTDESCRIPTOR_H
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USB Endpoint definitions"
///
/// This page lists definitions and macro for endpoint descriptors.
///
/// - USB Endpoint directions
/// - USBEndpointDescriptor_OUT
/// - USBEndpointDescriptor_IN
///
/// - USB Endpoint types
/// - USBEndpointDescriptor_CONTROL
/// - USBEndpointDescriptor_ISOCHRONOUS
/// - USBEndpointDescriptor_BULK
/// - USBEndpointDescriptor_INTERRUPT
///
/// - USB Endpoint maximun sizes
/// - USBEndpointDescriptor_MAXCTRLSIZE_FS
/// - USBEndpointDescriptor_MAXCTRLSIZE_HS
/// - USBEndpointDescriptor_MAXBULKSIZE_FS
/// - USBEndpointDescriptor_MAXBULKSIZE_HS
/// - USBEndpointDescriptor_MAXINTERRUPTSIZE_FS
/// - USBEndpointDescriptor_MAXINTERRUPTSIZE_HS
/// - USBEndpointDescriptor_MAXISOCHRONOUSSIZE_FS
/// - USBEndpointDescriptor_MAXISOCHRONOUSSIZE_HS
///
/// - USB Endpoint address define
/// - USBEndpointDescriptor_ADDRESS
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USB Endpoint directions"
///
/// This page lists definitions of USB endpoint directions.
///
/// !Directions
/// - USBEndpointDescriptor_OUT
/// - USBEndpointDescriptor_IN
/// Endpoint receives data from the host.
#define USBEndpointDescriptor_OUT 0
/// Endpoint sends data to the host.
#define USBEndpointDescriptor_IN 1
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USB Endpoint types"
///
/// This page lists definitions of USB endpoint types.
///
/// !Types
/// - USBEndpointDescriptor_CONTROL
/// - USBEndpointDescriptor_ISOCHRONOUS
/// - USBEndpointDescriptor_BULK
/// - USBEndpointDescriptor_INTERRUPT
/// Control endpoint type.
#define USBEndpointDescriptor_CONTROL 0
/// Isochronous endpoint type.
#define USBEndpointDescriptor_ISOCHRONOUS 1
/// Bulk endpoint type.
#define USBEndpointDescriptor_BULK 2
/// Interrupt endpoint type.
#define USBEndpointDescriptor_INTERRUPT 3
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USB Endpoint maximun sizes"
///
/// This page lists definitions of USB endpoint maximun sizes.
///
/// !Sizes
/// - USBEndpointDescriptor_MAXCTRLSIZE_FS
/// - USBEndpointDescriptor_MAXCTRLSIZE_HS
/// - USBEndpointDescriptor_MAXBULKSIZE_FS
/// - USBEndpointDescriptor_MAXBULKSIZE_HS
/// - USBEndpointDescriptor_MAXINTERRUPTSIZE_FS
/// - USBEndpointDescriptor_MAXINTERRUPTSIZE_HS
/// - USBEndpointDescriptor_MAXISOCHRONOUSSIZE_FS
/// - USBEndpointDescriptor_MAXISOCHRONOUSSIZE_HS
/// Maximum size for a full-speed control endpoint.
#define USBEndpointDescriptor_MAXCTRLSIZE_FS 64
/// Maximum size for a high-speed control endpoint.
#define USBEndpointDescriptor_MAXCTRLSIZE_HS 64
/// Maximum size for a full-speed bulk endpoint.
#define USBEndpointDescriptor_MAXBULKSIZE_FS 64
/// Maximum size for a high-speed bulk endpoint.
#define USBEndpointDescriptor_MAXBULKSIZE_HS 512
/// Maximum size for a full-speed interrupt endpoint.
#define USBEndpointDescriptor_MAXINTERRUPTSIZE_FS 64
/// Maximum size for a high-speed interrupt endpoint.
#define USBEndpointDescriptor_MAXINTERRUPTSIZE_HS 1024
/// Maximum size for a full-speed isochronous endpoint.
#define USBEndpointDescriptor_MAXISOCHRONOUSSIZE_FS 1023
/// Maximum size for a high-speed isochronous endpoint.
#define USBEndpointDescriptor_MAXISOCHRONOUSSIZE_HS 1024
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USB Endpoint address define"
///
/// This page lists macro for USB endpoint address definition.
///
/// !Macro
/// - USBEndpointDescriptor_ADDRESS
/// Calculates the address of an endpoint given its number and direction
/// \param direction USB endpoint direction definition
/// \param number USB endpoint number
/// \return The value used to set the endpoint descriptor based on input number
/// and direction
#define USBEndpointDescriptor_ADDRESS(direction, number) \
(((direction & 0x01) << 7) | (number & 0xF))
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
#ifdef __ICCARM__ // IAR
#pragma pack(1) // IAR
#define __attribute__(...) // IAR
#endif // IAR
//------------------------------------------------------------------------------
/// USB standard endpoint descriptor structure.
//------------------------------------------------------------------------------
typedef struct {
/// Size of the descriptor in bytes.
unsigned char bLength;
/// Descriptor type (<USBGenericDescriptor_ENDPOINT>).
unsigned char bDescriptorType;
/// Address and direction of the endpoint.
unsigned char bEndpointAddress;
/// Endpoint type and additional characteristics (for isochronous endpoints).
unsigned char bmAttributes;
/// Maximum packet size (in bytes) of the endpoint.
unsigned short wMaxPacketSize;
/// Polling rate of the endpoint.
unsigned char bInterval;
} __attribute__ ((packed)) USBEndpointDescriptor; // GCC
#ifdef __ICCARM__ // IAR
#pragma pack() // IAR
#endif // IAR
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern unsigned char USBEndpointDescriptor_GetNumber(
const USBEndpointDescriptor *endpoint);
extern unsigned char USBEndpointDescriptor_GetDirection(
const USBEndpointDescriptor *endpoint);
extern unsigned char USBEndpointDescriptor_GetType(
const USBEndpointDescriptor *endpoint);
extern unsigned short USBEndpointDescriptor_GetMaxPacketSize(
const USBEndpointDescriptor *endpoint);
extern unsigned char USBEndpointDescriptor_GetInterval(
const USBEndpointDescriptor *endpoint);
#endif //#ifndef USBENDPOINTDESCRIPTOR_H
@@ -0,0 +1,70 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*
Title: USBFeatureRequest implementation
About: Purpose
Implementation of the USBFeatureRequest class.
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "USBFeatureRequest.h"
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Returns the feature selector of a given CLEAR_FEATURE or SET_FEATURE
/// request.
/// \param request Pointer to a USBGenericRequest instance.
/// \return Feature selector.
//------------------------------------------------------------------------------
unsigned char USBFeatureRequest_GetFeatureSelector(
const USBGenericRequest *request)
{
return USBGenericRequest_GetValue(request);
}
//------------------------------------------------------------------------------
/// Indicates the test that the device must undertake following a
/// SET_FEATURE request.
/// \param request Pointer to a USBGenericRequest instance.
/// \return Test selector.
//------------------------------------------------------------------------------
unsigned char USBFeatureRequest_GetTestSelector(
const USBGenericRequest *request)
{
return (USBGenericRequest_GetIndex(request) >> 8) & 0xFF;
}
@@ -0,0 +1,146 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
\unit
!!!Purpose
Definition of a class for manipulating CLEAR_FEATURE and SET_FEATURE
requests.
!!!Usage
- To get USB feature request information (field values) from the
USBGenericRequest instance, use
- USBFeatureRequest_GetFeatureSelector
- USBFeatureRequest_GetTestSelector
*/
#ifndef USBFEATUREREQUEST_H
#define USBFEATUREREQUEST_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "USBGenericRequest.h"
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USB Feature Request definitions"
///
/// This page lists codes of USB Feature Request
///
/// - USB Feature selectors
/// - USBFeatureRequest_ENDPOINTHALT
/// - USBFeatureRequest_DEVICEREMOTEWAKEUP
/// - USBFeatureRequest_TESTMODE
///
/// - USB Test mode selectors
/// - USBFeatureRequest_TESTJ
/// - USBFeatureRequest_TESTK
/// - USBFeatureRequest_TESTSE0NAK
/// - USBFeatureRequest_TESTPACKET
/// - USBFeatureRequest_TESTFORCEENABLE
/// - USBFeatureRequest_TESTSENDZLP
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USB Feature selectors"
///
/// This page lists codes of USB feature selectors.
///
/// !Selectors
/// - USBFeatureRequest_ENDPOINTHALT
/// - USBFeatureRequest_DEVICEREMOTEWAKEUP
/// - USBFeatureRequest_TESTMODE
/// Halt feature of an endpoint.
#define USBFeatureRequest_ENDPOINTHALT 0
/// Remote wake-up feature of the device.
#define USBFeatureRequest_DEVICEREMOTEWAKEUP 1
/// Test mode of the device.
#define USBFeatureRequest_TESTMODE 2
/// OTG set feature
#define USBFeatureRequest_OTG 0x0B
//------------------------------------------------------------------------------
/// On The Go Feature Selectors
/// b_hnp_enable 3
/// a_hnp_support 4
/// a_alt_hnp_support 5
#define USBFeatureRequest_OTG_B_HNP_ENABLE 3
#define USBFeatureRequest_OTG_A_HNP_SUPPORT 4
#define USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT 5
//------------------------------------------------------------------------------
/// \page "USB Test mode selectors"
///
/// This page lists codes of USB high speed test mode selectors.
///
/// !Selectors
/// - USBFeatureRequest_TESTJ
/// - USBFeatureRequest_TESTK
/// - USBFeatureRequest_TESTSE0NAK
/// - USBFeatureRequest_TESTPACKET
/// - USBFeatureRequest_TESTFORCEENABLE
/// - USBFeatureRequest_TESTSENDZLP
/// Tests the high-output drive level on the D+ line.
#define USBFeatureRequest_TESTJ 1
/// Tests the high-output drive level on the D- line.
#define USBFeatureRequest_TESTK 2
/// Tests the output impedance, low-level output voltage and loading
/// characteristics.
#define USBFeatureRequest_TESTSE0NAK 3
/// Tests rise and fall times, eye patterns and jitter.
#define USBFeatureRequest_TESTPACKET 4
/// Tests the hub disconnect detection.
#define USBFeatureRequest_TESTFORCEENABLE 5
/// Send a ZLP in Test Mode.
#define USBFeatureRequest_TESTSENDZLP 6
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern unsigned char USBFeatureRequest_GetFeatureSelector(
const USBGenericRequest *request);
extern unsigned char USBFeatureRequest_GetTestSelector(
const USBGenericRequest *request);
#endif //#ifndef USBFEATUREREQUEST_H
@@ -0,0 +1,80 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*
Title: USBGenericDescriptor implementation
About: Purpose
Implementation of the USBGenericDescriptor class.
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "USBGenericDescriptor.h"
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Returns the length of a descriptor.
/// \param descriptor Pointer to a USBGenericDescriptor instance.
/// \return Length of descriptor in bytes.
//------------------------------------------------------------------------------
unsigned int USBGenericDescriptor_GetLength(
const USBGenericDescriptor *descriptor)
{
return descriptor->bLength;
}
//------------------------------------------------------------------------------
/// Returns the type of a descriptor.
/// \param descriptor Pointer to a USBGenericDescriptor instance.
/// \return Type of descriptor.
//------------------------------------------------------------------------------
unsigned char USBGenericDescriptor_GetType(
const USBGenericDescriptor *descriptor)
{
return descriptor->bDescriptorType;
}
//------------------------------------------------------------------------------
/// Returns a pointer to the descriptor right after the given one, when
/// parsing a Configuration descriptor.
/// \param descriptor - Pointer to a USBGenericDescriptor instance.
/// \return Pointer to the next descriptor.
//------------------------------------------------------------------------------
USBGenericDescriptor *USBGenericDescriptor_GetNextDescriptor(
const USBGenericDescriptor *descriptor)
{
return (USBGenericDescriptor *)
(((char *) descriptor) + USBGenericDescriptor_GetLength(descriptor));
}
@@ -0,0 +1,133 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
///
/// !!!Purpose
///
/// Definition of a generic USB descriptor class.
///
/// !!!Usage
///
/// -# Declare or access USB descriptors by USBGenericDescriptor instance.
/// -# To get usful information (field values) from the USB descriptors, use
/// - USBGenericDescriptor_GetLength
/// - USBGenericDescriptor_GetType
/// -# To scan the descriptors, use
/// - USBGenericDescriptor_GetNextDescriptor
//------------------------------------------------------------------------------
#ifndef USBGENERICDESCRIPTOR_H
#define USBGENERICDESCRIPTOR_H
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USB Descriptor types"
///
/// This page lists the codes of the usb descriptor types
///
/// !Types
/// - USBGenericDescriptor_DEVICE
/// - USBGenericDescriptor_CONFIGURATION
/// - USBGenericDescriptor_STRING
/// - USBGenericDescriptor_INTERFACE
/// - USBGenericDescriptor_ENDPOINT
/// - USBGenericDescriptor_DEVICEQUALIFIER
/// - USBGenericDescriptor_OTHERSPEEDCONFIGURATION
/// - USBGenericDescriptor_INTERFACEPOWER
/// - USBGenericDescriptor_OTG
/// - USBGenericDescriptor_DEBUG
/// - USBGenericDescriptor_INTERFACEASSOCIATION
/// Device descriptor type.
#define USBGenericDescriptor_DEVICE 1
/// Configuration descriptor type.
#define USBGenericDescriptor_CONFIGURATION 2
/// String descriptor type.
#define USBGenericDescriptor_STRING 3
/// Interface descriptor type.
#define USBGenericDescriptor_INTERFACE 4
/// Endpoint descriptor type.
#define USBGenericDescriptor_ENDPOINT 5
/// Device qualifier descriptor type.
#define USBGenericDescriptor_DEVICEQUALIFIER 6
/// Other speed configuration descriptor type.
#define USBGenericDescriptor_OTHERSPEEDCONFIGURATION 7
/// Interface power descriptor type.
#define USBGenericDescriptor_INTERFACEPOWER 8
/// On-The-Go descriptor type.
#define USBGenericDescriptor_OTG 9
/// Debug descriptor type.
#define USBGenericDescriptor_DEBUG 10
/// Interface association descriptor type.
#define USBGenericDescriptor_INTERFACEASSOCIATION 11
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
#ifdef __ICCARM__ // IAR
#pragma pack(1) // IAR
#define __attribute__(...) // IAR
#endif // IAR
/// Holds the few fields shared by all USB descriptors.
typedef struct {
/// Length of the descriptor in bytes.
unsigned char bLength;
/// Descriptor type.
unsigned char bDescriptorType;
} __attribute__ ((packed)) USBGenericDescriptor; // GCC
#ifdef __ICCARM__ // IAR
#pragma pack() // IAR
#endif // IAR
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern unsigned int USBGenericDescriptor_GetLength(
const USBGenericDescriptor *descriptor);
extern unsigned char USBGenericDescriptor_GetType(
const USBGenericDescriptor *descriptor);
extern USBGenericDescriptor *USBGenericDescriptor_GetNextDescriptor(
const USBGenericDescriptor *descriptor);
#endif //#ifndef USBGENERICDESCRIPTOR_H
@@ -0,0 +1,138 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*
Title: USBGenericRequest implementation
About: Purpose
Implementation of the USBGenericRequest class.
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "USBGenericRequest.h"
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Returns the type of the given request.
/// \param request Pointer to a USBGenericRequest instance.
/// \return "USB Request Types"
//------------------------------------------------------------------------------
extern unsigned char USBGenericRequest_GetType(const USBGenericRequest *request)
{
return ((request->bmRequestType >> 5) & 0x3);
}
//------------------------------------------------------------------------------
/// Returns the request code of the given request.
/// \param request Pointer to a USBGenericRequest instance.
/// \return Request code.
/// \sa "USB Request Codes"
//------------------------------------------------------------------------------
unsigned char USBGenericRequest_GetRequest(const USBGenericRequest *request)
{
return request->bRequest;
}
//------------------------------------------------------------------------------
/// Returns the wValue field of the given request.
/// \param request - Pointer to a USBGenericRequest instance.
/// \return Request value.
//------------------------------------------------------------------------------
unsigned short USBGenericRequest_GetValue(const USBGenericRequest *request)
{
return request->wValue;
}
//------------------------------------------------------------------------------
/// Returns the wIndex field of the given request.
/// \param request Pointer to a USBGenericRequest instance.
/// \return Request index;
//------------------------------------------------------------------------------
unsigned short USBGenericRequest_GetIndex(const USBGenericRequest *request)
{
return request->wIndex;
}
//------------------------------------------------------------------------------
/// Returns the expected length of the data phase following a request.
/// \param request Pointer to a USBGenericRequest instance.
/// \return Length of data phase.
//------------------------------------------------------------------------------
unsigned short USBGenericRequest_GetLength(const USBGenericRequest *request)
{
return request->wLength;
}
//------------------------------------------------------------------------------
/// Returns the endpoint number targetted by a given request.
/// \param request Pointer to a USBGenericRequest instance.
/// \return Endpoint number.
//------------------------------------------------------------------------------
unsigned char USBGenericRequest_GetEndpointNumber(
const USBGenericRequest *request)
{
return USBGenericRequest_GetIndex(request) & 0xF;
}
//------------------------------------------------------------------------------
/// Returns the intended recipient of a given request.
/// \param request Pointer to a USBGenericRequest instance.
/// \return Request recipient.
/// \sa "USB Request Recipients"
//------------------------------------------------------------------------------
unsigned char USBGenericRequest_GetRecipient(const USBGenericRequest *request)
{
// Recipient is in bits [0..4] of the bmRequestType field
return request->bmRequestType & 0xF;
}
//------------------------------------------------------------------------------
/// Returns the direction of the data transfer following the given request.
/// \param request Pointer to a USBGenericRequest instance.
/// \return Transfer direction.
/// \sa "USB Request Directions"
//------------------------------------------------------------------------------
unsigned char USBGenericRequest_GetDirection(const USBGenericRequest *request)
{
// Transfer direction is located in bit D7 of the bmRequestType field
if ((request->bmRequestType & 0x80) != 0) {
return USBGenericRequest_IN;
}
else {
return USBGenericRequest_OUT;
}
}
@@ -0,0 +1,244 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
\unit
!!!Purpose
Definition of the USBGenericRequest class and its methods.
!!!Usage
-# Declare or access USB requests by USBGenericRequest instance.
-# To get usful information (field values) from the USB requests, use
- USBGenericRequest_GetType
- USBGenericRequest_GetRequest
- USBGenericRequest_GetValue
- USBGenericRequest_GetIndex
- USBGenericRequest_GetLength
- USBGenericRequest_GetEndpointNumber
- USBGenericRequest_GetRecipient
- USBGenericRequest_GetDirection
*/
#ifndef USBGENERICREQUEST_H
#define USBGENERICREQUEST_H
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USB Generic Request definitions"
///
/// This page lists the codes of USB generic request.
///
/// - USB Request codes
/// - USBGenericRequest_GETSTATUS
/// - USBGenericRequest_CLEARFEATURE
/// - USBGenericRequest_SETFEATURE
/// - USBGenericRequest_SETADDRESS
/// - USBGenericRequest_GETDESCRIPTOR
/// - USBGenericRequest_SETDESCRIPTOR
/// - USBGenericRequest_GETCONFIGURATION
/// - USBGenericRequest_SETCONFIGURATION
/// - USBGenericRequest_GETINTERFACE
/// - USBGenericRequest_SETINTERFACE
/// - USBGenericRequest_SYNCHFRAME
///
/// - USB Request Recipients
/// - USBGenericRequest_DEVICE
/// - USBGenericRequest_INTERFACE
/// - USBGenericRequest_ENDPOINT
/// - USBGenericRequest_OTHER
///
/// - USB Request Types
/// - USBGenericRequest_STANDARD
/// - USBGenericRequest_CLASS
/// - USBGenericRequest_VENDOR
///
/// - USB Request Directions
/// - USBGenericRequest_IN
/// - USBGenericRequest_OUT
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USB Request codes"
///
/// This page lists the USB generic request codes.
///
/// !Codes
/// - USBGenericRequest_GETSTATUS
/// - USBGenericRequest_CLEARFEATURE
/// - USBGenericRequest_SETFEATURE
/// - USBGenericRequest_SETADDRESS
/// - USBGenericRequest_GETDESCRIPTOR
/// - USBGenericRequest_SETDESCRIPTOR
/// - USBGenericRequest_GETCONFIGURATION
/// - USBGenericRequest_SETCONFIGURATION
/// - USBGenericRequest_GETINTERFACE
/// - USBGenericRequest_SETINTERFACE
/// - USBGenericRequest_SYNCHFRAME
/// GET_STATUS request code.
#define USBGenericRequest_GETSTATUS 0
/// CLEAR_FEATURE request code.
#define USBGenericRequest_CLEARFEATURE 1
/// SET_FEATURE request code.
#define USBGenericRequest_SETFEATURE 3
/// SET_ADDRESS request code.
#define USBGenericRequest_SETADDRESS 5
/// GET_DESCRIPTOR request code.
#define USBGenericRequest_GETDESCRIPTOR 6
/// SET_DESCRIPTOR request code.
#define USBGenericRequest_SETDESCRIPTOR 7
/// GET_CONFIGURATION request code.
#define USBGenericRequest_GETCONFIGURATION 8
/// SET_CONFIGURATION request code.
#define USBGenericRequest_SETCONFIGURATION 9
/// GET_INTERFACE request code.
#define USBGenericRequest_GETINTERFACE 10
/// SET_INTERFACE request code.
#define USBGenericRequest_SETINTERFACE 11
/// SYNCH_FRAME request code.
#define USBGenericRequest_SYNCHFRAME 12
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USB Request Recipients"
///
/// This page lists codes of USB request recipients.
///
/// !Recipients
/// - USBGenericRequest_DEVICE
/// - USBGenericRequest_INTERFACE
/// - USBGenericRequest_ENDPOINT
/// - USBGenericRequest_OTHER
/// Recipient is the whole device.
#define USBGenericRequest_DEVICE 0
/// Recipient is an interface.
#define USBGenericRequest_INTERFACE 1
/// Recipient is an endpoint.
#define USBGenericRequest_ENDPOINT 2
/// Recipient is another entity.
#define USBGenericRequest_OTHER 3
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USB Request Types"
///
/// This page lists codes of USB request types.
///
/// !Types
/// - USBGenericRequest_STANDARD
/// - USBGenericRequest_CLASS
/// - USBGenericRequest_VENDOR
/// Request is standard.
#define USBGenericRequest_STANDARD 0
/// Request is class-specific.
#define USBGenericRequest_CLASS 1
/// Request is vendor-specific.
#define USBGenericRequest_VENDOR 2
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USB Request Directions"
///
/// This page lists codes of USB request directions.
///
/// !Directions
/// - USBGenericRequest_IN
/// - USBGenericRequest_OUT
/// Transfer occurs from device to the host.
#define USBGenericRequest_OUT 0
/// Transfer occurs from the host to the device.
#define USBGenericRequest_IN 1
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Generic USB SETUP request sent over Control endpoints.
//------------------------------------------------------------------------------
typedef struct {
/// Type of request
/// \sa "USB Request Recipients"
/// \sa "USB Request Types"
/// \sa "USB Request Directions"
unsigned char bmRequestType:8;
/// Request code
/// \sa "USB Request Codes"
unsigned char bRequest:8;
/// Request-specific value parameter.
unsigned short wValue:16;
/// Request-specific index parameter.
unsigned short wIndex:16;
/// Expected length (in bytes) of the data phase.
unsigned short wLength:16;
} USBGenericRequest;
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern unsigned char USBGenericRequest_GetType(
const USBGenericRequest *request);
extern unsigned char USBGenericRequest_GetRequest(
const USBGenericRequest *request);
extern unsigned short USBGenericRequest_GetValue(
const USBGenericRequest *request);
extern unsigned short USBGenericRequest_GetIndex(
const USBGenericRequest *request);
extern unsigned short USBGenericRequest_GetLength(
const USBGenericRequest *request);
extern unsigned char USBGenericRequest_GetEndpointNumber(
const USBGenericRequest *request);
extern unsigned char USBGenericRequest_GetRecipient(
const USBGenericRequest *request);
extern unsigned char USBGenericRequest_GetDirection(
const USBGenericRequest *request);
#endif //#ifndef USBGENERICREQUEST_H
@@ -0,0 +1,72 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*
Title: USBGetDescriptorRequest implementation
About: Purpose
Implementation of the USBGetDescriptorRequest class.
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "USBGetDescriptorRequest.h"
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Returns the type of the descriptor requested by the host given the
/// corresponding GET_DESCRIPTOR request.
/// \param request Pointer to a USBGenericDescriptor instance.
/// \return Type of the requested descriptor.
//------------------------------------------------------------------------------
unsigned char USBGetDescriptorRequest_GetDescriptorType(
const USBGenericRequest *request)
{
// Requested descriptor type is in the high-byte of the wValue field
return (USBGenericRequest_GetValue(request) >> 8) & 0xFF;
}
//------------------------------------------------------------------------------
/// Returns the index of the requested descriptor, given the corresponding
/// GET_DESCRIPTOR request.
/// \param request Pointer to a USBGenericDescriptor instance.
/// \return Index of the requested descriptor.
//------------------------------------------------------------------------------
unsigned char USBGetDescriptorRequest_GetDescriptorIndex(
const USBGenericRequest *request)
{
// Requested descriptor index if in the low byte of the wValue field
return USBGenericRequest_GetValue(request) & 0xFF;
}
@@ -0,0 +1,67 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
\unit
!!!Purpose
Definition of the USBGetDescriptorRequest class.
!!!Usage
- After a GET_DESCRIPTOR request has been received, retrive the useful
values with following functions:
- USBGetDescriptorRequest_GetDescriptorType: the descriptor type
- USBGetDescriptorRequest_GetDescriptorIndex: the index of the requested
descriptor
*/
#ifndef USBGETDESCRIPTORREQUEST_H
#define USBGETDESCRIPTORREQUEST_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "USBGenericRequest.h"
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern unsigned char USBGetDescriptorRequest_GetDescriptorType(
const USBGenericRequest *request);
extern unsigned char USBGetDescriptorRequest_GetDescriptorIndex(
const USBGenericRequest *request);
#endif //#ifndef USBGETDESCRIPTORREQUEST_H
@@ -0,0 +1,86 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \page USBInterfaceAssociateDescriptor
* !!!Purpose
*
* Class for manipulating USB IAD descriptors.
*
* !!!Usage
*
* -# Test
*/
#ifndef USBDIADDESCRIPTOR_H
#define USBDIADDESCRIPTOR_H
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
#ifdef __ICCARM__ // IAR
#pragma pack(1) // IAR
#define __attribute__(...) // IAR
#endif // IAR
/*
Type: USBDeviceDescriptor
USB standard device descriptor structure.
Variables:
bLength - Size of this descriptor in bytes.
bDescriptorType - Descriptor type (<USBGenericDescriptor_IAD>).
bFirstInterface - Interface number of the first interface that is
associated with this function.
bInterfaceCount - Number of contiguous interfaces that are
associated with this function.
bFunctionClass - Class code (assigned by USB-IF).
bFunctionSubClass - Subclass code (assigned by USB-IF).
bFunctionProtocol - Protocol code (assigned by USB-IF)
iFunction - Index of string descriptor describing this function.
*/
typedef struct {
unsigned char bLength;
unsigned char bDescriptorType;
unsigned char bFirstInterface;
unsigned char bInterfaceCount;
unsigned char bFunctionClass;
unsigned char bFunctionSubClass;
unsigned char bFunctionProtocol;
unsigned char iFunction;
} __attribute__ ((packed)) USBInterfaceAssociationDescriptor; // GCC
#ifdef __ICCARM__ // IAR
#pragma pack() // IAR
#endif // IAR
#endif //#ifndef USBDIADDESCRIPTOR_H
@@ -0,0 +1,87 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
\unit
!!!Purpose
Definition of a class for manipulating USB interface descriptors.
!!!Usage
- Declare USBInterfaceDescriptor instance as a part of the configuration
descriptors of a USB device.
*/
#ifndef USBINTERFACEDESCRIPTOR_H
#define USBINTERFACEDESCRIPTOR_H
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
#ifdef __ICCARM__ // IAR
#pragma pack(1) // IAR
#define __attribute__(...) // IAR
#endif // IAR
//------------------------------------------------------------------------------
/// USB standard interface descriptor structure.
//------------------------------------------------------------------------------
typedef struct {
/// Size of the descriptor in bytes.
unsigned char bLength;
/// Descriptor type (USBGenericDescriptor_INTERFACE).
unsigned char bDescriptorType;
/// Number of the interface in its configuration.
unsigned char bInterfaceNumber;
/// Value to select this alternate interface setting.
unsigned char bAlternateSetting;
/// Number of endpoints used by the inteface (excluding endpoint 0).
unsigned char bNumEndpoints;
/// Interface class code.
unsigned char bInterfaceClass;
/// Interface subclass code.
unsigned char bInterfaceSubClass;
/// Interface protocol code.
unsigned char bInterfaceProtocol;
/// Index of the interface string descriptor.
unsigned char iInterface;
} __attribute__ ((packed)) USBInterfaceDescriptor; // GCC
#ifdef __ICCARM__ // IAR
#pragma pack() // IAR
#endif // IAR
#endif //#ifndef USBINTERFACEDESCRIPTOR_H
@@ -0,0 +1,69 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*
Title: USBInterfaceRequest
About: Purpose
Implementation of USBInterfaceRequest class methods.
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "USBInterfaceRequest.h"
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Indicates which interface is targetted by a GET_INTERFACE or
/// SET_INTERFACE request.
/// \param request Pointer to a USBGenericRequest instance.
/// \return Interface number.
//------------------------------------------------------------------------------
unsigned char USBInterfaceRequest_GetInterface(const USBGenericRequest *request)
{
return (USBGenericRequest_GetIndex(request) & 0xFF);
}
//------------------------------------------------------------------------------
/// Indicates the new alternate setting that the interface targetted by a
/// SET_INTERFACE request should use.
/// \param request Pointer to a USBGenericRequest instance.
/// \return New active setting for the interface.
//------------------------------------------------------------------------------
unsigned char USBInterfaceRequest_GetAlternateSetting(
const USBGenericRequest *request)
{
return (USBGenericRequest_GetValue(request) & 0xFF);
}
@@ -0,0 +1,68 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
\unit
!!!Purpose
Definitions for manipulating SET_INTERFACE and GET_INTERFACE request.
!!!Usage
-# After a SET_INTERFACE request has been received, retrieve the
target interface using USBInterfaceRequest_GetInterface and its
new alternate setting with USBInterfaceRequest_GetAlternateSetting.
-# After a GET_INTERFACE request has been received, retrieve the target
interface using USBInterfaceRequest_GetInterface.
*/
#ifndef USBINTERFACEREQUEST_H
#define USBINTERFACEREQUEST_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "USBGenericRequest.h"
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern unsigned char USBInterfaceRequest_GetInterface(
const USBGenericRequest *request);
extern unsigned char USBInterfaceRequest_GetAlternateSetting(
const USBGenericRequest *request);
#endif //#ifndef USBINTERFACEREQUEST_H
@@ -0,0 +1,62 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*
Title: USBIrqHandler implementation
About: Purpose
Implementation of the USB Interrupt Handler.
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
#include <usb/device/core/USBD.h>
#include <exceptions.h>
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Call Arbitrer, device and host interrupt handler.
/// The IRQ functions are defined with weak and can be surcharged if needed.
//------------------------------------------------------------------------------
void USB_IrqHandler( void )
{
// Most arbitrer interrupt
usb_general_interrupt();
// Device interrupt
USBD_IrqHandler();
// Host interrupt
usb_pipe_interrupt();
}
@@ -0,0 +1,52 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
\unit
!!!Purpose
Implementation of the USB Interrupt Handler.
!!!Usage
-# The IRQ functions are defined with weak and can be surcharged if needed.
*/
#ifndef USBIRQHANDLER_H
#define USBIRQHANDLER_H
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void USB_IrqHandler( void );
#endif //#ifndef USBIRQHANDLER_H
@@ -0,0 +1,56 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*
Title: USBSetAddressRequest implementation
About: Purpose
Implementation of the USBSetAddressRequest class.
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "USBSetAddressRequest.h"
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Returns the address that the device must take in response to a
/// SET_ADDRESS request.
/// \param request Pointer to a USBGenericRequest instance.
/// \return New device address.
//------------------------------------------------------------------------------
unsigned char USBSetAddressRequest_GetAddress(const USBGenericRequest *request)
{
return USBGenericRequest_GetValue(request) & 0x7F;
}
@@ -0,0 +1,60 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
\unit
!!!Purpose
Definition of a class for manipulating SET_ADDRESS USB requests.
!!!Usage
- After a SET_ADDRESS request has been received, retrive the new address
value with USBSetAddressRequest_GetAddress.
*/
#ifndef USBSETADDRESSREQUEST_H
#define USBSETADDRESSREQUEST_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "USBGenericRequest.h"
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern unsigned char USBSetAddressRequest_GetAddress(
const USBGenericRequest *request);
#endif //#ifndef USBSETADDRESSREQUEST_H
@@ -0,0 +1,58 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*
Title: USBSetConfigurationRequest implementation
About: Purpose
Implementation of the USBSetConfigurationRequest class.
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "USBSetConfigurationRequest.h"
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Returns the number of the configuration that should be set in response
/// to the given SET_CONFIGURATION request.
/// \param request Pointer to a USBGenericRequest instance.
/// \return Number of the requested configuration.
//------------------------------------------------------------------------------
unsigned char USBSetConfigurationRequest_GetConfiguration(
const USBGenericRequest *request)
{
return USBGenericRequest_GetValue(request);
}
@@ -0,0 +1,61 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
\unit
!!!Purpose
Definition of a class for the Set Configuration request.
!!!Usage
- After a SET_CONFIGURATION request has been received, retrive the new
configuration value with USBSetConfigurationRequest_GetConfiguration.
*/
#ifndef USBSETCONFIGURATIONREQUEST_H
#define USBSETCONFIGURATIONREQUEST_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "USBGenericRequest.h"
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern unsigned char USBSetConfigurationRequest_GetConfiguration(
const USBGenericRequest *request);
#endif //#ifndef USBSETCONFIGURATIONREQUEST_H
@@ -0,0 +1,74 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
///
/// !!!Purpose
///
/// Definition of a class for manipulating String descriptors.
//------------------------------------------------------------------------------
#ifndef USBSTRINGDESCRIPTOR_H
#define USBSTRINGDESCRIPTOR_H
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USB String Descriptor definitions"
///
/// This page lists the codes and macros for USB string descriptor definition.
///
/// !Language IDs
/// - USBStringDescriptor_ENGLISH_US
///
/// !String Descriptor Length
/// - USBStringDescriptor_LENGTH
///
/// !ASCII to UNICODE convertion
/// - USBStringDescriptor_UNICODE
/// Language ID for US english.
#define USBStringDescriptor_ENGLISH_US 0x09, 0x04
/// Calculates the length of a string descriptor given the number of ascii
/// characters/language IDs in it.
/// \param length The ascii format string length.
/// \return The actual data length in bytes.
#define USBStringDescriptor_LENGTH(length) ((length) * 2 + 2)
/// Converts an ascii character to its unicode representation.
/// \param ascii The ASCII character to convert
/// \return A 2-byte-array for the UNICODE based on given ASCII
#define USBStringDescriptor_UNICODE(ascii) (ascii), 0
//------------------------------------------------------------------------------
#endif //#ifndef USBSTRINGDESCRIPTOR_H
@@ -0,0 +1,73 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
/// !Purpose
///
/// Declaration of constants for using Device Descriptors with a Mass Storage
/// driver.
///
/// !Usage
///
/// - For a USB device:
/// -# When declaring a USBDeviceDescriptor instance, use the Mass Storage
/// codes defined in this file (see "MS device codes").
//------------------------------------------------------------------------------
#ifndef MSDEVICEDESCRIPTOR_H
#define MSDEVICEDESCRIPTOR_H
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "MS device codes"
/// This page lists the class, subclass & protocol codes used by a device with
/// a Mass Storage driver.
///
/// !Codes
///
/// - MSDeviceDescriptor_CLASS
/// - MSDeviceDescriptor_SUBCLASS
/// - MSDeviceDescriptor_PROTOCOL
/// Class code for a Mass Storage device.
#define MSDeviceDescriptor_CLASS 0
/// Subclass code for a Mass Storage device.
#define MSDeviceDescriptor_SUBCLASS 0
/// Protocol code for a Mass Storage device.
#define MSDeviceDescriptor_PROTOCOL 0
//------------------------------------------------------------------------------
#endif //#ifndef MSDEVICEDESCRIPTOR_H
@@ -0,0 +1,75 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
/// !Purpose
///
/// Definition of several constants used when manipulating Mass Storage interface
/// descriptors.
///
/// !Usage
///
/// - For a USB device:
/// -# When declaring an interface descriptor for a Mass Storage device, use
/// the class, subclass and protocol codes defined here (see
/// "MS interface codes").
//------------------------------------------------------------------------------
#ifndef MSINTERFACEDESCRIPTOR_H
#define MSINTERFACEDESCRIPTOR_H
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "MS interface codes"
/// This page lists the available class, subclass & protocol codes for a Mass
/// Storage interface.
///
/// !Codes
///
/// - MSInterfaceDescriptor_CLASS
/// - MSInterfaceDescriptor_SCSI
/// - MSInterfaceDescriptor_BULKONLY
/// Class code for a Mass Storage interface.
#define MSInterfaceDescriptor_CLASS 0x08
/// Subclass code for a Mass Storage interface using the SCSI protocol.
#define MSInterfaceDescriptor_SCSI 0x06
/// Protocol code for a Mass Storage interface using Bulk-Only Transport.
#define MSInterfaceDescriptor_BULKONLY 0x50
//------------------------------------------------------------------------------
#endif //#ifndef MSINTERFACEDESCRIPTOR_H
@@ -0,0 +1,290 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
///
/// !!!Purpose
///
/// Collection of methods for using the USB device controller on AT91
/// microcontrollers.
///
/// !!!Usage
///
/// Please refer to the corresponding application note.
/// - "AT91 USB device framework"
/// - "USBD API" . "USBD API Methods"
//------------------------------------------------------------------------------
#ifndef USBD_H
#define USBD_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
// #include <board.h>
#include <usb/common/core/USBEndpointDescriptor.h>
#include <usb/common/core/USBGenericRequest.h>
//------------------------------------------------------------------------------
// Compile Options
//------------------------------------------------------------------------------
/// Compile option for HS or OTG, use DMA. Remove this define for not use DMA.
#if defined(CHIP_USB_OTGHS) || defined(CHIP_USB_UDPHS)
#define DMA
#endif
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USB device API return values"
///
/// This page lists the return values of the USB %device driver API
///
/// !Return codes
/// - USBD_STATUS_SUCCESS
/// - USBD_STATUS_LOCKED
/// - USBD_STATUS_ABORTED
/// - USBD_STATUS_RESET
/// Indicates the operation was successful.
#define USBD_STATUS_SUCCESS 0
/// Endpoint/device is already busy.
#define USBD_STATUS_LOCKED 1
/// Operation has been aborted.
#define USBD_STATUS_ABORTED 2
/// Operation has been aborted because the device has been reset.
#define USBD_STATUS_RESET 3
/// Part ot operation successfully done.
#define USBD_STATUS_PARTIAL_DONE 4
/// Operation failed because parameter error
#define USBD_STATUS_INVALID_PARAMETER 5
/// Operation failed because in unexpected state
#define USBD_STATUS_WRONG_STATE 6
/// Operation failed because HW not supported
#define USBD_STATUS_HW_NOT_SUPPORTED 0xFE
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USB device states"
///
/// This page lists the %device states of the USB %device driver.
///
/// !States
/// - USBD_STATE_SUSPENDED
/// - USBD_STATE_ATTACHED
/// - USBD_STATE_POWERED
/// - USBD_STATE_DEFAULT
/// - USBD_STATE_ADDRESS
/// - USBD_STATE_CONFIGURED
/// The device is currently suspended.
#define USBD_STATE_SUSPENDED 0
/// USB cable is plugged into the device.
#define USBD_STATE_ATTACHED 1
/// Host is providing +5V through the USB cable.
#define USBD_STATE_POWERED 2
/// Device has been reset.
#define USBD_STATE_DEFAULT 3
/// The device has been given an address on the bus.
#define USBD_STATE_ADDRESS 4
/// A valid configuration has been selected.
#define USBD_STATE_CONFIGURED 5
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USB device LEDs"
///
/// This page lists the LEDs used in the USB %device driver.
///
/// !LEDs
/// - USBD_LEDPOWER
/// - USBD_LEDUSB
/// - USBD_LEDOTHER
/// LED for indicating that the device is powered.
#define USBD_LEDPOWER 0
/// LED for indicating USB activity.
#define USBD_LEDUSB 1
/// LED for custom usage.
#define USBD_LEDOTHER 2
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Buffer struct used for multi-buffer-listed transfer.
/// The driver can process 255 bytes of buffers or buffer list window.
//------------------------------------------------------------------------------
typedef struct _USBDTransferBuffer {
/// Pointer to frame buffer
unsigned char * pBuffer;
/// Size of the frame (up to 64K-1)
unsigned short size;
/// Bytes transferred
unsigned short transferred;
/// Bytes in FIFO
unsigned short buffered;
/// Bytes remaining
unsigned short remaining;
} USBDTransferBuffer;
#ifdef __ICCARM__ // IAR
#define __attribute__(...) // IAR
#endif // IAR
//------------------------------------------------------------------------------
/// Struct used for USBD DMA Link List Transfer Descriptor, must be 16-bytes
/// aligned.
/// (For USB, DMA transfer is linked to EPs and FIFO address is EP defined)
//------------------------------------------------------------------------------
typedef struct _USBDDmaDescriptor {
/// Pointer to Next Descriptor
void* pNxtDesc;
/// Pointer to data buffer address
void* pDataAddr;
/// DMA Control setting register value
unsigned int ctrlSettings:8, /// Control settings
reserved:8, /// Not used
bufferLength:16; /// Length of buffer
/// Loaded to DMA register, OK to modify
unsigned int used;
} __attribute__((aligned(16))) USBDDmaDescriptor;
#ifdef __ICCARM__ // IAR
#pragma pack() // IAR
#endif // IAR
//------------------------------------------------------------------------------
/// Callback used by transfer functions (USBD_Read & USBD_Write) to notify
/// that a transaction is complete.
//------------------------------------------------------------------------------
typedef void (*TransferCallback)(void *pArg,
unsigned char status,
unsigned int transferred,
unsigned int remaining);
//------------------------------------------------------------------------------
/// Callback used by MBL transfer functions (USBD_Read & USBD_Write) to notify
/// that a transaction is complete.
/// \param pArg Pointer to callback arguments.
/// \param status USBD status.
/// \param nbFreed Number of buffers that is freed since last callback.
//------------------------------------------------------------------------------
typedef void (*MblTransferCallback)(void *pArg,
unsigned char status,
unsigned int nbFreed);
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void USBD_IrqHandler(void);
extern void USBD_Init(void);
extern void USBD_ConfigureSpeed(unsigned char forceFS);
extern void USBD_Connect(void);
extern void USBD_Disconnect(void);
extern char USBD_Write(
unsigned char bEndpoint,
const void *pData,
unsigned int size,
TransferCallback callback,
void *pArg);
extern char USBD_MblWrite(
unsigned char bEndpoint,
void * pMbl,
unsigned short wListSize,
unsigned char bCircList,
unsigned short wStartNdx,
MblTransferCallback fCallback,
void * pArgument);
extern char USBD_MblReuse(
unsigned char bEndpoint,
unsigned char * pNewBuffer,
unsigned short wNewSize);
extern char USBD_Read(
unsigned char bEndpoint,
void *pData,
unsigned int dLength,
TransferCallback fCallback,
void *pArg);
extern unsigned char USBD_Stall(unsigned char bEndpoint);
extern void USBD_Halt(unsigned char bEndpoint);
extern void USBD_Unhalt(unsigned char bEndpoint);
extern void USBD_ConfigureEndpoint(const USBEndpointDescriptor *pDescriptor);
extern unsigned char USBD_IsHalted(unsigned char bEndpoint);
extern void USBD_RemoteWakeUp(void);
extern void USBD_SetAddress(unsigned char address);
extern void USBD_SetConfiguration(unsigned char cfgnum);
extern unsigned char USBD_GetState(void);
extern unsigned char USBD_IsHighSpeed(void);
extern void USBD_Test(unsigned char bIndex);
/* USBD Callbacks */
#define USBDCallbacks_Reset()
#define USBDCallbacks_Suspended()
#define USBDCallbacks_Resumed()
extern void USBDCallbacks_RequestReceived(const USBGenericRequest *request);
extern void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum);
extern void USBDDriverCallbacks_InterfaceSettingChanged(unsigned char interface,
unsigned char setting);
#endif //#ifndef USBD_H
@@ -0,0 +1,752 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "USBDDriver.h"
#include "USBD.h"
#include <board.h>
#include "debug.h"
#include <usb/common/core/USBGenericDescriptor.h>
#include <usb/common/core/USBDeviceDescriptor.h>
#include <usb/common/core/USBConfigurationDescriptor.h>
#include <usb/common/core/USBDeviceQualifierDescriptor.h>
#include <usb/common/core/USBEndpointDescriptor.h>
#include <usb/common/core/USBFeatureRequest.h>
#include <usb/common/core/USBSetAddressRequest.h>
#include <usb/common/core/USBGetDescriptorRequest.h>
#include <usb/common/core/USBSetConfigurationRequest.h>
#include <usb/common/core/USBInterfaceRequest.h>
#include <string.h>
//------------------------------------------------------------------------------
// Local functions
//------------------------------------------------------------------------------
#if defined(CHIP_USB_OTGHS)
static unsigned char otg_features_supported = 0;
#endif
//------------------------------------------------------------------------------
/// Send a NULL packet
//------------------------------------------------------------------------------
static void TerminateCtrlInWithNull(void *pArg,
unsigned char status,
unsigned int transferred,
unsigned int remaining)
{
USBD_Write(0, // Endpoint #0
0, // No data buffer
0, // No data buffer
(TransferCallback) 0,
(void *) 0);
}
//------------------------------------------------------------------------------
/// Configures the device by setting it into the Configured state and
/// initializing all endpoints.
/// \param pDriver Pointer to a USBDDriver instance.
/// \param cfgnum Configuration number to set.
//------------------------------------------------------------------------------
static void SetConfiguration(USBDDriver *pDriver, unsigned char cfgnum)
{
USBEndpointDescriptor *pEndpoints[CHIP_USB_NUMENDPOINTS+1];
const USBConfigurationDescriptor *pConfiguration;
// Use different descriptor depending on device speed
if (USBD_IsHighSpeed()) {
pConfiguration = pDriver->pDescriptors->pHsConfiguration;
}
else {
pConfiguration = pDriver->pDescriptors->pFsConfiguration;
}
// Set & save the desired configuration
USBD_SetConfiguration(cfgnum);
pDriver->cfgnum = cfgnum;
// If the configuration is not 0, configure endpoints
if (cfgnum != 0) {
// Parse configuration to get endpoint descriptors
USBConfigurationDescriptor_Parse(pConfiguration, 0, pEndpoints, 0);
// Configure endpoints
int i = 0;
while (pEndpoints[i] != 0) {
USBD_ConfigureEndpoint(pEndpoints[i]);
i++;
}
}
// Should be done before send the ZLP
USBDDriverCallbacks_ConfigurationChanged(cfgnum);
// Acknowledge the request
USBD_Write(0, // Endpoint #0
0, // No data buffer
0, // No data buffer
(TransferCallback) 0,
(void *) 0);
}
//------------------------------------------------------------------------------
/// Sends the current configuration number to the host.
/// \param pDriver Pointer to a USBDDriver instance.
//------------------------------------------------------------------------------
static void GetConfiguration(const USBDDriver *pDriver)
{
USBD_Write(0, &(pDriver->cfgnum), 1, 0, 0);
}
//------------------------------------------------------------------------------
/// Sends the current status of the device to the host.
/// \param pDriver Pointer to a USBDDriver instance.
//------------------------------------------------------------------------------
static void GetDeviceStatus(const USBDDriver *pDriver)
{
static unsigned short data;
const USBConfigurationDescriptor *pConfiguration;
data = 0;
// Use different configuration depending on device speed
if (USBD_IsHighSpeed()) {
pConfiguration = pDriver->pDescriptors->pHsConfiguration;
}
else {
pConfiguration = pDriver->pDescriptors->pFsConfiguration;
}
// Check current configuration for power mode (if device is configured)
if (pDriver->cfgnum != 0) {
if (USBConfigurationDescriptor_IsSelfPowered(pConfiguration)) {
data |= 1;
}
}
// Check if remote wake-up is enabled
if (pDriver->isRemoteWakeUpEnabled) {
data |= 2;
}
// Send the device status
USBD_Write(0, &data, 2, 0, 0);
}
//------------------------------------------------------------------------------
/// Sends the current status of an endpoints to the USB host.
/// \param bEndpoint Endpoint number.
//------------------------------------------------------------------------------
static void GetEndpointStatus(unsigned char bEndpoint)
{
static unsigned short data;
data = 0;
// Check if the endpoint exists
if (bEndpoint > CHIP_USB_NUMENDPOINTS) {
USBD_Stall(0);
}
else {
// Check if the endpoint if currently halted
if (USBD_IsHalted(bEndpoint)) {
data = 1;
}
// Send the endpoint status
USBD_Write(0, &data, 2, 0, 0);
}
}
//------------------------------------------------------------------------------
/// Sends the requested USB descriptor to the host if available, or STALLs the
/// request.
/// \param pDriver Pointer to a USBDDriver instance.
/// \param type Type of the requested descriptor
/// \param index Index of the requested descriptor.
/// \param length Maximum number of bytes to return.
//------------------------------------------------------------------------------
static void GetDescriptor(
const USBDDriver *pDriver,
unsigned char type,
unsigned char indexRDesc,
unsigned int length)
{
const USBDeviceDescriptor *pDevice;
const USBConfigurationDescriptor *pConfiguration;
const USBDeviceQualifierDescriptor *pQualifier;
const USBConfigurationDescriptor *pOtherSpeed;
const USBGenericDescriptor **pStrings =
(const USBGenericDescriptor **) pDriver->pDescriptors->pStrings;
const USBGenericDescriptor *pString;
unsigned char numStrings = pDriver->pDescriptors->numStrings;
unsigned char terminateWithNull = 0;
// Use different set of descriptors depending on device speed
if (USBD_IsHighSpeed()) {
TRACE_DEBUG("HS ");
pDevice = pDriver->pDescriptors->pHsDevice;
pConfiguration = pDriver->pDescriptors->pHsConfiguration;
pQualifier = pDriver->pDescriptors->pHsQualifier;
pOtherSpeed = pDriver->pDescriptors->pHsOtherSpeed;
}
else {
TRACE_DEBUG("FS ");
pDevice = pDriver->pDescriptors->pFsDevice;
pConfiguration = pDriver->pDescriptors->pFsConfiguration;
pQualifier = pDriver->pDescriptors->pFsQualifier;
pOtherSpeed = pDriver->pDescriptors->pFsOtherSpeed;
}
// Check the descriptor type
switch (type) {
case USBGenericDescriptor_DEVICE:
TRACE_INFO_WP("Dev ");
// Adjust length and send descriptor
if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice)) {
length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice);
}
USBD_Write(0, pDevice, length, 0, 0);
break;
case USBGenericDescriptor_CONFIGURATION:
TRACE_INFO_WP("Cfg ");
// Adjust length and send descriptor
if (length > USBConfigurationDescriptor_GetTotalLength(pConfiguration)) {
length = USBConfigurationDescriptor_GetTotalLength(pConfiguration);
terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
}
USBD_Write(0,
pConfiguration,
length,
terminateWithNull ? TerminateCtrlInWithNull : 0,
0);
break;
case USBGenericDescriptor_DEVICEQUALIFIER:
TRACE_INFO_WP("Qua ");
// Check if descriptor exists
if (!pQualifier) {
USBD_Stall(0);
}
else {
// Adjust length and send descriptor
if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier)) {
length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier);
}
USBD_Write(0, pQualifier, length, 0, 0);
}
break;
case USBGenericDescriptor_OTHERSPEEDCONFIGURATION:
TRACE_INFO_WP("OSC ");
// Check if descriptor exists
if (!pOtherSpeed) {
USBD_Stall(0);
}
else {
// Adjust length and send descriptor
if (length > USBConfigurationDescriptor_GetTotalLength(pOtherSpeed)) {
length = USBConfigurationDescriptor_GetTotalLength(pOtherSpeed);
terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
}
USBD_Write(0,
pOtherSpeed,
length,
terminateWithNull ? TerminateCtrlInWithNull : 0,
0);
}
break;
case USBGenericDescriptor_STRING:
TRACE_INFO_WP("Str%d ", indexRDesc);
// Check if descriptor exists
if (indexRDesc > numStrings) {
USBD_Stall(0);
}
else {
pString = pStrings[indexRDesc];
// Adjust length and send descriptor
if (length > USBGenericDescriptor_GetLength(pString)) {
length = USBGenericDescriptor_GetLength(pString);
terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0);
}
USBD_Write(0,
pString,
length,
terminateWithNull ? TerminateCtrlInWithNull : 0,
0);
}
break;
default:
TRACE_WARNING(
"USBDDriver_GetDescriptor: Unknown descriptor type (%d)\n\r",
type);
USBD_Stall(0);
}
}
//------------------------------------------------------------------------------
/// Sets the active setting of the given interface if the configuration supports
/// it; otherwise, the control pipe is STALLed. If the setting of an interface
/// changes.
/// \parma pDriver Pointer to a USBDDriver instance.
/// \parma infnum Interface number.
/// \parma setting New active setting for the interface.
//------------------------------------------------------------------------------
static void SetInterface(
USBDDriver *pDriver,
unsigned char infnum,
unsigned char setting)
{
// Make sure alternate settings are supported
if (!pDriver->pInterfaces) {
USBD_Stall(0);
}
else {
// Change the current setting of the interface and trigger the callback
// if necessary
if (pDriver->pInterfaces[infnum] != setting) {
pDriver->pInterfaces[infnum] = setting;
// USBDDriverCallbacks_InterfaceSettingChanged(infnum, setting);
}
// Acknowledge the request
USBD_Write(0, 0, 0, 0, 0);
}
}
//------------------------------------------------------------------------------
/// Sends the currently active setting of the given interface to the USB
/// host. If alternate settings are not supported, this function STALLs the
/// control pipe.
/// \param pDriver Pointer to a USBDDriver instance.
/// \param infnum Interface number.
//------------------------------------------------------------------------------
static void GetInterface(
const USBDDriver *pDriver,
unsigned char infnum)
{
// Make sure alternate settings are supported, or STALL the control pipe
if (!pDriver->pInterfaces) {
USBD_Stall(0);
}
else {
// Sends the current interface setting to the host
USBD_Write(0, &(pDriver->pInterfaces[infnum]), 1, 0, 0);
}
}
#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
//------------------------------------------------------------------------------
// Performs the selected test on the USB device (high-speed only).
// \param test Test selector value.
//------------------------------------------------------------------------------
static void USBDDriver_Test(unsigned char test)
{
TRACE_DEBUG("UDPHS_Test\n\r");
// the lower byte of wIndex must be zero
// the most significant byte of wIndex is used to specify the specific test mode
switch (test) {
case USBFeatureRequest_TESTPACKET:
//Test mode Test_Packet:
//Upon command, a port must repetitively transmit the following test packet until
//the exit action is taken. This enables the testing of rise and fall times, eye
//patterns, jitter, and any other dynamic waveform specifications.
//The test packet is made up by concatenating the following strings.
//(Note: For J/K NRZI data, and for NRZ data, the bit on the left is the first one
//transmitted. “S” indicates that a bit stuff occurs, which inserts an “extra” NRZI data bit.
//“* N” is used to indicate N occurrences of a string of bits or symbols.)
//A port in Test_Packet mode must send this packet repetitively. The inter-packet timing
//must be no less than the minimum allowable inter-packet gap as defined in Section 7.1.18 and
//no greater than 125 us.
// Send ZLP
USBD_Test(USBFeatureRequest_TESTSENDZLP);
// Tst PACKET
USBD_Test(USBFeatureRequest_TESTPACKET);
while (1);
//break; not reached
case USBFeatureRequest_TESTJ:
//Test mode Test_J:
//Upon command, a port’s transceiver must enter the high-speed J state and remain in that
//state until the exit action is taken. This enables the testing of the high output drive
//level on the D+ line.
// Send ZLP
USBD_Test(USBFeatureRequest_TESTSENDZLP);
// Tst J
USBD_Test(USBFeatureRequest_TESTJ);
while (1);
//break; not reached
case USBFeatureRequest_TESTK:
//Test mode Test_K:
//Upon command, a port’s transceiver must enter the high-speed K state and remain in
//that state until the exit action is taken. This enables the testing of the high output drive
//level on the D- line.
// Send a ZLP
USBD_Test(USBFeatureRequest_TESTSENDZLP);
USBD_Test(USBFeatureRequest_TESTK);
while (1);
//break; not reached
case USBFeatureRequest_TESTSE0NAK:
//Test mode Test_SE0_NAK:
//Upon command, a port’s transceiver must enter the high-speed receive mode
//and remain in that mode until the exit action is taken. This enables the testing
//of output impedance, low level output voltage, and loading characteristics.
//In addition, while in this mode, upstream facing ports (and only upstream facing ports)
//must respond to any IN token packet with a NAK handshake (only if the packet CRC is
//determined to be correct) within the normal allowed device response time. This enables testing of
//the device squelch level circuitry and, additionally, provides a general purpose stimulus/response
//test for basic functional testing.
// Send a ZLP
USBD_Test(USBFeatureRequest_TESTSENDZLP);
// Test SE0_NAK
USBD_Test(USBFeatureRequest_TESTSE0NAK);
while (1);
//break; not reached
default:
USBD_Stall(0);
break;
}
// The exit action is to power cycle the device.
// The device must be disconnected from the host
}
#endif
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Initializes a USBDDriver instance with a list of descriptors. If
/// interfaces can have multiple alternate settings, an array to store the
/// current setting for each interface must be provided.
/// \param pDriver Pointer to a USBDDriver instance.
/// \param pDescriptors Pointer to a USBDDriverDescriptors instance.
/// \param pInterfaces Pointer to an array for storing the current alternate
/// setting of each interface (optional).
//------------------------------------------------------------------------------
void USBDDriver_Initialize(
USBDDriver *pDriver,
const USBDDriverDescriptors *pDescriptors,
unsigned char *pInterfaces)
{
pDriver->cfgnum = 0;
#if (BOARD_USB_BMATTRIBUTES == USBConfigurationDescriptor_SELFPOWERED_RWAKEUP) \
|| (BOARD_USB_BMATTRIBUTES == USBConfigurationDescriptor_BUSPOWERED_RWAKEUP)
pDriver->isRemoteWakeUpEnabled = 1;
#else
pDriver->isRemoteWakeUpEnabled = 0;
#endif
pDriver->pDescriptors = pDescriptors;
pDriver->pInterfaces = pInterfaces;
// Initialize interfaces array if not null
if (pInterfaces != 0) {
memset(pInterfaces, sizeof(pInterfaces), 0);
}
}
//------------------------------------------------------------------------------
/// Handles the given request if it is standard, otherwise STALLs it.
/// \param pDriver Pointer to a USBDDriver instance.
/// \param pRequest Pointer to a USBGenericRequest instance.
//------------------------------------------------------------------------------
void USBDDriver_RequestHandler(
USBDDriver *pDriver,
const USBGenericRequest *pRequest)
{
unsigned char cfgnum;
unsigned char infnum;
unsigned char eptnum;
unsigned char setting;
unsigned char type;
unsigned char indexDesc;
unsigned int length;
unsigned int address;
TRACE_INFO_WP("Std ");
// Check request code
switch (USBGenericRequest_GetRequest(pRequest)) {
case USBGenericRequest_GETDESCRIPTOR:
TRACE_INFO_WP("gDesc ");
// Send the requested descriptor
type = USBGetDescriptorRequest_GetDescriptorType(pRequest);
indexDesc = USBGetDescriptorRequest_GetDescriptorIndex(pRequest);
length = USBGenericRequest_GetLength(pRequest);
GetDescriptor(pDriver, type, indexDesc, length);
break;
case USBGenericRequest_SETADDRESS:
TRACE_INFO_WP("sAddr ");
// Sends a zero-length packet and then set the device address
address = USBSetAddressRequest_GetAddress(pRequest);
USBD_Write(0, 0, 0, (TransferCallback) USBD_SetAddress, (void *) address);
break;
case USBGenericRequest_SETCONFIGURATION:
TRACE_INFO_WP("sCfg ");
// Set the requested configuration
cfgnum = USBSetConfigurationRequest_GetConfiguration(pRequest);
SetConfiguration(pDriver, cfgnum);
break;
case USBGenericRequest_GETCONFIGURATION:
TRACE_INFO_WP("gCfg ");
// Send the current configuration number
GetConfiguration(pDriver);
break;
case USBGenericRequest_GETSTATUS:
TRACE_INFO_WP("gSta ");
// Check who is the recipient
switch (USBGenericRequest_GetRecipient(pRequest)) {
case USBGenericRequest_DEVICE:
TRACE_INFO_WP("Dev ");
// Send the device status
GetDeviceStatus(pDriver);
break;
case USBGenericRequest_ENDPOINT:
TRACE_INFO_WP("Ept ");
// Send the endpoint status
eptnum = USBGenericRequest_GetEndpointNumber(pRequest);
GetEndpointStatus(eptnum);
break;
default:
TRACE_WARNING(
"USBDDriver_RequestHandler: Unknown recipient (%d)\n\r",
USBGenericRequest_GetRecipient(pRequest));
USBD_Stall(0);
}
break;
case USBGenericRequest_CLEARFEATURE:
TRACE_INFO_WP("cFeat ");
// Check which is the requested feature
switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {
case USBFeatureRequest_ENDPOINTHALT:
TRACE_INFO_WP("Hlt ");
// Unhalt endpoint and send a zero-length packet
USBD_Unhalt(USBGenericRequest_GetEndpointNumber(pRequest));
USBD_Write(0, 0, 0, 0, 0);
break;
case USBFeatureRequest_DEVICEREMOTEWAKEUP:
TRACE_INFO_WP("RmWU ");
// Disable remote wake-up and send a zero-length packet
pDriver->isRemoteWakeUpEnabled = 0;
USBD_Write(0, 0, 0, 0, 0);
break;
default:
TRACE_WARNING(
"USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r",
USBFeatureRequest_GetFeatureSelector(pRequest));
USBD_Stall(0);
}
break;
case USBGenericRequest_SETFEATURE:
TRACE_INFO_WP("sFeat ");
// Check which is the selected feature
switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {
case USBFeatureRequest_DEVICEREMOTEWAKEUP:
TRACE_INFO_WP("RmWU ");
// Enable remote wake-up and send a ZLP
pDriver->isRemoteWakeUpEnabled = 1;
USBD_Write(0, 0, 0, 0, 0);
break;
case USBFeatureRequest_ENDPOINTHALT:
TRACE_INFO_WP("Halt ");
// Halt endpoint
USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest));
USBD_Write(0, 0, 0, 0, 0);
break;
#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
case USBFeatureRequest_TESTMODE:
// 7.1.20 Test Mode Support
if ((USBGenericRequest_GetType(pRequest) == USBGenericRequest_DEVICE)
&& ((USBGenericRequest_GetIndex(pRequest) & 0x000F) == 0)) {
// Handle test request
USBDDriver_Test(USBFeatureRequest_GetTestSelector(pRequest));
}
else {
USBD_Stall(0);
}
break;
#endif
#if defined(CHIP_USB_OTGHS)
case USBFeatureRequest_OTG_B_HNP_ENABLE:
TRACE_INFO_WP("OTG_B_HNP_ENABLE ");
otg_features_supported |= 1<<USBFeatureRequest_OTG_B_HNP_ENABLE;
USBD_Write(0, 0, 0, 0, 0);
break;
case USBFeatureRequest_OTG_A_HNP_SUPPORT:
TRACE_INFO_WP("OTG_A_HNP_SUPPORT ");
otg_features_supported |= 1<<USBFeatureRequest_OTG_A_HNP_SUPPORT;
USBD_Write(0, 0, 0, 0, 0);
break;
case USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT:
TRACE_INFO_WP("OTG_A_ALT_HNP_SUPPORT ");
otg_features_supported |= 1<<USBFeatureRequest_OTG_A_ALT_HNP_SUPPORT;
USBD_Write(0, 0, 0, 0, 0);
break;
#endif
default:
TRACE_WARNING(
"USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r",
USBFeatureRequest_GetFeatureSelector(pRequest));
USBD_Stall(0);
}
break;
case USBGenericRequest_SETINTERFACE:
TRACE_INFO_WP("sInterface ");
infnum = USBInterfaceRequest_GetInterface(pRequest);
setting = USBInterfaceRequest_GetAlternateSetting(pRequest);
SetInterface(pDriver, infnum, setting);
break;
case USBGenericRequest_GETINTERFACE:
TRACE_INFO_WP("gInterface ");
infnum = USBInterfaceRequest_GetInterface(pRequest);
GetInterface(pDriver, infnum);
break;
default:
TRACE_WARNING(
"USBDDriver_RequestHandler: Unknown request code (%d)\n\r",
USBGenericRequest_GetRequest(pRequest));
USBD_Stall(0);
}
}
//------------------------------------------------------------------------------
/// Test if RemoteWakeUP feature is enabled
/// \param pDriver Pointer to an USBDDriver instance.
/// \return 1 if remote wake up has been enabled by the host; otherwise, returns
/// 0
//------------------------------------------------------------------------------
unsigned char USBDDriver_IsRemoteWakeUpEnabled(const USBDDriver *pDriver)
{
return pDriver->isRemoteWakeUpEnabled;
}
#if defined(CHIP_USB_OTGHS)
//------------------------------------------------------------------------------
/// Return OTG features supported
/// \return the OTG features
//------------------------------------------------------------------------------
unsigned char USBDDriver_returnOTGFeatures(void)
{
return otg_features_supported;
}
//------------------------------------------------------------------------------
/// Clear OTG features supported
/// \return none
//------------------------------------------------------------------------------
void USBDDriver_clearOTGFeatures(void)
{
otg_features_supported = 0;
}
#endif
@@ -0,0 +1,101 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
\unit
!!!Purpose
USB Device Driver class definition.
!!!Usage
-# Instanciate a USBDDriver object and initialize it using
USBDDriver_Initialize.
-# When a USB SETUP request is received, forward it to the standard
driver using USBDDriver_RequestHandler.
-# Check the Remote Wakeup setting via USBDDriver_IsRemoteWakeUpEnabled.
*/
#ifndef USBDDRIVER_H
#define USBDDRIVER_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "USBDDriverDescriptors.h"
#include <usb/common/core/USBGenericRequest.h>
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// USB device driver structure, holding a list of descriptors identifying
/// the device as well as the driver current state.
//------------------------------------------------------------------------------
typedef struct {
/// List of descriptors used by the device.
const USBDDriverDescriptors *pDescriptors;
/// Current setting for each interface.
unsigned char *pInterfaces;
/// Current configuration number (0 -> device is not configured).
unsigned char cfgnum;
/// Indicates if remote wake up has been enabled by the host.
unsigned char isRemoteWakeUpEnabled;
#if defined(CHIP_USB_OTGHS)
/// Features supported by OTG
unsigned char otg_features_supported;
#endif
} USBDDriver;
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void USBDDriver_Initialize(
USBDDriver *pDriver,
const USBDDriverDescriptors *pDescriptors,
unsigned char *pInterfaces);
extern void USBDDriver_RequestHandler(
USBDDriver *pDriver,
const USBGenericRequest *pRequest);
extern unsigned char USBDDriver_IsRemoteWakeUpEnabled(const USBDDriver *pDriver);
#if defined(CHIP_USB_OTGHS)
extern unsigned char USBDDriver_returnOTGFeatures(void);
extern void USBDDriver_clearOTGFeatures(void);
#endif
#endif //#ifndef USBDDRIVER_H
@@ -0,0 +1,86 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
\unit
!!!Purpose
Definition of a class for declaring USB descriptors required by the
device driver.
*/
#ifndef USBDDRIVERDESCRIPTORS_H
#define USBDDRIVERDESCRIPTORS_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <usb/common/core/USBDeviceDescriptor.h>
#include <usb/common/core/USBConfigurationDescriptor.h>
#include <usb/common/core/USBDeviceQualifierDescriptor.h>
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// List of all descriptors used by a USB device driver. Each descriptor can
/// be provided in two versions: full-speed and high-speed. Devices which are
/// not high-speed capable do not need to provided high-speed descriptors and
/// the full-speed qualifier & other speed descriptors.
//------------------------------------------------------------------------------
typedef struct {
/// Pointer to the full-speed device descriptor.
const USBDeviceDescriptor *pFsDevice;
/// Pointer to the full-speed configuration descriptor.
const USBConfigurationDescriptor *pFsConfiguration;
/// Pointer to the full-speed qualifier descriptor.
const USBDeviceQualifierDescriptor *pFsQualifier;
/// Pointer to the full-speed other speed configuration descriptor.
const USBConfigurationDescriptor *pFsOtherSpeed;
/// Pointer to the high-speed device descriptor.
const USBDeviceDescriptor *pHsDevice;
/// Pointer to the high-speed configuration descriptor.
const USBConfigurationDescriptor *pHsConfiguration;
/// Pointer to the high-speed qualifier descriptor.
const USBDeviceQualifierDescriptor *pHsQualifier;
/// Pointer to the high-speed other speed configuration descriptor.
const USBConfigurationDescriptor *pHsOtherSpeed;
/// Pointer to the list of string descriptors.
const unsigned char **pStrings;
/// Number of string descriptors in list.
unsigned char numStrings;
} USBDDriverDescriptors;
#endif //#ifndef USBDDRIVERDESCRIPTORS_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,233 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
/// !Purpose
///
/// Mass Storage class definitions.
///
/// See
/// - <a
/// href="http://www.usb.org/developers/devclass_docs/usb_msc_overview_1.2.pdf">
/// USB Mass Storage Class Spec. Overview</a>
/// - <a href="http://www.usb.org/developers/devclass_docs/usbmassbulk_10.pdf">
/// USB Mass Storage Class Bulk-Only Transport</a>
///
/// !Usage
///
/// -# Uses "MSD Requests" to check incoming requests from USB Host.
/// -# Uses "MSD Subclass Codes" and "MSD Protocol Codes" to fill %device
/// interface descriptors for a MSD %device.
/// -# Handle the incoming Bulk data with "MSD CBW Definitions" and MSCbw
/// structure.
/// -# Prepare the outgoing Bulk data with "MSD CSW Definitions" and MSCsw
/// structure.
//------------------------------------------------------------------------------
#ifndef MSD_H
#define MSD_H
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "MSD Requests"
/// This page lists MSD-specific requests ( Actually for Bulk-only protocol ).
///
/// !Requests
/// - MSD_BULK_ONLY_RESET
/// - MSD_GET_MAX_LUN
/// Reset the mass storage %device and its associated interface.
#define MSD_BULK_ONLY_RESET 0xFF
/// Return the maximum LUN number supported by the %device.
#define MSD_GET_MAX_LUN 0xFE
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "MSD Subclass Codes"
/// This page lists the Subclass Codes for bInterfaceSubClass field.
/// (Table 2.1, USB Mass Storage Class Spec. Overview)
///
/// !SubClasses
/// - MSD_SUBCLASS_RBC
/// - MSD_SUBCLASS_SFF_MCC
/// - MSD_SUBCLASS_QIC
/// - MSD_SUBCLASS_UFI
/// - MSD_SUBCLASS_SFF
/// - MSD_SUBCLASS_SCSI
/// Reduced Block Commands (RBC) T10
#define MSD_SUBCLASS_RBC 0x01
/// C/DVD devices
#define MSD_SUBCLASS_SFF_MCC 0x02
/// Tape device
#define MSD_SUBCLASS_QIC 0x03
/// Floppy disk drive (FDD) device
#define MSD_SUBCLASS_UFI 0x04
/// Floppy disk drive (FDD) device
#define MSD_SUBCLASS_SFF 0x05
/// SCSI transparent command set
#define MSD_SUBCLASS_SCSI 0x06
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "MSD Protocol Codes"
/// This page lists the Transport Protocol codes for MSD.
/// (Table 3.1, USB Mass Storage Class Spec. Overview)
///
/// !Protocols
/// - MSD_PROTOCOL_CBI_COMPLETION
/// - MSD_PROTOCOL_CBI
/// - MSD_PROTOCOL_BULK_ONLY
/// Control/Bulk/Interrupt (CBI) Transport (with command complete interrupt)
#define MSD_PROTOCOL_CBI_COMPLETION 0x00
/// Control/Bulk/Interrupt (CBI) Transport (no command complete interrupt)
#define MSD_PROTOCOL_CBI 0x01
/// Bulk-Only Transport
#define MSD_PROTOCOL_BULK_ONLY 0x50
//------------------------------------------------------------------------------
/// Test unit control:
#define CTRL_NOT_READY 0x00
#define CTRL_GOOD 0x01
#define CTRL_BUSY 0x02
//------------------------------------------------------------------------------
/// \page "MSD CBW Definitions"
/// This page lists the Command Block Wrapper (CBW) definitions.
///
/// !Constants
/// - MSD_CBW_SIZE
/// - MSD_CBW_SIGNATURE
///
/// !Fields
/// - MSD_CBW_DEVICE_TO_HOST
/// Command Block Wrapper Size
#define MSD_CBW_SIZE 31
/// 'USBC' 0x43425355
#define MSD_CBW_SIGNATURE 0x43425355
/// CBW bmCBWFlags field
#define MSD_CBW_DEVICE_TO_HOST (1 << 7)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "MSD CSW Definitions"
/// This page lists the Command Status Wrapper (CSW) definitions.
///
/// !Constants
/// - MSD_CSW_SIZE
/// - MSD_CSW_SIGNATURE
///
/// !Command Block Status Values
/// (Table 5.3 , USB Mass Storage Class Bulk-Only Transport)
/// - MSD_CSW_COMMAND_PASSED
/// - MSD_CSW_COMMAND_FAILED
/// - MSD_CSW_PHASE_ERROR
/// Command Status Wrapper Size
#define MSD_CSW_SIZE 13
/// 'USBS' 0x53425355
#define MSD_CSW_SIGNATURE 0x53425355
/// Command Passed (good status)
#define MSD_CSW_COMMAND_PASSED 0
/// Command Failed
#define MSD_CSW_COMMAND_FAILED 1
/// Phase Error
#define MSD_CSW_PHASE_ERROR 2
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Structures
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Command Block Wrapper (CBW),
/// See Table 5.1, USB Mass Storage Class Bulk-Only Transport.
///
/// The CBW shall start on a packet boundary and shall end as a
/// short packet with exactly 31 (1Fh) bytes transferred.
//------------------------------------------------------------------------------
typedef struct {
/// 'USBC' 0x43425355 (little endian)
unsigned int dCBWSignature;
/// Must be the same as dCSWTag
unsigned int dCBWTag;
/// Number of bytes transfer
unsigned int dCBWDataTransferLength;
/// Indicates the directin of the transfer:
/// 0x80=IN=device-to-host,
/// 0x00=OUT=host-to-device
unsigned char bmCBWFlags;
/// bits 0->3: bCBWLUN
unsigned char bCBWLUN :4,
bReserved1:4; /// reserved
/// bits 0->4: bCBWCBLength
unsigned char bCBWCBLength:5,
bReserved2 :3; /// reserved
/// Command block
unsigned char pCommand[16];
} MSCbw;
//------------------------------------------------------------------------------
/// Command Status Wrapper (CSW),
/// See Table 5.2, USB Mass Storage Class Bulk-Only Transport.
//------------------------------------------------------------------------------
typedef struct
{
/// 'USBS' 0x53425355 (little endian)
unsigned int dCSWSignature;
/// Must be the same as dCBWTag
unsigned int dCSWTag;
/// For Data-Out the device shall report in the dCSWDataResidue the
/// difference between the amount of data expected as stated in the
/// dCBWDataTransferLength, and the actual amount of data processed by
/// the device. For Data-In the device shall report in the dCSWDataResidue
/// the difference between the amount of data expected as stated in the
/// dCBWDataTransferLength and the actual amount of relevant data sent by
/// the device. The dCSWDataResidue shall not exceed the value sent in the
/// dCBWDataTransferLength.
unsigned int dCSWDataResidue;
/// Indicates the success or failure of the command.
unsigned char bCSWStatus;
} MSCsw;
#endif //#ifndef MSD_H
@@ -0,0 +1,609 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "SBCMethods.h"
#include "MSDDStateMachine.h"
//-----------------------------------------------------------------------------
// Internal functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// Returns the expected transfer length and direction (IN, OUT or don't care)
/// from the host point-of-view.
/// \param cbw Pointer to the CBW to examinate
/// \param pLength Expected length of command
/// \param pType Expected direction of command
//-----------------------------------------------------------------------------
static void MSDD_GetCommandInformation(MSCbw *cbw,
unsigned int *length,
unsigned char *type)
{
// Expected host transfer direction and length
(*length) = cbw->dCBWDataTransferLength;
if (*length == 0) {
(*type) = MSDD_NO_TRANSFER;
}
else if ((cbw->bmCBWFlags & MSD_CBW_DEVICE_TO_HOST) != 0) {
(*type) = MSDD_DEVICE_TO_HOST;
}
else {
(*type) = MSDD_HOST_TO_DEVICE;
}
}
//-----------------------------------------------------------------------------
/// Pre-processes a command by checking the differences between the host and
/// device expectations in term of transfer type and length.
/// Once one of the thirteen cases is identified, the actions to do during the
/// post-processing phase are stored in the dCase variable of the command
/// state.
/// \param pMsdDriver Pointer to a MSDDriver instance
/// \return 1 if the command is supported, false otherwise
//-----------------------------------------------------------------------------
static unsigned char MSDD_PreProcessCommand(MSDDriver *pMsdDriver)
{
unsigned int hostLength = 0;
unsigned int deviceLength = 0;
unsigned char hostType;
unsigned char deviceType;
unsigned char isCommandSupported;
MSDCommandState *commandState = &(pMsdDriver->commandState);
MSCsw *csw = &(commandState->csw);
MSCbw *cbw = &(commandState->cbw);
MSDLun *lun = &(pMsdDriver->luns[(unsigned char) cbw->bCBWLUN]);
// Get information about the command
// Host-side
MSDD_GetCommandInformation(cbw, &hostLength, &hostType);
// Device-side
isCommandSupported = SBC_GetCommandInformation(cbw->pCommand,
&deviceLength,
&deviceType,
lun);
// Initialize data residue and result status
csw->dCSWDataResidue = 0;
csw->bCSWStatus = MSD_CSW_COMMAND_PASSED;
// Check if the command is supported
if (isCommandSupported) {
// Identify the command case
if(hostType == MSDD_NO_TRANSFER) {
// Case 1 (Hn = Dn)
if(deviceType == MSDD_NO_TRANSFER) {
//TRACE_WARNING("Case 1\n\r");
commandState->postprocess = 0;
commandState->length = 0;
}
else if(deviceType == MSDD_DEVICE_TO_HOST) {
// Case 2 (Hn < Di)
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 2\n\r");
commandState->postprocess = MSDD_CASE_PHASE_ERROR;
commandState->length = 0;
}
else { //if(deviceType == MSDD_HOST_TO_DEVICE) {
// Case 3 (Hn < Do)
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 3\n\r");
commandState->postprocess = MSDD_CASE_PHASE_ERROR;
commandState->length = 0;
}
}
// Case 4 (Hi > Dn)
else if(hostType == MSDD_DEVICE_TO_HOST) {
if(deviceType == MSDD_NO_TRANSFER) {
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 4\n\r");
commandState->postprocess = MSDD_CASE_STALL_IN;
commandState->length = 0;
csw->dCSWDataResidue = hostLength;
}
else if(deviceType == MSDD_DEVICE_TO_HOST) {
TRACE_ERROR("cmd=0x%0x h=%d d=%d", cbw->pCommand[0], hostLength, deviceLength);
if(hostLength > deviceLength) {
// Case 5 (Hi > Di)
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 5\n\r");
commandState->postprocess = MSDD_CASE_STALL_IN;
commandState->length = deviceLength;
csw->dCSWDataResidue = hostLength - deviceLength;
}
else if(hostLength == deviceLength) {
// Case 6 (Hi = Di)
commandState->postprocess = 0;
commandState->length = deviceLength;
}
else { //if(hostLength < deviceLength) {
// Case 7 (Hi < Di)
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 7\n\r");
commandState->postprocess = MSDD_CASE_PHASE_ERROR;
commandState->length = hostLength;
}
}
else { //if(deviceType == MSDD_HOST_TO_DEVICE) {
// Case 8 (Hi <> Do)
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 8\n\r");
commandState->postprocess =
MSDD_CASE_STALL_IN | MSDD_CASE_PHASE_ERROR;
commandState->length = 0;
}
}
else if(hostType == MSDD_HOST_TO_DEVICE) {
if(deviceType == MSDD_NO_TRANSFER) {
// Case 9 (Ho > Dn)
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 9\n\r");
commandState->postprocess = MSDD_CASE_STALL_OUT;
commandState->length = 0;
csw->dCSWDataResidue = hostLength;
}
else if(deviceType == MSDD_DEVICE_TO_HOST) {
// Case 10 (Ho <> Di)
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 10\n\r");
commandState->postprocess =
MSDD_CASE_STALL_OUT | MSDD_CASE_PHASE_ERROR;
commandState->length = 0;
}
else { //if(deviceType == MSDD_HOST_TO_DEVICE) {
if(hostLength > deviceLength) {
// Case 11 (Ho > Do)
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 11\n\r");
commandState->postprocess = MSDD_CASE_STALL_OUT;
// commandState->length = deviceLength;
// csw->dCSWDataResidue = hostLength - deviceLength;
commandState->length = 0;
csw->dCSWDataResidue = deviceLength;
}
else if(hostLength == deviceLength) {
// Case 12 (Ho = Do)
//TRACE_WARNING(
// "MSDD_PreProcessCommand: Case 12\n\r");
commandState->postprocess = 0;
commandState->length = deviceLength;
}
else { //if(hostLength < deviceLength) {
// Case 13 (Ho < Do)
TRACE_WARNING(
"MSDD_PreProcessCommand: Case 13\n\r");
commandState->postprocess = MSDD_CASE_PHASE_ERROR;
commandState->length = hostLength;
}
}
}
}
return isCommandSupported;
}
//-----------------------------------------------------------------------------
/// Post-processes a command given the case identified during the
/// pre-processing step.
/// Depending on the case, one of the following actions can be done:
/// - Bulk IN endpoint is stalled
/// - Bulk OUT endpoint is stalled
/// - CSW status set to phase error
/// \param pMsdDriver Pointer to a MSDDriver instance
/// \return If the device is halted
//-----------------------------------------------------------------------------
static unsigned char MSDD_PostProcessCommand(MSDDriver *pMsdDriver)
{
MSDCommandState *commandState = &(pMsdDriver->commandState);
MSCsw *csw = &(commandState->csw);
unsigned char haltStatus = 0;
// STALL Bulk IN endpoint ?
if ((commandState->postprocess & MSDD_CASE_STALL_IN) != 0) {
TRACE_INFO_WP("StallIn ");
MSDD_Halt(MSDD_CASE_STALL_IN);
haltStatus = 1;
}
// STALL Bulk OUT endpoint ?
if ((commandState->postprocess & MSDD_CASE_STALL_OUT) != 0) {
TRACE_INFO_WP("StallOut ");
MSDD_Halt(MSDD_CASE_STALL_OUT);
haltStatus = 1;
}
// Set CSW status code to phase error ?
if ((commandState->postprocess & MSDD_CASE_PHASE_ERROR) != 0) {
TRACE_INFO_WP("PhaseErr ");
csw->bCSWStatus = MSD_CSW_PHASE_ERROR;
}
return haltStatus;
}
//-----------------------------------------------------------------------------
/// Processes the latest command received by the %device.
/// \param pMsdDriver Pointer to a MSDDriver instance
/// \return 1 if the command has been completed, false otherwise.
//-----------------------------------------------------------------------------
static unsigned char MSDD_ProcessCommand(MSDDriver * pMsdDriver)
{
unsigned char status;
MSDCommandState *commandState = &(pMsdDriver->commandState);
MSCbw *cbw = &(commandState->cbw);
MSCsw *csw = &(commandState->csw);
MSDLun *lun = &(pMsdDriver->luns[(unsigned char) cbw->bCBWLUN]);
unsigned char isCommandComplete = 0;
// Check if LUN is valid
if (cbw->bCBWLUN > pMsdDriver->maxLun) {
TRACE_WARNING(
"MSDD_ProcessCommand: LUN %d not exist\n\r", cbw->bCBWLUN);
status = MSDD_STATUS_ERROR;
}
else {
// Process command
if (pMsdDriver->maxLun > 0) {
TRACE_INFO_WP("LUN%d ", cbw->bCBWLUN);
}
status = SBC_ProcessCommand(lun, commandState);
}
// Check command result code
if (status == MSDD_STATUS_PARAMETER) {
TRACE_WARNING(
"MSDD_ProcessCommand: Unknown cmd 0x%02X\n\r",
cbw->pCommand[0]);
// Update sense data
SBC_UpdateSenseData(&(lun->requestSenseData),
SBC_SENSE_KEY_ILLEGAL_REQUEST,
SBC_ASC_INVALID_FIELD_IN_CDB,
0);
// Result codes
csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
isCommandComplete = 1;
// stall the request, IN or OUT
if (((cbw->bmCBWFlags & MSD_CBW_DEVICE_TO_HOST) == 0)
&& (cbw->dCBWDataTransferLength > 0)) {
// Stall the OUT endpoint : host to device
// MSDD_Halt(MSDD_CASE_STALL_OUT);
commandState->postprocess = MSDD_CASE_STALL_OUT;
TRACE_INFO_WP("StaOUT ");
}
else {
// Stall the IN endpoint : device to host
// MSDD_Halt(MSDD_CASE_STALL_IN);
commandState->postprocess = MSDD_CASE_STALL_IN;
TRACE_INFO_WP("StaIN ");
}
}
else if (status == MSDD_STATUS_ERROR) {
TRACE_WARNING("MSD_ProcessCommand: Cmd %x fail\n\r",
((SBCCommand*)commandState->cbw.pCommand)->bOperationCode);
// Update sense data
SBC_UpdateSenseData(&(lun->requestSenseData),
SBC_SENSE_KEY_MEDIUM_ERROR,
SBC_ASC_INVALID_FIELD_IN_CDB,
0);
// Result codes
csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
isCommandComplete = 1;
}
else if (status == MSDD_STATUS_RW) {
csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
isCommandComplete = 1;
}
else {
// Update sense data
SBC_UpdateSenseData(&(lun->requestSenseData),
SBC_SENSE_KEY_NO_SENSE,
0,
0);
// Is command complete ?
if (status == MSDD_STATUS_SUCCESS) {
isCommandComplete = 1;
}
}
// Check if command has been completed
if (isCommandComplete) {
TRACE_INFO_WP("Cplt ");
// Adjust data residue
if (commandState->length != 0) {
csw->dCSWDataResidue += commandState->length;
// STALL the endpoint waiting for data
if ((cbw->bmCBWFlags & MSD_CBW_DEVICE_TO_HOST) == 0) {
// Stall the OUT endpoint : host to device
// MSDD_Halt(MSDD_CASE_STALL_OUT);
commandState->postprocess = MSDD_CASE_STALL_OUT;
TRACE_INFO_WP("StaOUT ");
}
else {
// Stall the IN endpoint : device to host
// MSDD_Halt(MSDD_CASE_STALL_IN);
commandState->postprocess = MSDD_CASE_STALL_IN;
TRACE_INFO_WP("StaIN ");
}
}
// Reset command state
commandState->state = 0;
}
return isCommandComplete;
}
//-----------------------------------------------------------------------------
/// State machine for the MSD %device driver
/// \param pMsdDriver Pointer to a MSDDriver instance
//-----------------------------------------------------------------------------
void MSDD_StateMachine(MSDDriver * pMsdDriver)
{
MSDCommandState *commandState = &(pMsdDriver->commandState);
MSCbw *cbw = &(commandState->cbw);
MSCsw *csw = &(commandState->csw);
MSDTransfer *transfer = &(commandState->transfer);
unsigned char status;
// Identify current driver state
switch (pMsdDriver->state) {
//----------------------
case MSDD_STATE_READ_CBW:
//----------------------
// Start the CBW read operation
transfer->semaphore = 0;
status = MSDD_Read(cbw,
MSD_CBW_SIZE,
(TransferCallback) MSDDriver_Callback,
(void *) transfer);
// Check operation result code
if (status == USBD_STATUS_SUCCESS) {
// If the command was successful, wait for transfer
pMsdDriver->state = MSDD_STATE_WAIT_CBW;
}
break;
//----------------------
case MSDD_STATE_WAIT_CBW:
//----------------------
// Check transfer semaphore
if (transfer->semaphore > 0) {
// Take semaphore and terminate transfer
transfer->semaphore--;
// Check if transfer was successful
if (transfer->status == USBD_STATUS_SUCCESS) {
TRACE_INFO_WP("------------------------------\n\r");
// Process received command
pMsdDriver->state = MSDD_STATE_PROCESS_CBW;
}
else if (transfer->status == USBD_STATUS_RESET) {
TRACE_INFO("MSDD_StateMachine: EP resetted\n\r");
pMsdDriver->state = MSDD_STATE_READ_CBW;
}
else {
TRACE_WARNING(
"MSDD_StateMachine: Failed to read CBW\n\r");
pMsdDriver->state = MSDD_STATE_READ_CBW;
}
}
break;
//-------------------------
case MSDD_STATE_PROCESS_CBW:
//-------------------------
// Check if this is a new command
if (commandState->state == 0) {
// Copy the CBW tag
csw->dCSWTag = cbw->dCBWTag;
// Check that the CBW is 31 bytes long
if ((transfer->transferred != MSD_CBW_SIZE) ||
(transfer->remaining != 0)) {
TRACE_WARNING(
"MSDD_StateMachine: Invalid CBW (len %d)\n\r",
(int)transfer->transferred);
// Wait for a reset recovery
pMsdDriver->waitResetRecovery = 1;
// Halt the Bulk-IN and Bulk-OUT pipes
MSDD_Halt(MSDD_CASE_STALL_OUT | MSDD_CASE_STALL_IN);
csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
pMsdDriver->state = MSDD_STATE_READ_CBW;
}
// Check the CBW Signature
else if (cbw->dCBWSignature != MSD_CBW_SIGNATURE) {
TRACE_WARNING(
"MSD_BOTStateMachine: Invalid CBW (Bad signature)\n\r");
// Wait for a reset recovery
pMsdDriver->waitResetRecovery = 1;
// Halt the Bulk-IN and Bulk-OUT pipes
MSDD_Halt(MSDD_CASE_STALL_OUT | MSDD_CASE_STALL_IN);
csw->bCSWStatus = MSD_CSW_COMMAND_FAILED;
pMsdDriver->state = MSDD_STATE_READ_CBW;
}
else {
// Pre-process command
MSDD_PreProcessCommand(pMsdDriver);
}
}
// Process command
if (csw->bCSWStatus == MSDD_STATUS_SUCCESS) {
if (MSDD_ProcessCommand(pMsdDriver)) {
// Post-process command if it is finished
if (MSDD_PostProcessCommand(pMsdDriver)) {
TRACE_INFO_WP("WaitHALT ");
pMsdDriver->state = MSDD_STATE_WAIT_HALT;
}
else {
pMsdDriver->state = MSDD_STATE_SEND_CSW;
}
}
TRACE_INFO_WP("\n\r");
}
break;
//----------------------
case MSDD_STATE_SEND_CSW:
//----------------------
// Set signature
csw->dCSWSignature = MSD_CSW_SIGNATURE;
// Start the CSW write operation
status = MSDD_Write(csw,
MSD_CSW_SIZE,
(TransferCallback) MSDDriver_Callback,
(void *) transfer);
// Check operation result code
if (status == USBD_STATUS_SUCCESS) {
TRACE_INFO_WP("SendCSW ");
// Wait for end of transfer
pMsdDriver->state = MSDD_STATE_WAIT_CSW;
}
break;
//----------------------
case MSDD_STATE_WAIT_CSW:
//----------------------
// Check transfer semaphore
if (transfer->semaphore > 0) {
// Take semaphore and terminate transfer
transfer->semaphore--;
// Check if transfer was successful
if (transfer->status == USBD_STATUS_RESET) {
TRACE_INFO("MSDD_StateMachine: EP resetted\n\r");
}
else if (transfer->status == USBD_STATUS_ABORTED) {
TRACE_WARNING(
"MSDD_StateMachine: Failed to send CSW\n\r");
}
else {
TRACE_INFO_WP("ok");
}
// Read new CBW
pMsdDriver->state = MSDD_STATE_READ_CBW;
}
break;
//----------------------
case MSDD_STATE_WAIT_HALT:
//----------------------
if (MSDD_IsHalted() == 0) {
pMsdDriver->state = MSDD_STATE_SEND_CSW;
}
break;
}
}
@@ -0,0 +1,264 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//-----------------------------------------------------------------------------
/// \unit
/// !Purpose
///
/// Definitions, structs, functions required by a Mass Storage device driver
/// state machine..
///
/// !Usage
///
/// - For a USB device:
/// -# MSDD_Write, MSDD_Read, MSDD_Halt should be defined for
/// usage in the state machine procedure.
///
/// -# MSDD_StateMachine is invoked to run the MSD state machine.
///
//-----------------------------------------------------------------------------
#ifndef MSDDSTATEMACHINE_H
#define MSDDSTATEMACHINE_H
//-----------------------------------------------------------------------------
// Headers
//-----------------------------------------------------------------------------
#include "MSD.h"
#include "MSDLun.h"
#include "debug.h"
//-----------------------------------------------------------------------------
// Definitions
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "MSD Driver Possible states"
/// ...
///
/// !States
/// - MSDD_STATE_READ_CBW
/// - MSDD_STATE_WAIT_CBW
/// - MSDD_STATE_PROCESS_CBW
/// - MSDD_STATE_WAIT_HALT
/// - MSDD_STATE_SEND_CSW
/// - MSDD_STATE_WAIT_CSW
/// - MSDD_STATE_WAIT_RESET
//! \brief Driver is expecting a command block wrapper
#define MSDD_STATE_READ_CBW (1 << 0)
//! \brief Driver is waiting for the transfer to finish
#define MSDD_STATE_WAIT_CBW (1 << 1)
//! \brief Driver is processing the received command
#define MSDD_STATE_PROCESS_CBW (1 << 2)
//! \brief Driver is halted because pipe halt or wait reset
#define MSDD_STATE_WAIT_HALT (1 << 3)
//! \brief Driver is starting the transmission of a command status wrapper
#define MSDD_STATE_SEND_CSW (1 << 4)
//! \brief Driver is waiting for the CSW transmission to finish
#define MSDD_STATE_WAIT_CSW (1 << 5)
//! \brief Driver is waiting for the MassStorageReset
#define MSDD_STATE_WAIT_RESET (1 << 6)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "MSD Driver Result Codes"
/// This page lists result codes for MSD functions.
///
/// !Codes
/// - MSDD_STATUS_SUCCESS
/// - MSDD_STATUS_ERROR
/// - MSDD_STATUS_INCOMPLETE
/// - MSDD_STATUS_PARAMETER
/// - MSDD_STATUS_RW
//! \brief Method was successful
#define MSDD_STATUS_SUCCESS 0x00
//! \brief There was an error when trying to perform a method
#define MSDD_STATUS_ERROR 0x01
//! \brief No error was encountered but the application should call the
//! method again to continue the operation
#define MSDD_STATUS_INCOMPLETE 0x02
//! \brief A wrong parameter has been passed to the method
#define MSDD_STATUS_PARAMETER 0x03
//! \brief An error when reading/writing disk (protected or not present)
#define MSDD_STATUS_RW 0x04
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "MSD Driver Action Cases"
/// This page lists actions to perform during the post-processing phase of a
/// command.
///
/// !Actions
/// - MSDD_CASE_PHASE_ERROR
/// - MSDD_CASE_STALL_IN
/// - MSDD_CASE_STALL_OUT
//! \brief Indicates that the CSW should report a phase error
#define MSDD_CASE_PHASE_ERROR (1 << 0)
//! \brief The driver should halt the Bulk IN pipe after the transfer
#define MSDD_CASE_STALL_IN (1 << 1)
//! \brief The driver should halt the Bulk OUT pipe after the transfer
#define MSDD_CASE_STALL_OUT (1 << 2)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "MSD Driver Xfr Directions"
/// This page lists possible direction values for a data transfer
///
/// !Directions
/// - MSDD_DEVICE_TO_HOST
/// - MSDD_HOST_TO_DEVICE
/// - MSDD_NO_TRANSFER
#define MSDD_DEVICE_TO_HOST 0
#define MSDD_HOST_TO_DEVICE 1
#define MSDD_NO_TRANSFER 2
//------------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Types
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \brief Structure for holding the result of a USB transfer
//! \see MSDDriver_Callback
//------------------------------------------------------------------------------
typedef struct {
volatile unsigned int transferred; /// Number of bytes transferred
volatile unsigned int remaining; /// Number of bytes not transferred
volatile unsigned short semaphore; /// Semaphore to indicate transfer completion
volatile unsigned short status; /// Operation result code
} MSDTransfer;
//------------------------------------------------------------------------------
//! \brief Status of an executing command
//! \see MSDCbw
//! \see MSDCsw
//! \see MSDTransfer
//------------------------------------------------------------------------------
typedef struct {
MSDTransfer transfer; /// Current transfer status (USB)
MSDTransfer disktransfer;/// Current transfer status (Disk)
unsigned int length; /// Remaining length of command
MSCbw cbw; /// Received CBW (31 bytes)
unsigned char state; /// Current command state
MSCsw csw; /// CSW to send (13 bytes)
unsigned char postprocess; /// Actions to perform when command is complete
} MSDCommandState;
//------------------------------------------------------------------------------
/// \brief MSD driver state variables
/// \see MSDCommandState
/// \see MSDLun
//------------------------------------------------------------------------------
typedef struct {
/// LUN list for the %device.
MSDLun *luns;
/// State of the currently executing command
MSDCommandState commandState;
/// Maximum LUN index
unsigned char maxLun;
/// Current state of the driver
unsigned char state;
/// Indicates if the driver is waiting for a reset recovery
unsigned char waitResetRecovery;
} MSDDriver;
//-----------------------------------------------------------------------------
// Inline functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// This function is to be used as a callback for USB or LUN transfers.
/// \param transfer Pointer to the transfer structure to update
/// \param status Operation result code
/// \param transferred Number of bytes transferred by the command
/// \param remaining Number of bytes not transferred
//-----------------------------------------------------------------------------
static inline void MSDDriver_Callback(MSDTransfer *transfer,
unsigned char status,
unsigned int transferred,
unsigned int remaining)
{
TRACE_DEBUG("Cbk ");
transfer->semaphore++;
transfer->status = status;
transfer->transferred = transferred;
transfer->remaining = remaining;
}
//-----------------------------------------------------------------------------
// Driver functions
//-----------------------------------------------------------------------------
//- MSD General support function
extern char MSDD_Read(
void* pData,
unsigned int dLength,
TransferCallback fCallback,
void* pArgument);
extern char MSDD_Write(
void* pData,
unsigned int dLength,
TransferCallback fCallback,
void* pArgument);
extern void MSDD_Halt(unsigned int stallCase);
extern unsigned int MSDD_IsHalted(void);
//-----------------------------------------------------------------------------
// Exported functions
//-----------------------------------------------------------------------------
extern void MSDD_StateMachine(MSDDriver * pMsdDriver);
#endif // #define MSDDSTATEMACHINE_H
@@ -0,0 +1,341 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#include <Media.h>
#include "MSDDriver.h"
#include "MSDDriverDescriptors.h"
#include "SBCMethods.h"
#include "debug.h"
#include <usb/common/core/USBGenericRequest.h>
#include <usb/common/core/USBFeatureRequest.h>
#include <usb/device/core/USBD.h>
#include <usb/device/core/USBDDriver.h>
//-----------------------------------------------------------------------------
// Internal variables
//-----------------------------------------------------------------------------
/// Mass storage device driver instance.
static MSDDriver msdDriver;
/// Standard device driver instance.
static USBDDriver usbdDriver;
//-----------------------------------------------------------------------------
// Internal functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// Resets the state of the MSD driver
//-----------------------------------------------------------------------------
static void MSDDriver_Reset(void)
{
TRACE_INFO_WP("MSDReset ");
msdDriver.state = MSDD_STATE_READ_CBW;
msdDriver.waitResetRecovery = 0;
msdDriver.commandState.state = 0;
}
//-----------------------------------------------------------------------------
// Callback re-implementation
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// Invoked when a new SETUP request is received from the host. Forwards the
/// request to the Mass Storage device driver handler function.
/// \param request Pointer to a USBGenericRequest instance.
//-----------------------------------------------------------------------------
void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
{
MSDDriver_RequestHandler(request);
}
//-----------------------------------------------------------------------------
/// Invoked when the configuration of the device changes. Resets the mass
/// storage driver.
/// \param cfgnum New configuration number.
//-----------------------------------------------------------------------------
void USBDDriverCallbacks_ConfigurationChanged(unsigned char cfgnum)
{
if (cfgnum > 0) {
MSDDriver_Reset();
}
}
//-----------------------------------------------------------------------------
// Driver functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// Reads from host through MSD defined bulk OUT pipe. Act as USBD_Read but by
/// a fixed OUT endpoint.
/// \param data Pointer to the data buffer that contains data read from host.
/// \param size The number of bytes should be read (buffer size).
/// \param callback Pointer to the function invoked on end of reading.
/// \param argument Pointer to additional argument data struct.
//-----------------------------------------------------------------------------
char MSDD_Read(void *data,
unsigned int size,
TransferCallback callback,
void *argument)
{
return USBD_Read(MSDDriverDescriptors_BULKOUT,
data,
size,
callback,
argument);
}
//-----------------------------------------------------------------------------
/// Writes to host through MSD defined bulk IN pipe. Act as USBD_Write but by
/// a fixed IN endpoint.
/// \param data Pointer to the data that writes to the host.
/// \param size The number of bytes should be write.
/// \param callback Pointer to the function invoked on end of writing.
/// \param argument Pointer to additional argument data struct.
//-----------------------------------------------------------------------------
char MSDD_Write(void *data,
unsigned int size,
TransferCallback callback,
void *argument)
{
return USBD_Write(MSDDriverDescriptors_BULKIN,
data,
size,
callback,
argument);
}
//-----------------------------------------------------------------------------
/// HALT Specified USB pipe.
/// \param stallCASE Case of the stall condition (Bulk In/Out/Both).
//-----------------------------------------------------------------------------
void MSDD_Halt(unsigned int stallCASE)
{
if (stallCASE & MSDD_CASE_STALL_OUT) {
USBD_Halt(MSDDriverDescriptors_BULKOUT);
}
if (stallCASE & MSDD_CASE_STALL_IN) {
USBD_Halt(MSDDriverDescriptors_BULKIN);
}
}
//-----------------------------------------------------------------------------
/// Return halted status
/// \return stallCASE bitmap, case of the stall condition
/// (bit: MSDD_CASE_STALL_OUT or MSDD_CASE_STALL_IN)
//-----------------------------------------------------------------------------
unsigned int MSDD_IsHalted(void)
{
unsigned int stallCASE = 0;
if (USBD_IsHalted(MSDDriverDescriptors_BULKOUT)) {
stallCASE |= MSDD_CASE_STALL_OUT;
}
if (USBD_IsHalted(MSDDriverDescriptors_BULKIN)) {
stallCASE |= MSDD_CASE_STALL_IN;
}
return stallCASE;
}
//-----------------------------------------------------------------------------
// Exported functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// Initializes the MSD driver and the associated USB driver.
/// \param luns Pointer to a list of LUNs
/// \param numLuns Number of LUN in list
/// \see MSDLun
//-----------------------------------------------------------------------------
void MSDDriver_Initialize(MSDLun *defLuns, unsigned char numLuns)
{
TRACE_INFO("MSD init\n\r");
// Command state initialization
msdDriver.commandState.state = 0;
msdDriver.commandState.postprocess = 0;
msdDriver.commandState.length = 0;
msdDriver.commandState.transfer.semaphore = 0;
// LUNs
msdDriver.luns = defLuns;
msdDriver.maxLun = (unsigned char) (numLuns - 1);
// Reset BOT driver
MSDDriver_Reset();
// Init the USB driver
USBDDriver_Initialize(&usbdDriver, &msdDriverDescriptors, 0);
USBD_Init();
}
//-----------------------------------------------------------------------------
/// Handler for incoming SETUP requests on default Control endpoint 0.
///
/// Standard requests are forwarded to the USBDDriver_RequestHandler
/// method.
/// \param request Pointer to a USBGenericRequest instance
//-----------------------------------------------------------------------------
void MSDDriver_RequestHandler(const USBGenericRequest *request)
{
TRACE_INFO_WP("NewReq ");
// Handle requests
switch (USBGenericRequest_GetRequest(request)) {
//---------------------
case USBGenericRequest_CLEARFEATURE:
//---------------------
TRACE_INFO_WP("ClrFeat ");
switch (USBFeatureRequest_GetFeatureSelector(request)) {
//---------------------
case USBFeatureRequest_ENDPOINTHALT:
//---------------------
TRACE_INFO_WP("Hlt ");
// Do not clear the endpoint halt status if the device is waiting
// for a reset recovery sequence
if (!msdDriver.waitResetRecovery) {
// Forward the request to the standard handler
USBDDriver_RequestHandler(&usbdDriver, request);
}
else {
TRACE_INFO_WP("No ");
}
USBD_Write(0, 0, 0, 0, 0);
break;
//------
default:
//------
// Forward the request to the standard handler
USBDDriver_RequestHandler(&usbdDriver, request);
}
break;
//-------------------
case MSD_GET_MAX_LUN:
//-------------------
TRACE_INFO_WP("gMaxLun ");
// Check request parameters
if ((request->wValue == 0)
&& (request->wIndex == 0)
&& (request->wLength == 1)) {
USBD_Write(0, &(msdDriver.maxLun), 1, 0, 0);
}
else {
TRACE_WARNING(
"MSDDriver_RequestHandler: GetMaxLUN(%d,%d,%d)\n\r",
request->wValue, request->wIndex, request->wLength);
USBD_Stall(0);
}
break;
//-----------------------
case MSD_BULK_ONLY_RESET:
//-----------------------
TRACE_INFO_WP("Rst ");
// Check parameters
if ((request->wValue == 0)
&& (request->wIndex == 0)
&& (request->wLength == 0)) {
// Reset the MSD driver
MSDDriver_Reset();
USBD_Write(0, 0, 0, 0, 0);
}
else {
TRACE_WARNING(
"MSDDriver_RequestHandler: Reset(%d,%d,%d)\n\r",
request->wValue, request->wIndex, request->wLength);
USBD_Stall(0);
}
break;
//------
default:
//------
// Forward request to standard handler
USBDDriver_RequestHandler(&usbdDriver, request);
break;
}
}
//-----------------------------------------------------------------------------
/// State machine for the MSD driver
//-----------------------------------------------------------------------------
void MSDDriver_StateMachine(void)
{
if (USBD_GetState() < USBD_STATE_CONFIGURED){}
else MSDD_StateMachine(&msdDriver);
}
//-----------------------------------------------------------------------------
/// Starts a remote wake-up sequence if the host has explicitely enabled it
/// by sending the appropriate SET_FEATURE request.
//-----------------------------------------------------------------------------
void MSDDriver_RemoteWakeUp(void)
{
// Remote wake-up has been enabled
if (USBDDriver_IsRemoteWakeUpEnabled(&usbdDriver)) {
USBD_RemoteWakeUp();
}
// Remote wake-up NOT enabled
else {
TRACE_WARNING(
"MSD..RemoteWakeUp: Host has not enabled remote wake-up\n\r");
}
}
@@ -0,0 +1,75 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
/// !Purpose
///
/// Mass storage %device driver implementation.
///
/// !Usage
///
/// -# Enable and setup USB related pins (see pio & board.h).
/// -# Configure the memory interfaces used for Mass Storage LUNs
/// (see memories, MSDLun.h).
/// -# Configure the USB MSD %driver using MSDDriver_Initialize.
/// -# Invoke MSDDriver_StateMachine in main loop to handle all Mass Storage
/// operations.
//------------------------------------------------------------------------------
#ifndef MSDDRIVER_H
#define MSDDRIVER_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "MSD.h"
#include "MSDLun.h"
// #include <utility/trace.h>
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void MSDDriver_Initialize(MSDLun *luns, unsigned char numLuns);
extern void MSDDriver_RequestHandler(const USBGenericRequest *request);
extern void MSDDriver_StateMachine(void);
extern void MSDDriver_RemoteWakeUp(void);
extern void MSDDriver_DataCallback(unsigned char isRead,
unsigned int dataLength,
unsigned int nullCnt,
unsigned int fullCnt);
#endif // #ifndef MSDDRIVER_H
@@ -0,0 +1,468 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "MSDDriverDescriptors.h"
#include <board.h>
#include <usb/common/core/USBGenericDescriptor.h>
#include <usb/common/core/USBDeviceDescriptor.h>
#include <usb/common/core/USBConfigurationDescriptor.h>
#include <usb/common/core/USBInterfaceDescriptor.h>
#include <usb/common/core/USBEndpointDescriptor.h>
#include <usb/common/core/USBStringDescriptor.h>
#include <usb/common/massstorage/MSDeviceDescriptor.h>
#include <usb/common/massstorage/MSInterfaceDescriptor.h>
//------------------------------------------------------------------------------
// Internal definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "MSD Device Descriptor IDs"
/// ...
/// !IDs
/// - MSDDriverDescriptors_VENDORID
/// - MSDDriverDescriptors_PRODUCTID
/// - MSDDriverDescriptors_RELEASE
/// Vendor ID for the Mass Storage device driver.
#define MSDDriverDescriptors_VENDORID 0x03EB
/// Product ID for the Mass Storage device driver.
#define MSDDriverDescriptors_PRODUCTID 0x6129
/// Device release number for the Mass Storage device driver.
#define MSDDriverDescriptors_RELEASE 0x0100
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Macros
//------------------------------------------------------------------------------
/// Returns the minimum between two values.
#define MIN(a, b) ((a < b) ? a : b)
//------------------------------------------------------------------------------
// Internal types
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// List of configuration descriptors used by a Mass Storage device driver.
//------------------------------------------------------------------------------
typedef struct {
/// Standard configuration descriptor.
USBConfigurationDescriptor configuration;
#if defined(CHIP_USB_OTGHS)
// OTG descriptor
USBOtgDescriptor otgDescriptor;
#endif
/// Mass storage interface descriptor.
USBInterfaceDescriptor interface;
/// Bulk-out endpoint descriptor.
USBEndpointDescriptor bulkOut;
/// Bulk-in endpoint descriptor.
USBEndpointDescriptor bulkIn;
} __attribute__ ((packed)) MSDConfigurationDescriptors;
//------------------------------------------------------------------------------
// Local variables
//------------------------------------------------------------------------------
/// Mass storage driver device descriptor.
static const USBDeviceDescriptor deviceDescriptor = {
sizeof(USBDeviceDescriptor),
USBGenericDescriptor_DEVICE,
USBDeviceDescriptor_USB2_00,
MSDeviceDescriptor_CLASS,
MSDeviceDescriptor_SUBCLASS,
MSDeviceDescriptor_PROTOCOL,
CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
MSDDriverDescriptors_VENDORID,
MSDDriverDescriptors_PRODUCTID,
MSDDriverDescriptors_RELEASE,
1, // Manufacturer string descriptor index.
2, // Product string descriptor index.
3, // Serial number string descriptor index.
1 // Device has one possible configuration.
};
#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
/// Device qualifier descriptor.
static const USBDeviceQualifierDescriptor qualifierDescriptor = {
sizeof(USBDeviceQualifierDescriptor),
USBGenericDescriptor_DEVICEQUALIFIER,
USBDeviceDescriptor_USB2_00,
MSDeviceDescriptor_CLASS,
MSDeviceDescriptor_SUBCLASS,
MSDeviceDescriptor_PROTOCOL,
CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0),
1, // Device has one possible configuration.
0x00
};
#endif
/// Full-speed configuration descriptor.
static const MSDConfigurationDescriptors configurationDescriptorsFS = {
// Standard configuration descriptor.
{
sizeof(USBConfigurationDescriptor),
USBGenericDescriptor_CONFIGURATION,
sizeof(MSDConfigurationDescriptors),
1, // Configuration has one interface.
1, // This is configuration #1.
0, // No string descriptor for configuration.
BOARD_USB_BMATTRIBUTES,
USBConfigurationDescriptor_POWER(100)
},
#if defined(CHIP_USB_OTGHS)
// OTG descriptor
{
sizeof(USBOtgDescriptor),
USBGenericDescriptor_OTG,
USBOTGDescriptor_HNP_SRP
},
#endif
// Mass Storage interface descriptor.
{
sizeof(USBInterfaceDescriptor),
USBGenericDescriptor_INTERFACE,
0, // This is interface #0.
0, // This is alternate setting #0.
2, // Interface uses two endpoints.
MSInterfaceDescriptor_CLASS,
MSInterfaceDescriptor_SCSI,
MSInterfaceDescriptor_BULKONLY,
0 // No string descriptor for interface.
},
// Bulk-OUT endpoint descriptor
{
sizeof(USBEndpointDescriptor),
USBGenericDescriptor_ENDPOINT,
USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_OUT,
MSDDriverDescriptors_BULKOUT),
USBEndpointDescriptor_BULK,
MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDDriverDescriptors_BULKOUT),
USBEndpointDescriptor_MAXBULKSIZE_FS),
0 // Must be 0 for full-speed Bulk endpoints.
},
// Bulk-IN endpoint descriptor
{
sizeof(USBEndpointDescriptor),
USBGenericDescriptor_ENDPOINT,
USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_IN,
MSDDriverDescriptors_BULKIN),
USBEndpointDescriptor_BULK,
MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDDriverDescriptors_BULKIN),
USBEndpointDescriptor_MAXBULKSIZE_FS),
0 // Must be 0 for full-speed Bulk endpoints.
}
};
#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
/// Full-speed other speed configuration descriptor.
static const MSDConfigurationDescriptors otherSpeedDescriptorsFS = {
// Standard configuration descriptor.
{
sizeof(USBConfigurationDescriptor),
USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
sizeof(MSDConfigurationDescriptors),
1, // Configuration has one interface.
1, // This is configuration #1.
0, // No string descriptor for configuration.
BOARD_USB_BMATTRIBUTES,
USBConfigurationDescriptor_POWER(100)
},
#if defined(CHIP_USB_OTGHS)
// OTG descriptor
{
sizeof(USBOtgDescriptor),
USBGenericDescriptor_OTG,
USBOTGDescriptor_HNP_SRP
},
#endif
// Mass Storage interface descriptor.
{
sizeof(USBInterfaceDescriptor),
USBGenericDescriptor_INTERFACE,
0, // This is interface #0.
0, // This is alternate setting #0.
2, // Interface uses two endpoints.
MSInterfaceDescriptor_CLASS,
MSInterfaceDescriptor_SCSI,
MSInterfaceDescriptor_BULKONLY,
0 // No string descriptor for interface.
},
// Bulk-OUT endpoint descriptor
{
sizeof(USBEndpointDescriptor),
USBGenericDescriptor_ENDPOINT,
USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_OUT,
MSDDriverDescriptors_BULKOUT),
USBEndpointDescriptor_BULK,
MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDDriverDescriptors_BULKOUT),
USBEndpointDescriptor_MAXBULKSIZE_HS),
0 // No string descriptor for endpoint.
},
// Bulk-IN endpoint descriptor
{
sizeof(USBEndpointDescriptor),
USBGenericDescriptor_ENDPOINT,
USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_IN,
MSDDriverDescriptors_BULKIN),
USBEndpointDescriptor_BULK,
MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDDriverDescriptors_BULKIN),
USBEndpointDescriptor_MAXBULKSIZE_HS),
0 // No string descriptor for endpoint.
}
};
/// High-speed configuration descriptor.
static const MSDConfigurationDescriptors configurationDescriptorsHS = {
// Standard configuration descriptor.
{
sizeof(USBConfigurationDescriptor),
USBGenericDescriptor_CONFIGURATION,
sizeof(MSDConfigurationDescriptors),
1, // Configuration has one interface.
1, // This is configuration #1.
0, // No string descriptor for configuration.
BOARD_USB_BMATTRIBUTES,
USBConfigurationDescriptor_POWER(100)
},
#if defined(CHIP_USB_OTGHS)
// OTG descriptor
{
sizeof(USBOtgDescriptor),
USBGenericDescriptor_OTG,
USBOTGDescriptor_HNP_SRP
},
#endif
// Mass Storage interface descriptor.
{
sizeof(USBInterfaceDescriptor),
USBGenericDescriptor_INTERFACE,
0, // This is interface #0.
0, // This is alternate setting #0.
2, // Interface uses two endpoints.
MSInterfaceDescriptor_CLASS,
MSInterfaceDescriptor_SCSI,
MSInterfaceDescriptor_BULKONLY,
0 // No string descriptor for interface.
},
// Bulk-OUT endpoint descriptor
{
sizeof(USBEndpointDescriptor),
USBGenericDescriptor_ENDPOINT,
USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_OUT,
MSDDriverDescriptors_BULKOUT),
USBEndpointDescriptor_BULK,
MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDDriverDescriptors_BULKOUT),
USBEndpointDescriptor_MAXBULKSIZE_HS),
0 // No string descriptor for endpoint.
},
// Bulk-IN endpoint descriptor
{
sizeof(USBEndpointDescriptor),
USBGenericDescriptor_ENDPOINT,
USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_IN,
MSDDriverDescriptors_BULKIN),
USBEndpointDescriptor_BULK,
MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDDriverDescriptors_BULKIN),
USBEndpointDescriptor_MAXBULKSIZE_HS),
0 // No string descriptor for endpoint.
}
};
/// High-speed other speed configuration descriptor.
static const MSDConfigurationDescriptors otherSpeedDescriptorsHS = {
// Standard configuration descriptor.
{
sizeof(USBConfigurationDescriptor),
USBGenericDescriptor_OTHERSPEEDCONFIGURATION,
sizeof(MSDConfigurationDescriptors),
1, // Configuration has one interface.
1, // This is configuration #1.
0, // No string descriptor for configuration.
BOARD_USB_BMATTRIBUTES,
USBConfigurationDescriptor_POWER(100)
},
#if defined(CHIP_USB_OTGHS)
// OTG descriptor
{
sizeof(USBOtgDescriptor),
USBGenericDescriptor_OTG,
USBOTGDescriptor_HNP_SRP
},
#endif
// Mass Storage interface descriptor.
{
sizeof(USBInterfaceDescriptor),
USBGenericDescriptor_INTERFACE,
0, // This is interface #0.
0, // This is alternate setting #0.
2, // Interface uses two endpoints.
MSInterfaceDescriptor_CLASS,
MSInterfaceDescriptor_SCSI,
MSInterfaceDescriptor_BULKONLY,
0 // No string descriptor for interface.
},
// Bulk-OUT endpoint descriptor
{
sizeof(USBEndpointDescriptor),
USBGenericDescriptor_ENDPOINT,
USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_OUT,
MSDDriverDescriptors_BULKOUT),
USBEndpointDescriptor_BULK,
MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDDriverDescriptors_BULKOUT),
USBEndpointDescriptor_MAXBULKSIZE_FS),
0 // No string descriptor for endpoint.
},
// Bulk-IN endpoint descriptor
{
sizeof(USBEndpointDescriptor),
USBGenericDescriptor_ENDPOINT,
USBEndpointDescriptor_ADDRESS(
USBEndpointDescriptor_IN,
MSDDriverDescriptors_BULKIN),
USBEndpointDescriptor_BULK,
MIN(CHIP_USB_ENDPOINTS_MAXPACKETSIZE(MSDDriverDescriptors_BULKIN),
USBEndpointDescriptor_MAXBULKSIZE_FS),
0 // No string descriptor for endpoint.
}
};
#endif
/// Language ID string descriptor.
static const unsigned char languageIdDescriptor[] = {
USBStringDescriptor_LENGTH(1),
USBGenericDescriptor_STRING,
USBStringDescriptor_ENGLISH_US
};
/// Manufacturer string descriptor.
static const unsigned char manufacturerDescriptor[] = {
USBStringDescriptor_LENGTH(7),
USBGenericDescriptor_STRING,
USBStringDescriptor_UNICODE('9'),
USBStringDescriptor_UNICODE('X'),
USBStringDescriptor_UNICODE(' '),
USBStringDescriptor_UNICODE('T'),
USBStringDescriptor_UNICODE('E'),
USBStringDescriptor_UNICODE('A'),
USBStringDescriptor_UNICODE('M'),
};
/// Product string descriptor.
static const unsigned char productDescriptor[] = {
USBStringDescriptor_LENGTH(5),
USBGenericDescriptor_STRING,
USBStringDescriptor_UNICODE('S'),
USBStringDescriptor_UNICODE('K'),
USBStringDescriptor_UNICODE('Y'),
USBStringDescriptor_UNICODE('9'),
USBStringDescriptor_UNICODE('X'),
};
/// Serial number string descriptor. The serial number must be at least 12
/// characters long and made up of only letters & numbers to be compliant with
/// the MSD specification.
static const unsigned char serialNumberDescriptor[] = {
USBStringDescriptor_LENGTH(12),
USBGenericDescriptor_STRING,
USBStringDescriptor_UNICODE('0'),
USBStringDescriptor_UNICODE('1'),
USBStringDescriptor_UNICODE('2'),
USBStringDescriptor_UNICODE('3'),
USBStringDescriptor_UNICODE('4'),
USBStringDescriptor_UNICODE('5'),
USBStringDescriptor_UNICODE('6'),
USBStringDescriptor_UNICODE('7'),
USBStringDescriptor_UNICODE('8'),
USBStringDescriptor_UNICODE('9'),
USBStringDescriptor_UNICODE('A'),
USBStringDescriptor_UNICODE('B')
};
/// List of all string descriptors used.
static const unsigned char *stringDescriptors[] = {
languageIdDescriptor,
manufacturerDescriptor,
productDescriptor,
serialNumberDescriptor
};
//------------------------------------------------------------------------------
// Global variables
//------------------------------------------------------------------------------
/// List of the standard descriptors used by the Mass Storage driver.
const USBDDriverDescriptors msdDriverDescriptors = {
&deviceDescriptor,
(USBConfigurationDescriptor *) &configurationDescriptorsFS,
#if defined(CHIP_USB_UDPHS) || defined(CHIP_USB_OTGHS)
&qualifierDescriptor,
(USBConfigurationDescriptor *) &otherSpeedDescriptorsFS,
&deviceDescriptor,
(USBConfigurationDescriptor *) &configurationDescriptorsHS,
&qualifierDescriptor,
(USBConfigurationDescriptor *) &otherSpeedDescriptorsHS,
#else
0, // No full-speed device qualifier descriptor
0, // No full-speed other speed configuration
0, // No high-speed device descriptor
0, // No high-speed configuration descriptor
0, // No high-speed device qualifier descriptor
0, // No high-speed other speed configuration descriptor
#endif
stringDescriptors,
4 // Four string descriptors in array
};
@@ -0,0 +1,83 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
/// !Purpose
///
/// Definitions of the descriptors required by a Mass Storage device driver.
///
/// !Usage
///
/// - For a USB %device:
/// -# When initializing a USBDDriver instance, use msdDriverDescriptors as
/// the list of standard descriptors.
//------------------------------------------------------------------------------
#ifndef MSDDRIVERDESCRIPTORS_H
#define MSDDRIVERDESCRIPTORS_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <usb/device/core/USBDDriverDescriptors.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "MSD endpoint addresses"
/// This page lists the addresses used by the Mass Storage driver %endpoints.
///
/// !Addresses
///
/// - MSDDriverDescriptors_BULKOUT
/// - MSDDriverDescriptors_BULKIN
/// Address of the Mass Storage bulk-out endpoint.
#define MSDDriverDescriptors_BULKOUT 1
/// Address of the Mass Storage bulk-in endpoint.
#if defined(at91sam9m10)
#define MSDDriverDescriptors_BULKIN 6
#else
#define MSDDriverDescriptors_BULKIN 2
#endif
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Exported variables
//------------------------------------------------------------------------------
extern const USBDDriverDescriptors msdDriverDescriptors;
#endif //#ifndef MSDDRIVERDESCRIPTORS_H
@@ -0,0 +1,135 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef _MSDIOFIFO_H
#define _MSDIOFIFO_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
/// Idle state, do nothing
#define MSDIO_IDLE 0
/// Start, to start IO operation
#define MSDIO_START 1
/// Wait, waiting for IO operation done
#define MSDIO_WAIT 2
/// Next, to check if the next block can be performed
#define MSDIO_NEXT 3
/// Pause, to pause the process for buffer full or null
#define MSDIO_PAUSE 4
/// Abort, to abort the process
#define MSDIO_ABORT 5
/// Done, finish without error
#define MSDIO_DONE 6
/// Error, any error happens
#define MSDIO_ERROR 7
/// FIFO offset before USB transmit start
//#define MSDIO_FIFO_OFFSET (4*512)
/// FIFO trunk size (in each transfer, large amount of data)
#if !defined(MSD_OP_BUFFER)
#define MSDIO_READ10_CHUNK_SIZE (4*512)
#define MSDIO_WRITE10_CHUNK_SIZE (4*512)
#endif
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
/// FIFO buffer for READ/WRITE (disk) operation of a mass storage device
typedef struct _MSDIOFifo {
/// Pointer to the ring buffer allocated for read/write
unsigned char * pBuffer;
/// The size of the buffer allocated
unsigned int bufferSize;
#ifdef MSDIO_FIFO_OFFSET
/// The offset to start USB transfer (READ10)
unsigned int bufferOffset;
#endif
/// The index of input data (loaded to fifo buffer)
unsigned int inputNdx;
/// The total size of the loaded data
unsigned int inputTotal;
/// The index of output data (sent from the fifo buffer)
unsigned int outputNdx;
/// The total size of the output data
unsigned int outputTotal;
/// The total size of the data
unsigned int dataTotal;
/// The size of the block in bytes
unsigned short blockSize;
#if defined(MSDIO_READ10_CHUNK_SIZE) || defined(MSDIO_WRITE10_CHUNK_SIZE)
/// The size of one chunk
/// (1 block, or several blocks for large amount data R/W)
unsigned int chunkSize;
#endif
/// State of input & output
unsigned char inputState;
unsigned char outputState;
//- Statistics
/// Times when fifo has no data to send
unsigned short nullCnt;
/// Times when fifo can not load more input data
unsigned short fullCnt;
} MSDIOFifo, *PMSDIOFifo;
//------------------------------------------------------------------------------
// MACROS
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Increase the index, by defined block size, in the ring buffer
/// \param ndx The index to be increased
/// \param sectSize The defined block size
/// \param bufSize The ring buffer size
//------------------------------------------------------------------------------
#define MSDIOFifo_IncNdx(ndx, sectSize, bufSize) \
if ((ndx) >= (bufSize) - (sectSize)) (ndx) = 0; \
else (ndx) += (sectSize)
//------------------------------------------------------------------------------
// Exported Functions
//------------------------------------------------------------------------------
extern void MSDIOFifo_Init(MSDIOFifo *pFifo,
void * pBuffer, unsigned short bufferSize);
#endif // _MSDIOFIFO_H
@@ -0,0 +1,366 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "MSDLun.h"
#include "debug.h"
#include <usb/device/core/USBD.h>
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
/// Default LUN block size in bytes
#define DEFAULT_LUN_BLOCK_SIZE 512
//------------------------------------------------------------------------------
// Internal variables
//------------------------------------------------------------------------------
/// Inquiry data to return to the host for the Lun.
static SBCInquiryData inquiryData = {
SBC_DIRECT_ACCESS_BLOCK_DEVICE, // Direct-access block device
SBC_PERIPHERAL_DEVICE_CONNECTED,// Peripheral device is connected
0x00, // Reserved bits
0x01, // Media is removable
SBC_SPC_VERSION_4, // SPC-4 supported
0x2, // Response data format, must be 0x2
0, // Hierarchical addressing not supported
0, // ACA not supported
0x0, // Obsolete bits
sizeof(SBCInquiryData) - 5, // Additional length
0, // No embedded SCC
0, // No access control coordinator
SBC_TPGS_NONE, // No target port support group
0, // Third-party copy not supported
0x0, // Reserved bits
0, // Protection information not supported
0x0, // Obsolete bit
0, // No embedded enclosure service component
0x0, // ???
0, // Device is not multi-port
0x0, // Obsolete bits
0x0, // Unused feature
0x0, // Unused features
0, // Task management model not supported
0x0, // ???
{'A','T','M','E','L',' ',' ',' '},
{'M','a','s','s',' ',
'S','t','o','r','a','g','e',' ',
'M','S','D'},
{'0','.','0','1'},
{'M','a','s','s',' ',
'S','t','o','r','a','g','e',' ',
'E','x','a','m','p','l','e'},
0x00, // Unused features
0x00, // Reserved bits
{SBC_VERSION_DESCRIPTOR_SBC_3}, // SBC-3 compliant device
{0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0} // Reserved
};
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \brief Initializes a LUN instance. Must be invoked at least once even no
//! Media is linked.
//! \param lun Pointer to the MSDLun instance to initialize
//! \param media Media on which the LUN is constructed, set to 0 to
//! disconnect the Media or initialize an ejected LUN.
//! \param ioBuffer Pointer to a buffer used for read/write operation and
//! which must be blockSize bytes long.
//! \param ioBufferSize Size of the allocated IO buffer.
//! \param baseAddress Base address of the LUN in number of media blocks
//! \param size Total size of the LUN in number of media blocks
//! \param blockSize One block of the LUN in number of media blocks
//! \param protected The LUN area is forced to readonly even the media
//! is writable
//! \param dataMonitor Pointer to a Monitor Function to analyze the flow of
//! this LUN.
//------------------------------------------------------------------------------
void LUN_Init(MSDLun *lun,
Media *media,
unsigned char *ioBuffer,
unsigned int ioBufferSize,
unsigned int baseAddress,
unsigned int size,
unsigned short blockSize,
unsigned char protected,
void (*dataMonitor)(unsigned char flowDirection,
unsigned int dataLength,
unsigned int fifoNullCount,
unsigned int fifoFullCount))
{
unsigned int logicalBlockAddress;
TRACE_INFO("LUN init\n\r");
// Initialize inquiry data
lun->inquiryData = &inquiryData;
// Initialize request sense data
lun->requestSenseData.bResponseCode = SBC_SENSE_DATA_FIXED_CURRENT;
lun->requestSenseData.isValid = 1;
lun->requestSenseData.bObsolete1 = 0;
lun->requestSenseData.bSenseKey = SBC_SENSE_KEY_NO_SENSE;
lun->requestSenseData.bReserved1 = 0;
lun->requestSenseData.isILI = 0;
lun->requestSenseData.isEOM = 0;
lun->requestSenseData.isFilemark = 0;
lun->requestSenseData.pInformation[0] = 0;
lun->requestSenseData.pInformation[1] = 0;
lun->requestSenseData.pInformation[2] = 0;
lun->requestSenseData.pInformation[3] = 0;
lun->requestSenseData.bAdditionalSenseLength
= sizeof(SBCRequestSenseData) - 8;
lun->requestSenseData.bAdditionalSenseCode = 0;
lun->requestSenseData.bAdditionalSenseCodeQualifier = 0;
lun->requestSenseData.bFieldReplaceableUnitCode = 0;
lun->requestSenseData.bSenseKeySpecific = 0;
lun->requestSenseData.pSenseKeySpecific[0] = 0;
lun->requestSenseData.pSenseKeySpecific[0] = 0;
lun->requestSenseData.isSKSV = 0;
STORE_DWORDB(0, lun->readCapacityData.pLogicalBlockAddress);
STORE_DWORDB(0, lun->readCapacityData.pLogicalBlockLength);
// Initialize LUN
lun->media = media;
if (media == 0) {
lun->status = LUN_NOT_PRESENT;
return;
}
lun->baseAddress = baseAddress;
// Customized block size
if (blockSize) {
lun->blockSize = blockSize;
}
else {
if (media->blockSize < DEFAULT_LUN_BLOCK_SIZE)
lun->blockSize = DEFAULT_LUN_BLOCK_SIZE / media->blockSize;
else
lun->blockSize = 1;
}
if (size) {
lun->size = size;
}
else {
lun->size = media->size;
//if (blockSize)
// lun->size = media->size / blockSize;
//else {
// if (media->blockSize < DEFAULT_LUN_BLOCK_SIZE)
// lun->size = media->size / lun->blockSize;
// else
// lun->size = media->size;
//}
}
TRACE_INFO("LUN: blkSize %d, size %d\n\r", (int)lun->blockSize, (int)lun->size);
if (protected) lun->protected = 1;
else lun->protected = media->protected;
lun->ioFifo.pBuffer = ioBuffer;
lun->ioFifo.bufferSize = ioBufferSize;
lun->dataMonitor = dataMonitor;
// Initialize read capacity data
logicalBlockAddress = lun->size / lun->blockSize - 1;
STORE_DWORDB(logicalBlockAddress,
lun->readCapacityData.pLogicalBlockAddress);
STORE_DWORDB(lun->blockSize * media->blockSize,
lun->readCapacityData.pLogicalBlockLength);
// Indicate media change
lun->status = LUN_CHANGED;
}
//------------------------------------------------------------------------------
//! \brief Eject the media from a LUN
//! \param lun Pointer to the MSDLun instance to initialize
//! \return Operation result code
//------------------------------------------------------------------------------
unsigned char LUN_Eject(MSDLun *lun)
{
if (lun->media) {
// Avoid any LUN R/W in progress
if (lun->media->state == MED_STATE_BUSY) {
return USBD_STATUS_LOCKED;
}
// Remove the link of the media
lun->media = 0;
}
// LUN is removed
lun->status = LUN_NOT_PRESENT;
return USBD_STATUS_SUCCESS;
}
//------------------------------------------------------------------------------
//! \brief Writes data on the a LUN starting at the specified block address.
//! \param lun Pointer to a MSDLun instance
//! \param blockAddress First block address to write
//! \param data Pointer to the data to write
//! \param length Number of blocks to write
//! \param callback Optional callback to invoke when the write finishes
//! \return Operation result code
//------------------------------------------------------------------------------
unsigned char LUN_Write(MSDLun *lun,
unsigned int blockAddress,
void *data,
unsigned int length,
TransferCallback callback,
void *argument)
{
unsigned int medBlk, medLen;
unsigned char status;
TRACE_INFO_WP("LUNWrite(%u) ", blockAddress);
// Check that the data is not too big
if ((length + blockAddress) * lun->blockSize > lun->size) {
TRACE_WARNING("LUN_Write: Data too big\n\r");
status = USBD_STATUS_ABORTED;
}
else if (lun->media == 0 || lun->status != LUN_READY) {
TRACE_WARNING("LUN_Write: Media not ready\n\r");
status = USBD_STATUS_ABORTED;
}
else if (lun->protected) {
TRACE_WARNING("LUN_Write: LUN is readonly\n\r");
status = USBD_STATUS_ABORTED;
}
else {
// Compute write start address
medBlk = lun->baseAddress + blockAddress * lun->blockSize;
medLen = length * lun->blockSize;
// Start write operation
status = MED_Write(lun->media,
medBlk,
data,
medLen,
(MediaCallback) callback,
argument);
// Check operation result code
if (status == MED_STATUS_SUCCESS) {
status = USBD_STATUS_SUCCESS;
}
else {
TRACE_WARNING("LUN_Write: Cannot write media\n\r");
status = USBD_STATUS_ABORTED;
}
}
return status;
}
//------------------------------------------------------------------------------
//! \brief Reads data from a LUN, starting at the specified block address.
//! \param lun Pointer to a MSDLun instance
//! \param blockAddress First block address to read
//! \param data Pointer to a data buffer in which to store the data
//! \param length Number of blocks to read
//! \param callback Optional callback to invoke when the read finishes
//! \return Operation result code
//------------------------------------------------------------------------------
unsigned char LUN_Read(MSDLun *lun,
unsigned int blockAddress,
void *data,
unsigned int length,
TransferCallback callback,
void *argument)
{
unsigned int medBlk, medLen;
unsigned char status;
// Check that the data is not too big
if ((length + blockAddress) * lun->blockSize > lun->size) {
TRACE_WARNING("LUN_Read: Area: (%d + %d)*%d > %d\n\r",
(int)length, (int)blockAddress, (int)lun->blockSize, (int)lun->size);
status = USBD_STATUS_ABORTED;
}
else if (lun->media == 0 || lun->status != LUN_READY) {
TRACE_WARNING("LUN_Read: Media not present\n\r");
status = USBD_STATUS_ABORTED;
}
else {
TRACE_INFO_WP("LUNRead(%u) ", blockAddress);
// Compute read start address
medBlk = lun->baseAddress + (blockAddress * lun->blockSize);
medLen = length * lun->blockSize;
// Start write operation
status = MED_Read(lun->media,
medBlk,
data,
medLen,
(MediaCallback) callback,
argument);
// Check result code
if (status == MED_STATUS_SUCCESS) {
status = USBD_STATUS_SUCCESS;
}
else {
TRACE_WARNING("LUN_Read: Cannot read media\n\r");
status = USBD_STATUS_ABORTED;
}
}
return status;
}
@@ -0,0 +1,161 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
/// !Purpose
///
/// Logical Unit Number (LUN) used by the Mass Storage driver and the SCSI
/// protocol. Represents a logical hard-drive.
///
/// !Usage
/// -# Initialize Memory related pins (see pio & board.h).
/// -# Initialize a Media instance for the LUN (see memories).
/// -# Initlalize the LUN with LUN_Init, and link to the initialized Media.
/// -# To read data from the LUN linked media, uses LUN_Read.
/// -# To write data to the LUN linked media, uses LUN_Write.
/// -# To unlink the media, uses LUN_Eject.
//------------------------------------------------------------------------------
#ifndef MSDLUN_H
#define MSDLUN_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "SBC.h"
#include <Media.h>
#include <usb/device/massstorage/MSDIOFifo.h>
#include <usb/device/core/USBD.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
/// LUN RC: success
#define LUN_STATUS_SUCCESS 0x00
/// LUN RC: error
#define LUN_STATUS_ERROR 0x02
/// Media of LUN is removed
#define LUN_NOT_PRESENT 0x00
/// LUN is ejected by host
#define LUN_EJECTED 0x01
/// Media of LUN is changed
#define LUN_CHANGED 0x10
/// LUN Not Ready to Ready transition
#define LUN_TRANS_READY LUN_CHANGED
/// Media of LUN is ready
#define LUN_READY 0x11
//------------------------------------------------------------------------------
// Structures
//------------------------------------------------------------------------------
/// LUN structure
typedef struct {
/// Pointer to a SBCInquiryData instance.
SBCInquiryData *inquiryData;
/// Fifo for USB transfer, must be assigned.
MSDIOFifo ioFifo;
/// Pointer to Media instance for the LUN.
Media *media;
/// Pointer to a Monitor Function to analyze the flow of LUN.
/// \param flowDirection 1 - device to host (READ10)
/// 0 - host to device (WRITE10)
/// \param dataLength Length of data transferred in bytes.
/// \param fifoNullCount Times that FIFO is NULL to wait
/// \param fifoFullCount Times that FIFO is filled to wait
void (*dataMonitor)(unsigned char flowDirection,
unsigned int dataLength,
unsigned int fifoNullCount,
unsigned int fifoFullCount);
/// The start position of the media (blocks) allocated to the LUN.
unsigned int baseAddress;
/// The size of the media (blocks) allocated to the LUN.
unsigned int size;
/// Sector size of the media in number of media blocks
unsigned short blockSize;
/// The LUN can be readonly even the media is writable
#ifdef __cplusplus
unsigned char protectd;
#else
unsigned char protected;
#endif
/// The LUN status (Ejected/Changed/)
unsigned char status;
/// Data for the RequestSense command.
SBCRequestSenseData requestSenseData;
/// Data for the ReadCapacity command.
SBCReadCapacity10Data readCapacityData;
} MSDLun;
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void LUN_Init(MSDLun *lun,
Media *media,
unsigned char *ioBuffer,
unsigned int ioBufferSize,
unsigned int baseAddress,
unsigned int size,
unsigned short blockSize,
#ifdef __cplusplus
unsigned char protectd,
#else
unsigned char protected,
#endif
void (*dataMonitor)(unsigned char flowDirection,
unsigned int dataLength,
unsigned int fifoNullCount,
unsigned int fifoFullCount));
extern unsigned char LUN_Eject(MSDLun *lun);
extern unsigned char LUN_Write(MSDLun *lun,
unsigned int blockAddress,
void *data,
unsigned int length,
TransferCallback callback,
void *argument);
extern unsigned char LUN_Read(MSDLun *lun,
unsigned int blockAddress,
void *data,
unsigned int length,
TransferCallback callback,
void *argument);
#endif //#ifndef MSDLUN_H
@@ -0,0 +1,653 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
/// !Purpose
///
/// SCSI definitions.
///
/// !Usage
///
/// -# After command block received, Access and decode the SCSI command block
/// with SBCCommand structure.
//------------------------------------------------------------------------------
#ifndef SBC_H
#define SBC_H
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "SBC Operation Codes"
/// This page lists operation codes of commands described in the SBC-3
/// standard.
///
/// \note That most commands are actually defined in other standards,
/// like SPC-4. Optional commands are not included here.
///
/// \see sbc3r07.pdf - Section 5.1 - Table 12
/// \see spc4r06.pdf
/// \see SBCCommand
///
/// !Codes
/// - SBC_INQUIRY
/// - SBC_READ_10
/// - SBC_READ_CAPACITY_10
/// - SBC_REQUEST_SENSE
/// - SBC_TEST_UNIT_READY
/// - SBC_WRITE_10
///
/// !Optional Codes but required by Windows
/// - SBC_PREVENT_ALLOW_MEDIUM_REMOVAL
/// - SBC_MODE_SENSE_6
/// - SBC_VERIFY_10
/// - SBC_READ_FORMAT_CAPACITIES
/// Request information regarding parameters of the target and Logical Unit.
#define SBC_INQUIRY 0x12
/// Request the transfer data to the host.
#define SBC_READ_10 0x28
/// Request capacities of the currently installed medium.
#define SBC_READ_CAPACITY_10 0x25
/// Request that the device server transfer sense data.
#define SBC_REQUEST_SENSE 0x03
/// Check if the LUN is ready
#define SBC_TEST_UNIT_READY 0x00
/// Request that the device write the data transferred by the host.
#define SBC_WRITE_10 0x2A
/// Request that the target enable or disable the removal of the medium in
/// the Logical Unit.
#define SBC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E
/// Report parameters.
#define SBC_MODE_SENSE_6 0x1A
/// Request that the %device verify the data on the medium.
#define SBC_VERIFY_10 0x2F
/// Request a list of the possible capacities that can be formatted on medium
#define SBC_READ_FORMAT_CAPACITIES 0x23
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "SBC Periph. Qualifiers"
/// This page lists the peripheral qualifier values specified in the INQUIRY
/// data
/// \see spc4r06.pdf - Section 6.4.2 - Table 83
/// \see SBCInquiryData
///
/// !Qualifiers
/// - SBC_PERIPHERAL_DEVICE_CONNECTED
/// - SBC_PERIPHERAL_DEVICE_NOT_CONNECTED
/// - SBC_PERIPHERAL_DEVICE_NOT_SUPPORTED
#define SBC_PERIPHERAL_DEVICE_CONNECTED 0x00
#define SBC_PERIPHERAL_DEVICE_NOT_CONNECTED 0x01
#define SBC_PERIPHERAL_DEVICE_NOT_SUPPORTED 0x03
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "SBC Periph. Types"
/// This page lists peripheral device types specified in the INQUIRY data
/// \see spc4r06.pdf - Section 6.4.2 - Table 84
/// \see SBCInquiryData
///
/// !Types
/// - SBC_DIRECT_ACCESS_BLOCK_DEVICE
/// - SBC_SEQUENTIAL_ACCESS_DEVICE
/// - SBC_PRINTER_DEVICE
/// - SBC_PROCESSOR_DEVICE
/// - SBC_WRITE_ONCE_DEVICE
/// - SBC_CD_DVD_DEVICE
/// - SBC_SCANNER_DEVICE
/// - SBC_OPTICAL_MEMORY_DEVICE
/// - SBC_MEDIA_CHANGER_DEVICE
/// - SBC_COMMUNICATION_DEVICE
/// - SBC_STORAGE_ARRAY_CONTROLLER_DEVICE
/// - SBC_ENCLOSURE_SERVICES_DEVICE
/// - SBC_SIMPLIFIED_DIRECT_ACCESS_DEVICE
/// - SBC_OPTICAL_CARD_READER_WRITER_DEVICE
/// - SBC_BRIDGE_CONTROLLER_COMMANDS
/// - SBC_OBJECT_BASED_STORAGE_DEVICE
#define SBC_DIRECT_ACCESS_BLOCK_DEVICE 0x00
#define SBC_SEQUENTIAL_ACCESS_DEVICE 0x01
#define SBC_PRINTER_DEVICE 0x02
#define SBC_PROCESSOR_DEVICE 0x03
#define SBC_WRITE_ONCE_DEVICE 0x04
#define SBC_CD_DVD_DEVICE 0x05
#define SBC_SCANNER_DEVICE 0x06
#define SBC_OPTICAL_MEMORY_DEVICE 0x07
#define SBC_MEDIA_CHANGER_DEVICE 0x08
#define SBC_COMMUNICATION_DEVICE 0x09
#define SBC_STORAGE_ARRAY_CONTROLLER_DEVICE 0x0C
#define SBC_ENCLOSURE_SERVICES_DEVICE 0x0D
#define SBC_SIMPLIFIED_DIRECT_ACCESS_DEVICE 0x0E
#define SBC_OPTICAL_CARD_READER_WRITER_DEVICE 0x0F
#define SBC_BRIDGE_CONTROLLER_COMMANDS 0x10
#define SBC_OBJECT_BASED_STORAGE_DEVICE 0x11
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \brief Version value for the SBC-3 specification
/// \see spc4r06.pdf - Section 6.4.2 - Table 85
#define SBC_SPC_VERSION_4 0x06
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \brief Values for the TPGS field returned in INQUIRY data
/// \see spc4r06.pdf - Section 6.4.2 - Table 86
#define SBC_TPGS_NONE 0x0
#define SBC_TPGS_ASYMMETRIC 0x1
#define SBC_TPGS_SYMMETRIC 0x2
#define SBC_TPGS_BOTH 0x3
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \brief Version descriptor value for the SBC-3 specification
/// \see spc4r06.pdf - Section 6.4.2 - Table 87
#define SBC_VERSION_DESCRIPTOR_SBC_3 0x04C0
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "SBC Sense Response Codes"
/// This page lists sense data response codes returned in REQUEST SENSE data
/// \see spc4r06.pdf - Section 4.5.1 - Table 12
///
/// !Codes
/// - SBC_SENSE_DATA_FIXED_CURRENT
/// - SBC_SENSE_DATA_FIXED_DEFERRED
/// - SBC_SENSE_DATA_DESCRIPTOR_CURRENT
/// - SBC_SENSE_DATA_DESCRIPTOR_DEFERRED
#define SBC_SENSE_DATA_FIXED_CURRENT 0x70
#define SBC_SENSE_DATA_FIXED_DEFERRED 0x71
#define SBC_SENSE_DATA_DESCRIPTOR_CURRENT 0x72
#define SBC_SENSE_DATA_DESCRIPTOR_DEFERRED 0x73
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "SBC Sense Keys"
/// This page lists sense key values returned in the REQUEST SENSE data
/// \see spc4r06.pdf - Section 4.5.6 - Table 27
///
/// !Keys
/// - SBC_SENSE_KEY_NO_SENSE
/// - SBC_SENSE_KEY_RECOVERED_ERROR
/// - SBC_SENSE_KEY_NOT_READY
/// - SBC_SENSE_KEY_MEDIUM_ERROR
/// - SBC_SENSE_KEY_HARDWARE_ERROR
/// - SBC_SENSE_KEY_ILLEGAL_REQUEST
/// - SBC_SENSE_KEY_UNIT_ATTENTION
/// - SBC_SENSE_KEY_DATA_PROTECT
/// - SBC_SENSE_KEY_BLANK_CHECK
/// - SBC_SENSE_KEY_VENDOR_SPECIFIC
/// - SBC_SENSE_KEY_COPY_ABORTED
/// - SBC_SENSE_KEY_ABORTED_COMMAND
/// - SBC_SENSE_KEY_VOLUME_OVERFLOW
/// - SBC_SENSE_KEY_MISCOMPARE
/// No specific sense key. Successful command.
#define SBC_SENSE_KEY_NO_SENSE 0x00
/// Command completed succesfully with some recovery action by the %device.
#define SBC_SENSE_KEY_RECOVERED_ERROR 0x01
/// The device can not be accessed.
#define SBC_SENSE_KEY_NOT_READY 0x02
/// Command terminated with a error condition that was probably caused by a
/// flaw in the medium or an error in the recorded data.
#define SBC_SENSE_KEY_MEDIUM_ERROR 0x03
/// Hardware failure while performing the command or during a self test.
#define SBC_SENSE_KEY_HARDWARE_ERROR 0x04
/// Illegal parameter found in the command or additional parameters.
#define SBC_SENSE_KEY_ILLEGAL_REQUEST 0x05
/// Removable medium may have been changed or the %device has been reset.
#define SBC_SENSE_KEY_UNIT_ATTENTION 0x06
/// Write on a block that is protected.
#define SBC_SENSE_KEY_DATA_PROTECT 0x07
/// Indicates that a write-once device or a sequential-access device
/// encountered blank medium or format-defined end-of-data indication while
/// reading or a write-once device encountered a non-blank medium while writing.
#define SBC_SENSE_KEY_BLANK_CHECK 0x08
/// Reporting vendor specific conditions.
#define SBC_SENSE_KEY_VENDOR_SPECIFIC 0x09
/// EXTENDED COPY command was aborted.
#define SBC_SENSE_KEY_COPY_ABORTED 0x0A
/// Device aborted the command.
#define SBC_SENSE_KEY_ABORTED_COMMAND 0x0B
/// A buffered peripheral device is overflow.
#define SBC_SENSE_KEY_VOLUME_OVERFLOW 0x0D
/// The source data did not match the data read from the medium.
#define SBC_SENSE_KEY_MISCOMPARE 0x0E
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "SBC Sense Additionals"
/// This page lists additional sense code values returned in REQUEST SENSE data
/// \see spc4r06.pdf - Section 4.5.6 - Table 28
///
/// !Additional Codes
/// - SBC_ASC_LOGICAL_UNIT_NOT_READY
/// - SBC_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE
/// - SBC_ASC_INVALID_FIELD_IN_CDB
/// - SBC_ASC_WRITE_PROTECTED
/// - SBC_ASC_FORMAT_CORRUPTED
/// - SBC_ASC_INVALID_COMMAND_OPERATION_CODE
/// - SBC_ASC_TOO_MUCH_WRITE_DATA
/// - SBC_ASC_NOT_READY_TO_READY_CHANGE
/// - SBC_ASC_MEDIUM_NOT_PRESENT
#define SBC_ASC_LOGICAL_UNIT_NOT_READY 0x04
#define SBC_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x21
#define SBC_ASC_INVALID_FIELD_IN_CDB 0x24
#define SBC_ASC_WRITE_PROTECTED 0x27
#define SBC_ASC_FORMAT_CORRUPTED 0x31
#define SBC_ASC_INVALID_COMMAND_OPERATION_CODE 0x20
#define SBC_ASC_TOO_MUCH_WRITE_DATA 0x26
#define SBC_ASC_NOT_READY_TO_READY_CHANGE 0x28
#define SBC_ASC_MEDIUM_NOT_PRESENT 0x3A
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \brief MEDIUM TYPE field value for direct-access block devices
/// \see sbc3r06.pdf - Section 6.3.1
#define SBC_MEDIUM_TYPE_DIRECT_ACCESS_BLOCK_DEVICE 0x00
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \brief MRIE field values
/// \see sbc3r06.pdf - Section 7.4.11 - Table 286
#define SBC_MRIE_NO_REPORTING 0x00
#define SBC_MRIE_ASYNCHRONOUS 0x01
#define SBC_MRIE_GENERATE_UNIT_ATTENTION 0x02
#define SBC_MRIE_COND_GENERATE_RECOVERED_ERROR 0x03
#define SBC_MRIE_UNCOND_GENERATE_RECOVERED_ERROR 0x04
#define SBC_MRIE_GENERATE_NO_SENSE 0x05
#define SBC_MRIE_ON_REQUEST 0x06
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \brief Supported mode pages
/// \see sbc3r06.pdf - Section 6.3.1 - Table 115
#define SBC_PAGE_READ_WRITE_ERROR_RECOVERY 0x01
#define SBC_PAGE_INFORMATIONAL_EXCEPTIONS_CONTROL 0x1C
#define SBC_PAGE_RETURN_ALL 0x3F
#define SBC_PAGE_VENDOR_SPECIFIC 0x00
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "MSD Endian Macros"
/// This page lists the macros for endianness conversion.
///
/// !Macros
/// - WORDB
/// - DWORDB
/// - STORE_DWORDB
/// - STORE_WORDB
/// \brief Converts a byte array to a word value using the big endian format
#define WORDB(bytes) ((unsigned short) ((bytes[0] << 8) | bytes[1]))
/// \brief Converts a byte array to a dword value using the big endian format
#define DWORDB(bytes) ((unsigned int) ((bytes[0] << 24) | (bytes[1] << 16) \
| (bytes[2] << 8) | bytes[3]))
/// \brief Stores a dword value in a byte array, in big endian format
#define STORE_DWORDB(dword, bytes) \
bytes[0] = (unsigned char) (((dword) >> 24) & 0xFF); \
bytes[1] = (unsigned char) (((dword) >> 16) & 0xFF); \
bytes[2] = (unsigned char) (((dword) >> 8) & 0xFF); \
bytes[3] = (unsigned char) ((dword) & 0xFF);
/// \brief Stores a word value in a byte array, in big endian format
#define STORE_WORDB(word, bytes) \
bytes[0] = (unsigned char) (((word) >> 8) & 0xFF); \
bytes[1] = (unsigned char) ((word) & 0xFF);
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Structures
//------------------------------------------------------------------------------
#ifdef __ICCARM__ // IAR
#pragma pack(1) // IAR
#define __attribute__(...) // IAR
#endif // IAR
//------------------------------------------------------------------------------
/// \brief Structure for the INQUIRY command
/// \see spc4r06.pdf - Section 6.4.1 - Table 81
//------------------------------------------------------------------------------
typedef struct {
unsigned char bOperationCode; //!< 0x12 : SBC_INQUIRY
unsigned char isEVPD:1, //!< Type of requested data
bReserved1:7; //!< Reserved bits
unsigned char bPageCode; //!< Specifies the VPD to return
unsigned char pAllocationLength[2]; //!< Size of host buffer
unsigned char bControl; //!< 0x00
} __attribute__ ((packed)) SBCInquiry; // GCC
//------------------------------------------------------------------------------
/// \brief Standard INQUIRY data format returned by the device
/// \see spc4r06.pdf - Section 6.4.2 - Table 82
//------------------------------------------------------------------------------
typedef struct {
unsigned char bPeripheralDeviceType:5, //!< Peripheral device type
bPeripheralQualifier :3; //!< Peripheral qualifier
unsigned char bReserved1:7, //!< Reserved bits
isRMB :1; //!< Is media removable ?
unsigned char bVersion; //!< SPC version used
unsigned char bResponseDataFormat:4, //!< Must be 0x2
isHIGHSUP :1, //!< Hierarchical addressing used ?
isNORMACA :1, //!< ACA attribute supported ?
bObsolete1 :2; //!< Obsolete bits
unsigned char bAdditionalLength; //!< Length of remaining INQUIRY data
unsigned char isSCCS :1, //!< Embedded SCC ?
isACC :1, //!< Access control coordinator ?
bTPGS :2, //!< Target port support group
is3PC :1, //!< Third-party copy supported ?
bReserved2:2, //!< Reserved bits
isProtect :1; //!< Protection info supported ?
unsigned char bObsolete2:1, //!< Obsolete bit
isEncServ :1, //!< Embedded enclosure service comp?
isVS :1, //!< ???
isMultiP :1, //!< Multi-port device ?
bObsolete3:3, //!< Obsolete bits
bUnused1 :1; //!< Unused feature
unsigned char bUnused2:6, //!< Unused features
isCmdQue:1, //!< Task management model supported ?
isVS2 :1; //!< ???
unsigned char pVendorID[8]; //!< T10 vendor identification
unsigned char pProductID[16]; //!< Vendor-defined product ID
unsigned char pProductRevisionLevel[4];//!< Vendor-defined product revision
unsigned char pVendorSpecific[20]; //!< Vendor-specific data
unsigned char bUnused3; //!< Unused features
unsigned char bReserved3; //!< Reserved bits
unsigned short pVersionDescriptors[8]; //!< Standards the device complies to
unsigned char pReserved4[22]; //!< Reserved bytes
} __attribute__ ((packed)) SBCInquiryData; // GCC
//------------------------------------------------------------------------------
/// \brief Data structure for the READ (10) command
/// \see sbc3r07.pdf - Section 5.7 - Table 34
//------------------------------------------------------------------------------
typedef struct {
unsigned char bOperationCode; //!< 0x28 : SBC_READ_10
unsigned char bObsolete1:1, //!< Obsolete bit
isFUA_NV:1, //!< Cache control bit
bReserved1:1, //!< Reserved bit
isFUA:1, //!< Cache control bit
isDPO:1, //!< Cache control bit
bRdProtect:3; //!< Protection information to send
unsigned char pLogicalBlockAddress[4]; //!< Index of first block to read
unsigned char bGroupNumber:5, //!< Information grouping
bReserved2:3; //!< Reserved bits
unsigned char pTransferLength[2]; //!< Number of blocks to transmit
unsigned char bControl; //!< 0x00
} __attribute__ ((packed)) SBCRead10; // GCC
//------------------------------------------------------------------------------
/// \brief Structure for the READ CAPACITY (10) command
/// \see sbc3r07.pdf - Section 5.11.1 - Table 40
//------------------------------------------------------------------------------
typedef struct {
unsigned char bOperationCode; //!< 0x25 : RBC_READ_CAPACITY
unsigned char bObsolete1:1, //!< Obsolete bit
bReserved1:7; //!< Reserved bits
unsigned char pLogicalBlockAddress[4]; //!< Block to evaluate if PMI is set
unsigned char pReserved2[2]; //!< Reserved bytes
unsigned char isPMI:1, //!< Partial medium indicator bit
bReserved3:7; //!< Reserved bits
unsigned char bControl; //!< 0x00
} __attribute__ ((packed)) SBCReadCapacity10;
//------------------------------------------------------------------------------
/// \brief Data returned by the device after a READ CAPACITY (10) command
/// \see sbc3r07.pdf - Section 5.11.2 - Table 41
//------------------------------------------------------------------------------
typedef struct {
unsigned char pLogicalBlockAddress[4]; //!< Address of last logical block
unsigned char pLogicalBlockLength[4]; //!< Length of each logical block
} __attribute__ ((packed)) SBCReadCapacity10Data;
//------------------------------------------------------------------------------
/// \brief Structure for the REQUEST SENSE command
/// \see spc4r06.pdf - Section 6.26 - Table 170
//------------------------------------------------------------------------------
typedef struct {
unsigned char bOperationCode; //!< 0x03 : SBC_REQUEST_SENSE
unsigned char isDesc :1, //!< Type of information expected
bReserved1:7; //!< Reserved bits
unsigned char pReserved2[2]; //!< Reserved bytes
unsigned char bAllocationLength; //!< Size of host buffer
unsigned char bControl; //!< 0x00
} __attribute__ ((packed)) SBCRequestSense;
//------------------------------------------------------------------------------
/// \brief Fixed format sense data returned after a REQUEST SENSE command has
/// been received with a DESC bit cleared.
/// \see spc4r06.pdf - Section 4.5.3 - Table 26
//------------------------------------------------------------------------------
typedef struct {
unsigned char bResponseCode:7, //!< Sense data format
isValid :1; //!< Information field is standard
unsigned char bObsolete1; //!< Obsolete byte
unsigned char bSenseKey :4, //!< Generic error information
bReserved1:1, //!< Reserved bit
isILI :1, //!< SSC
isEOM :1, //!< SSC
isFilemark:1; //!< SSC
unsigned char pInformation[4]; //!< Command-specific
unsigned char bAdditionalSenseLength; //!< sizeof(SBCRequestSense_data)-8
unsigned char pCommandSpecificInformation[4]; //!< Command-specific
unsigned char bAdditionalSenseCode; //!< Additional error information
unsigned char bAdditionalSenseCodeQualifier; //!< Further error information
unsigned char bFieldReplaceableUnitCode; //!< Specific component code
unsigned char bSenseKeySpecific:7, //!< Additional exception info
isSKSV :1; //!< Is sense key specific valid?
unsigned char pSenseKeySpecific[2]; //!< Additional exception info
} __attribute__ ((packed)) SBCRequestSenseData;
//------------------------------------------------------------------------------
/// \brief Data structure for the TEST UNIT READY command
/// \see spc4r06.pdf - Section 6.34 - Table 192
//------------------------------------------------------------------------------
typedef struct {
unsigned char bOperationCode; //!< 0x00 : SBC_TEST_UNIT_READY
unsigned char pReserved1[4]; //!< Reserved bits
unsigned char bControl; //!< 0x00
} __attribute__ ((packed)) SBCTestUnitReady; // GCC
//------------------------------------------------------------------------------
/// \brief Structure for the WRITE (10) command
/// \see sbc3r07.pdf - Section 5.26 - Table 70
//------------------------------------------------------------------------------
typedef struct {
unsigned char bOperationCode; //!< 0x2A : SBC_WRITE_10
unsigned char bObsolete1:1, //!< Obsolete bit
isFUA_NV:1, //!< Cache control bit
bReserved1:1, //!< Reserved bit
isFUA:1, //!< Cache control bit
isDPO:1, //!< Cache control bit
bWrProtect:3; //!< Protection information to send
unsigned char pLogicalBlockAddress[4]; //!< First block to write
unsigned char bGroupNumber:5, //!< Information grouping
bReserved2:3; //!< Reserved bits
unsigned char pTransferLength[2]; //!< Number of blocks to write
unsigned char bControl; //!< 0x00
} __attribute__ ((packed)) SBCWrite10;
//------------------------------------------------------------------------------
/// \brief Structure for the PREVENT/ALLOW MEDIUM REMOVAL command
/// \see sbc3r07.pdf - Section 5.5 - Table 30
//------------------------------------------------------------------------------
typedef struct {
unsigned char bOperationCode; //!< 0x1E : SBC_PREVENT_ALLOW_MEDIUM_REMOVAL
unsigned char pReserved1[3]; //!< Reserved bytes
unsigned char bPrevent:2, //!< Accept/prohibit removal
bReserved2:6; //!< Reserved bits
unsigned char bControl; //!< 0x00
} __attribute__ ((packed)) SBCMediumRemoval; // GCC
//------------------------------------------------------------------------------
/// \brief Structure for the MODE SENSE (6) command
/// \see spc4r06 - Section 6.9.1 - Table 98
//------------------------------------------------------------------------------
typedef struct {
unsigned char bOperationCode; //!< 0x1A : SBC_MODE_SENSE_6
unsigned char bReserved1:3, //!< Reserved bits
isDBD:1, //!< Disable block descriptors bit
bReserved2:4; //!< Reserved bits
unsigned char bPageCode:6, //!< Mode page to return
bPC:2; //!< Type of parameter values to return
unsigned char bSubpageCode; //!< Mode subpage to return
unsigned char bAllocationLength; //!< Host buffer allocated size
unsigned char bControl; //!< 0x00
} __attribute__ ((packed)) SBCModeSense6; // GCC
//------------------------------------------------------------------------------
/// \brief Header for the data returned after a MODE SENSE (6) command
/// \see spc4r06.pdf - Section 7.4.3 - Table 268
//------------------------------------------------------------------------------
typedef struct {
unsigned char bModeDataLength; //!< Length of mode data to follow
unsigned char bMediumType; //!< Type of medium (SBC_MEDIUM_TYPE_DIRECT_ACCESS_BLOCK_DEVICE)
unsigned char bReserved1:4, //!< Reserved bits
isDPOFUA:1, //!< DPO/FUA bits supported ?
bReserved2:2, //!< Reserved bits
isWP:1; //!< Is medium write-protected ?
unsigned char bBlockDescriptorLength; //!< Length of all block descriptors
} __attribute__ ((packed)) SBCModeParameterHeader6; // GCC
//------------------------------------------------------------------------------
/// \brief Informational exceptions control mode page
/// \see spc4r06.pdf - Section 7.4.11 - Table 285
//------------------------------------------------------------------------------
typedef struct {
unsigned char bPageCode:6, //!< 0x1C : SBC_PAGE_INFORMATIONAL_EXCEPTIONS_CONTROL
isSPF:1, //!< Page or subpage data format
isPS:1; //!< Parameters saveable ?
unsigned char bPageLength; //!< Length of page data (0x0A)
unsigned char isLogErr:1, //!< Should informational exceptions be logged ?
isEBackErr:1, //!< Enable background error bit
isTest:1, //!< Create a device test failure ?
isDExcpt:1, //!< Disable exception control bit
isEWasc:1, //!< Report warnings ?
isEBF:1, //!< Enable background function bit
bReserved1:1, //!< Reserved bit
isPerf:1; //!< Delay acceptable when treating exceptions ?
unsigned char bMRIE:4, //!< Method of reporting informational exceptions
bReserved2:4; //!< Reserved bits
unsigned char pIntervalTimer[4]; //!< Error reporting period
unsigned char pReportCount[4]; //!< Maximum number of time a report can be issued
} __attribute__ ((packed)) SBCInformationalExceptionsControl; // GCC
//------------------------------------------------------------------------------
/// \brief Read/write error recovery mode page
/// \see sbc3r07.pdf - Section 6.3.5 - Table 122
//------------------------------------------------------------------------------
typedef struct {
unsigned char bPageCode:6, //!< 0x01 : SBC_PAGE_READ_WRITE_ERROR_RECOVERY
isSPF:1, //!< Page or subpage data format
isPS:1; //!< Parameters saveable ?
unsigned char bPageLength; //!< Length of page data (0x0A)
unsigned char isDCR:1, //!< Disable correction bit
isDTE:1, //!< Data terminate on error bit
isPER:1, //!< Post error bit
isEER:1, //!< Enable early recovery bit
isRC:1, //!< Read continuous bit
isTB:1, //!< Transfer block bit
isARRE:1, //!< Automatic read reallocation enabled bit
isAWRE:1; //!< Automatic write reallocation enabled bit
unsigned char bReadRetryCount; //!< Number of retries when reading
unsigned char pObsolete1[3]; //!< Obsolete bytes
unsigned char bReserved1; //!< Reserved byte
unsigned char bWriteRetryCount; //!< Number of retries when writing
unsigned char bReserved2; //!< Reserved byte
unsigned char pRecoveryTimeLimit[2]; //!< Maximum time duration for error recovery
} __attribute__ ((packed)) SBCReadWriteErrorRecovery; // GCC
//------------------------------------------------------------------------------
/// \brief Generic structure for holding information about SBC commands
/// \see SBCInquiry
/// \see SBCRead10
/// \see SBCReadCapacity10
/// \see SBCRequestSense
/// \see SBCTestUnitReady
/// \see SBCWrite10
/// \see SBCMediumRemoval
/// \see SBCModeSense6
//------------------------------------------------------------------------------
typedef union {
unsigned char bOperationCode; //!< Operation code of the command
SBCInquiry inquiry; //!< INQUIRY command
SBCRead10 read10; //!< READ (10) command
SBCReadCapacity10 readCapacity10; //!< READ CAPACITY (10) command
SBCRequestSense requestSense; //!< REQUEST SENSE command
SBCTestUnitReady testUnitReady; //!< TEST UNIT READY command
SBCWrite10 write10; //!< WRITE (10) command
SBCMediumRemoval mediumRemoval; //!< PREVENT/ALLOW MEDIUM REMOVAL command
SBCModeSense6 modeSense6; //!< MODE SENSE (6) command
} SBCCommand;
#ifdef __ICCARM__ // IAR
#pragma pack() // IAR
#endif // IAR
#endif //#ifndef SBC_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,111 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
/// !Purpose
///
/// SCSI commands implementation.
///
/// !Usage
///
/// -# After a CBW is received from host, use SBC_GetCommandInformation to check
/// if the command is supported, and get the command length and type
/// information before processing it.
/// -# Then SBC_ProcessCommand can be used to handle a valid command, to
/// perform the command operations.
/// -# SBC_UpdateSenseData is used to update the sense data that will be sent
/// to host.
//------------------------------------------------------------------------------
#ifndef SBCMETHODS_H
#define SBCMETHODS_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "SBC.h"
// #include <nand/MSDLun.h>
#include "MSDDStateMachine.h"
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "SBC Command States"
/// This page lists the possible states of a SBC command.
///
/// !States
/// - SBC_STATE_READ
/// - SBC_STATE_WAIT_READ
/// - SBC_STATE_WRITE
/// - SBC_STATE_WAIT_WRITE
/// - SBC_STATE_NEXT_BLOCK
/// Start of reading bulk data
#define SBC_STATE_READ 0x01
/// Waiting for the bulk data reading complete
#define SBC_STATE_WAIT_READ 0x02
/// Read error state
#define SBC_STATE_READ_ERROR 0x03
/// Start next read block
#define SBC_STATE_NEXT_READ 0x04
/// Start writing bulk data to host
#define SBC_STATE_WRITE 0x05
/// Waiting for the bulk data sending complete
#define SBC_STATE_WAIT_WRITE 0x06
/// Write error state
#define SBC_STATE_WRITE_ERROR 0x07
/// Start next write block
#define SBC_STATE_NEXT_WRITE 0x08
/// Start next command block
#define SBC_STATE_NEXT_BLOCK 0x09
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
void SBC_UpdateSenseData(SBCRequestSenseData *requestSenseData,
unsigned char senseKey,
unsigned char additionalSenseCode,
unsigned char additionalSenseCodeQualifier);
unsigned char SBC_GetCommandInformation(void *command,
unsigned int *length,
unsigned char *type,
MSDLun *lun);
unsigned char SBC_ProcessCommand(MSDLun *lun,
MSDCommandState *commandState);
#endif //#ifndef SBCMETHODS_H
+187
View File
@@ -0,0 +1,187 @@
/****************************************************************************
* Copyright (c) 2011 by Michael Fischer. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
****************************************************************************
* History:
*
* 22.05.2011 mifi First Version for the SAM3S4C
****************************************************************************/
#define __VECTORS_SAM3S_C__
#include "debug.h"
/*=========================================================================*/
/* DEFINE: All extern Data */
/*=========================================================================*/
extern unsigned long _estack;
/*=========================================================================*/
/* DEFINE: Prototypes */
/*=========================================================================*/
void ResetHandler(void);
void NMI_Handler (void) __attribute__((weak));
void HardFault_Handler (void) __attribute__((weak));
void MemManage_Handler (void) __attribute__((weak));
void BusFault_Handler (void) __attribute__((weak));
void UsageFault_Handler (void) __attribute__((weak));
void SVC_Handler (void) __attribute__((weak));
void DebugMon_Handler (void) __attribute__((weak));
void PendSV_Handler(void) __attribute__((weak));
void SysTick_Handler (void) __attribute__((weak));
void SUPC_IRQHandler (void) __attribute__((weak));
void RSTC_IRQHandler (void) __attribute__((weak));
void RTC_IRQHandler (void) __attribute__((weak));
void RTT_IRQHandler (void) __attribute__((weak));
void WDT_IRQHandler (void) __attribute__((weak));
void PMC_IRQHandler (void) __attribute__((weak));
void EEFC_IRQHandler (void) __attribute__((weak));
void UART0_IRQHandler (void) __attribute__((weak));
void UART1_IRQHandler (void) __attribute__((weak));
void SMC_IRQHandler (void) __attribute__((weak));
void PIOA_IRQHandler (void) __attribute__((weak));
void PIOB_IRQHandler (void) __attribute__((weak));
void PIOC_IRQHandler (void) __attribute__((weak));
void USART0_IRQHandler (void) __attribute__((weak));
void USART1_IRQHandler (void) __attribute__((weak));
void MCI_IRQHandler (void) __attribute__((weak));
void TWI0_IRQHandler (void) __attribute__((weak));
void TWI1_IRQHandler (void) __attribute__((weak));
void SPI_IRQHandler (void) __attribute__((weak));
void SSC_IRQHandler (void) __attribute__((weak));
void TC0_IRQHandler (void) __attribute__((weak));
void TC1_IRQHandler (void) __attribute__((weak));
void TC2_IRQHandler (void) __attribute__((weak));
void TC3_IRQHandler (void) __attribute__((weak));
void TC4_IRQHandler (void) __attribute__((weak));
void TC5_IRQHandler (void) __attribute__((weak));
void ADC_IRQHandler (void) __attribute__((weak));
void DAC_IRQHandler (void) __attribute__((weak));
void PWM_IRQHandler (void) __attribute__((weak));
void CRCCU_IRQHandler (void) __attribute__((weak));
void ACC_IRQHandler (void) __attribute__((weak));
void USBD_IrqHandler (void) __attribute__((weak));
/*=========================================================================*/
/* DEFINE: All code exported */
/*=========================================================================*/
/*
* This is our vector table.
*/
__attribute__ ((section(".vectors"), used))
void (* const gVectors[])(void) =
{
(void (*)(void))((unsigned long)&_estack),
ResetHandler,
NMI_Handler,
HardFault_Handler,
MemManage_Handler,
BusFault_Handler,
UsageFault_Handler,
0, 0, 0, 0,
SVC_Handler,
DebugMon_Handler,
0,
PendSV_Handler,
SysTick_Handler,
SUPC_IRQHandler, /* 0 SUPPLY CONTROLLER */
RSTC_IRQHandler, /* 1 RESET CONTROLLER */
RTC_IRQHandler, /* 2 REAL TIME CLOCK */
RTT_IRQHandler, /* 3 REAL TIME TIMER */
WDT_IRQHandler, /* 4 WATCHDOG TIMER */
PMC_IRQHandler, /* 5 PMC */
EEFC_IRQHandler, /* 6 EEFC */
0, /* 7 Reserved */
UART0_IRQHandler, /* 8 UART0 */
UART1_IRQHandler, /* 9 UART1 */
SMC_IRQHandler, /* 10 SMC */
PIOA_IRQHandler, /* 11 Parallel IO Controller A */
PIOB_IRQHandler, /* 12 Parallel IO Controller B */
PIOC_IRQHandler, /* 13 Parallel IO Controller C */
USART0_IRQHandler, /* 14 USART 0 */
USART1_IRQHandler, /* 15 USART 1 */
0, /* 16 Reserved */
0, /* 17 Reserved */
MCI_IRQHandler, /* 18 MCI */
TWI0_IRQHandler, /* 19 TWI 0 */
TWI1_IRQHandler, /* 20 TWI 1 */
SPI_IRQHandler, /* 21 SPI */
SSC_IRQHandler, /* 22 SSC */
TC0_IRQHandler, /* 23 Timer Counter 0 */
TC1_IRQHandler, /* 24 Timer Counter 1 */
TC2_IRQHandler, /* 25 Timer Counter 2 */
TC3_IRQHandler, /* 26 Timer Counter 3 */
TC4_IRQHandler, /* 27 Timer Counter 4 */
TC5_IRQHandler, /* 28 Timer Counter 5 */
ADC_IRQHandler, /* 29 ADC controller */
DAC_IRQHandler, /* 30 DAC controller */
PWM_IRQHandler, /* 31 PWM */
CRCCU_IRQHandler, /* 32 CRC Calculation Unit */
ACC_IRQHandler, /* 33 Analog Comparator */
USBD_IrqHandler, /* 34 USB Device Port */
0 /* 35 not used */
}; /* gVectors */
/*
* And here are the weak interrupt handlers.
*/
void NMI_Handler (void) { while(1); }
void HardFault_Handler (void) { while(1); }
void MemManage_Handler (void) { while(1); }
void BusFault_Handler (void) { while(1); }
void UsageFault_Handler (void) { while(1); }
void SVC_Handler (void) { while(1); }
void DebugMon_Handler (void) { while(1); }
void SUPC_IRQHandler (void) { while(1); }
void RSTC_IRQHandler (void) { while(1); }
void RTC_IRQHandler (void) { while(1); }
void RTT_IRQHandler (void) { while(1); }
void WDT_IRQHandler (void) { while(1); }
void PMC_IRQHandler (void) { while(1); }
void EEFC_IRQHandler (void) { while(1); }
void UART1_IRQHandler (void) { while(1); }
void SMC_IRQHandler (void) { while(1); }
void PIOA_IRQHandler (void) { while(1); }
void PIOB_IRQHandler (void) { while(1); }
void PIOC_IRQHandler (void) { while(1); }
void USART0_IRQHandler (void) { while(1); }
void USART1_IRQHandler (void) { while(1); }
void MCI_IRQHandler (void) { while(1); }
void TWI1_IRQHandler (void) { while(1); }
void SSC_IRQHandler (void) { while(1); }
void TC0_IRQHandler (void) { while(1); }
void TC1_IRQHandler (void) { while(1); }
void TC4_IRQHandler (void) { while(1); }
void TC5_IRQHandler (void) { while(1); }
void ADC_IRQHandler (void) { while(1); }
void CRCCU_IRQHandler (void) { while(1); }
void ACC_IRQHandler (void) { while(1); }
/*** EOF ***/
+338
View File
@@ -0,0 +1,338 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../../opentx.h"
#if defined(ROTARY_ENCODER_NAVIGATION)
#if defined(TELEMETREZ)
uint8_t TrotCount ; // TeZ version
uint8_t LastTrotCount ; // TeZ version
uint8_t RotEncoder ;
#define ROTENC_DOWN() (RotEncoder != 0)
#else
uint8_t RotPosition ;
int8_t LastRotaryValue ;
int8_t Rotary_diff ;
int8_t RotaryControl ;
uint8_t RotEncoder ;
#define ROTENC_DOWN() (RotEncoder & 0x20)
#endif
void rotencPoll()
{
#if defined(TELEMETREZ)
if (TrotCount != LastTrotCount) {
g_rotenc[0] = LastTrotCount = TrotCount ;
}
#else
// Rotary Encoder polling
PORTA = 0 ; // No pullups
DDRA = 0x1F ; // Top 3 bits input
asm(" rjmp 1f") ;
asm("1:") ;
uint8_t rotary ;
rotary = PINA ;
DDRA = 0xFF ; // Back to all outputs
rotary &= 0xE0 ;
RotEncoder = rotary ; // just read the lcd pin
rotary &= 0xDF ;
if ( rotary != RotPosition ) {
uint8_t x ;
x = RotPosition & 0x40 ;
x <<= 1 ;
x ^= rotary & 0x80 ;
if ( x ) {
g_rotenc[0] -= 1 ;
}
else {
g_rotenc[0] += 1 ;
}
RotPosition = rotary ;
}
#endif // TELEMETREZ
}
#else
#define ROTENC_DOWN() (0)
#endif // ROTARY_ENCODER_NAVIGATION
#ifndef SIMU
inline void boardInit()
{
// Set up I/O port data directions and initial states
DDRA = 0xff; PORTA = 0x00; // LCD data
DDRB = 0x81; PORTB = 0x7e; //pullups keys+nc
DDRC = 0x3e; PORTC = 0xc1; //pullups nc
DDRD = 0x00; PORTD = 0xff; //pullups keys
DDRE = (1<<OUT_E_BUZZER); PORTE = 0xff-(1<<OUT_E_BUZZER); //pullups + buzzer 0
DDRF = 0x00; PORTF = 0x00; //anain
DDRG = 0x14; PORTG = 0xfb; //pullups + SIM_CTL=1 = phonejack = ppm_in, Haptic output and off (0)
ADMUX = ADC_VREF_TYPE;
ADCSRA = 0x85; // ADC enabled, pre-scaler division=32 (no interrupt, no auto-triggering)
#if defined(CPUM2561)
TCCR2B = (0b111 << CS20); // Norm mode, clk/1024 (differs from ATmega64 chip)
OCR2A = 156;
TIMSK2 |= (1<<OCIE2A) | (1<<TOIE2); // Enable Output-Compare and Overflow interrrupts
#else
// TCNT0 10ms = 16MHz/1024/156 periodic timer (9.984ms)
// (with 1:4 duty at 157 to average 10.0ms)
// Timer overflows at about 61Hz or once every 16ms.
TCCR0 = (0b111 << CS00); // Norm mode, clk/1024
OCR0 = 156;
#endif
#if defined(AUDIO) || defined(VOICE)
SET_TIMER_AUDIO_CTRL();
#if defined(CPUM2561)
OCR4A = 0xFF;
RESUME_AUDIO_INTERRUPT();
#else
TIMSK |= (1<<OCIE0) | (1<<TOIE0) | (1<<TOIE2); // Enable Output-Compare and Overflow interrrupts
#endif
#elif defined(PWM_BACKLIGHT)
/** Smartieparts LED Backlight is connected to PORTB/pin7, which can be used as pwm output of timer2 **/
#if defined(SP22)
TCCR2 = (0b011 << CS20)|(1<<WGM20)|(1<<COM21)|(1<<COM20); // inv. pwm mode, clk/64
#else
TCCR2 = (0b011 << CS20)|(1<<WGM20)|(1<<COM21); // pwm mode, clk/64
#endif
#if !defined(CPUM2561)
TIMSK |= (1<<OCIE0) | (1<<TOIE0); // Enable Output-Compare and Overflow interrrupts
#endif
#else
#if !defined(CPUM2561)
TIMSK |= (1<<OCIE0) | (1<<TOIE0); // Enable Output-Compare and Overflow interrrupts
#endif
#endif
}
#endif
#ifndef SIMU
FORCEINLINE
#endif
uint8_t keyDown()
{
return ((~PINB) & 0x7E) | ROTENC_DOWN();
}
#if defined(TELEMETRY_MOD_14051)
extern uint8_t pf7_digital[2];
#define THR_STATE() pf7_digital[0]
#define AIL_STATE() pf7_digital[1]
#elif defined(JETI) || defined(FRSKY) || defined(ARDUPILOT) || defined(NMEA) || defined(MAVLINK)
#define THR_STATE() (PINC & (1<<INP_C_ThrCt))
#define AIL_STATE() (PINC & (1<<INP_C_AileDR))
#else
#define THR_STATE() (PINE & (1<<INP_E_ThrCt))
#define AIL_STATE() (PINE & (1<<INP_E_AileDR))
#endif
bool switchState(EnumKeys enuk)
{
uint8_t result = 0 ;
if (enuk < (int)DIM(keys))
return keys[enuk].state();
switch(enuk){
case SW_ELE:
result = PINE & (1<<INP_E_ElevDR);
break;
case SW_AIL:
result = AIL_STATE();
break;
case SW_RUD:
result = PING & (1<<INP_G_RuddDR);
break;
// INP_G_ID1 INP_E_ID2
// id0 0 1
// id1 1 1
// id2 1 0
case SW_ID0:
result = !(PING & (1<<INP_G_ID1));
break;
case SW_ID1:
result = (PING & (1<<INP_G_ID1)) && (PINE & (1<<INP_E_ID2));
break;
case SW_ID2:
result = !(PINE & (1<<INP_E_ID2));
break;
#if defined(EXTRA_3POS)
case SW_ID3:
result = (calibratedStick[POT1+EXTRA_3POS-1] < 0);
break;
case SW_ID4:
result = (calibratedStick[POT1+EXTRA_3POS-1] == 0);
break;
case SW_ID5:
result = (calibratedStick[POT1+EXTRA_3POS-1] > 0);
break;
#endif
case SW_GEA:
result = PINE & (1<<INP_E_Gear);
break;
case SW_THR:
result = THR_STATE();
break;
case SW_TRN:
result = PINE & (1<<INP_E_Trainer);
break;
default:
break;
}
return result;
}
#ifndef SIMU
FORCEINLINE
#endif
void readKeysAndTrims()
{
uint8_t enuk = KEY_MENU;
// User buttons ...
uint8_t in = ~PINB;
for(int i=1; i<7; i++)
{
//INP_B_KEY_MEN 1 .. INP_B_KEY_LFT 6
keys[enuk].input(in & (1<<i),(EnumKeys)enuk);
++enuk;
}
// Trim switches ...
static const pm_uchar crossTrim[] PROGMEM ={
1<<INP_D_TRM_LH_DWN, // bit 7
1<<INP_D_TRM_LH_UP,
1<<INP_D_TRM_LV_DWN,
1<<INP_D_TRM_LV_UP,
1<<INP_D_TRM_RV_DWN,
1<<INP_D_TRM_RV_UP,
1<<INP_D_TRM_RH_DWN,
1<<INP_D_TRM_RH_UP // bit 0
};
in = ~PIND;
for (int i=0; i<8; i++) {
// INP_D_TRM_RH_UP 0 .. INP_D_TRM_LH_UP 7
keys[enuk].input(in & pgm_read_byte(crossTrim+i), (EnumKeys)enuk);
++enuk;
}
#if defined(ROTARY_ENCODER_NAVIGATION)
keys[enuk].input(ROTENC_DOWN(), (EnumKeys)enuk); // Rotary Enc. Switch
#endif
#if defined(NAVIGATION_STICKS)
if (~PINB & 0x7E) {
StickScrollTimer = STICK_SCROLL_TIMEOUT ;
}
#endif
}
bool checkSlaveMode()
{
// no power -> only phone jack = slave mode
static bool lastSlaveMode = false;
static uint8_t checkDelay = 0;
if (IS_AUDIO_BUSY()) {
checkDelay = 20;
}
else if (checkDelay) {
--checkDelay;
}
else {
lastSlaveMode = (PING & (1<<INP_G_RF_POW));
}
return lastSlaveMode;
}
#if defined(PWM_BACKLIGHT)
// exponential PWM table for linear brightness
static const uint8_t pwmtable[16] PROGMEM =
{
0, 2, 3, 4, 6, 8, 11, 16, 23, 32, 45, 64, 90, 128, 181, 255
};
static uint8_t bl_target;
static uint8_t bl_current;
void backlightFadeOn()
{
bl_target = 15 - g_eeGeneral.blOnBright;
}
void backlightFadeOff()
{
bl_target = g_eeGeneral.blOffBright;
}
bool getBackLightState()
{
return (bl_target==g_eeGeneral.blOnBright);
}
void backlightFade() //called from per10ms()
{
if (bl_target != bl_current) {
if (bl_target > bl_current)
OCR2 = pgm_read_byte(&pwmtable[++bl_current]);
else
OCR2 = pgm_read_byte(&pwmtable[--bl_current]);
}
}
#endif
+236
View File
@@ -0,0 +1,236 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef board_stock_h
#define board_stock_h
#define GPIO_BUTTON_MENU pinb
#define GPIO_BUTTON_EXIT pinb
#define GPIO_BUTTON_RIGHT pinb
#define GPIO_BUTTON_LEFT pinb
#define GPIO_BUTTON_UP pinb
#define GPIO_BUTTON_DOWN pinb
#define PIN_BUTTON_MENU (1<<INP_B_KEY_MEN)
#define PIN_BUTTON_EXIT (1<<INP_B_KEY_EXT)
#define PIN_BUTTON_UP (1<<INP_B_KEY_UP)
#define PIN_BUTTON_DOWN (1<<INP_B_KEY_DWN)
#define PIN_BUTTON_RIGHT (1<<INP_B_KEY_RGT)
#define PIN_BUTTON_LEFT (1<<INP_B_KEY_LFT)
#define GPIO_TRIM_LH_L pind
#define GPIO_TRIM_LV_DN pind
#define GPIO_TRIM_RV_UP pind
#define GPIO_TRIM_RH_L pind
#define GPIO_TRIM_LH_R pind
#define GPIO_TRIM_LV_UP pind
#define GPIO_TRIM_RV_DN pind
#define GPIO_TRIM_RH_R pind
#define PIN_TRIM_LH_L (1<<INP_D_TRM_LH_DWN)
#define PIN_TRIM_LV_DN (1<<INP_D_TRM_LV_DWN)
#define PIN_TRIM_RV_UP (1<<INP_D_TRM_RV_UP)
#define PIN_TRIM_RH_L (1<<INP_D_TRM_RH_DWN)
#define PIN_TRIM_LH_R (1<<INP_D_TRM_LH_UP)
#define PIN_TRIM_LV_UP (1<<INP_D_TRM_LV_UP)
#define PIN_TRIM_RV_DN (1<<INP_D_TRM_RV_DWN)
#define PIN_TRIM_RH_R (1<<INP_D_TRM_RH_UP)
#if defined(CPUM2561)
#define TIMER_16KHZ_VECT TIMER2_OVF_vect
#define COUNTER_16KHZ TCNT2
#define TIMER_10MS_VECT TIMER2_COMPA_vect
#define TIMER_10MS_COMPVAL OCR2A
#define PAUSE_10MS_INTERRUPT() TIMSK2 &= ~(1<<OCIE2A)
#define RESUME_10MS_INTERRUPT() TIMSK2 |= (1<<OCIE2A)
#define PAUSE_PPMIN_INTERRUPT() TIMSK3 &= ~(1<<ICIE3)
#define RESUME_PPMIN_INTERRUPT() TIMSK3 |= (1<<ICIE3)
#define TIMER_AUDIO_VECT TIMER4_COMPA_vect
#define SET_TIMER_AUDIO_CTRL() TCCR4B = (1 << WGM42) | (0b010 << CS40)
#define PAUSE_AUDIO_INTERRUPT() TIMSK4 &= ~(1<<OCIE4A)
#define RESUME_AUDIO_INTERRUPT() TIMSK4 |= (1<<OCIE4A)
#else
#define TIMER_16KHZ_VECT TIMER0_OVF_vect
#define COUNTER_16KHZ TCNT0
#define TIMER_10MS_VECT TIMER0_COMP_vect
#define TIMER_10MS_COMPVAL OCR0
#define PAUSE_10MS_INTERRUPT() TIMSK &= ~(1<<OCIE0)
#define RESUME_10MS_INTERRUPT() TIMSK |= (1<<OCIE0)
#define PAUSE_PPMIN_INTERRUPT() ETIMSK &= ~(1<<TICIE3)
#define RESUME_PPMIN_INTERRUPT() ETIMSK |= (1<<TICIE3)
#define TIMER_AUDIO_VECT TIMER2_OVF_vect
#define SET_TIMER_AUDIO_CTRL() TCCR2 = (0b010 << CS00) // Norm mode, clk/8
#define PAUSE_AUDIO_INTERRUPT() TIMSK &= ~(1<<TOIE2)
#define RESUME_AUDIO_INTERRUPT() TIMSK |= (1<<TOIE2)
#endif
// Power driver (none)
#define pwrCheck() (e_power_on)
#define pwrOff()
#define UNEXPECTED_SHUTDOWN() (mcusr & (1 << WDRF))
// Trainer driver
bool checkSlaveMode();
#define SLAVE_MODE() checkSlaveMode()
#define JACK_PPM_OUT() PORTG &= ~(1<<OUT_G_SIM_CTL)
#define JACK_PPM_IN() PORTG |= (1<<OUT_G_SIM_CTL)
// PWM Backlight driver
#if defined(PWM_BACKLIGHT)
void backlightFadeOn();
#define __BACKLIGHT_ON backlightFadeOn()
void backlightFadeOff();
#define __BACKLIGHT_OFF backlightFadeOff()
bool getBackLightState();
#define IS_BACKLIGHT_ON() getBackLightState()
void backlightFade();
#else
#if defined(SP22)
#define __BACKLIGHT_ON PORTB &= ~(1 << OUT_B_LIGHT)
#define __BACKLIGHT_OFF PORTB |= (1 << OUT_B_LIGHT)
#define IS_BACKLIGHT_ON() (~PORTB & (1<<OUT_B_LIGHT))
#else
#define __BACKLIGHT_ON PORTB |= (1 << OUT_B_LIGHT)
#define __BACKLIGHT_OFF PORTB &= ~(1 << OUT_B_LIGHT)
#define IS_BACKLIGHT_ON() (PORTB & (1<<OUT_B_LIGHT))
#endif
#endif
// G: The following comments relate to the original stock PCB only
//
// elev thr
// LV RV
// 2 ^ 4 ^
// 1 2
// | rudd | aile
// <----X--3-> LH <----X--0-> RH
// 6 | 7 1 | 0
// | |
// 3 v 5 v
//
//PORTA 7 6 5 4 3 2 1 0
// O O O O O O O O
// ------------------------ LCD_DAT -----------------------
//
//PORTB 7 6 5 4 3 2 1 0
// O i i i i i i O
// light KEY_LFT KEY_RGT KEY_UP KEY_DWN KEY_EXT KEY_MEN PPM
//
//PORTC 7 6 5 4 3 2 1 0
// - - O O O O O -
// NC NC LCD_E LCD_RNW LCD_A0 LCD_RES LCD_CS1 NC
//
//PORTD 7 6 5 4 3 2 1 0
// i i i i i i i i
// TRM_D_DWN _UP TRM_C_DWN _UP TRM_B_DWN _UP TRM_A_DWN _UP
//
//PORTE 7 6 5 4 3 2 1 0
// i i i i O i i i
// PPM_IN ID2 Trainer Gear Buzzer ElevDR AileDR THRCT
//
//PORTF 7 6 5 4 3 2 1 0
// ai ai ai ai ai ai ai ai
// ANA_ BAT PITT_TRM HOV_THR HOV_PIT STCK_LH STCK_RV STCK_LV STCK_RH
// rud thro elev aile
//PORTG 7 6 5 4 3 2 1 0
// - - - O i i i
// SIM_CTL ID1 Haptic RF_POW RuddDR
#define OUT_B_LIGHT 7
#define INP_B_KEY_LFT 6
#define INP_B_KEY_RGT 5
#define INP_B_KEY_UP 4
#define INP_B_KEY_DWN 3
#define INP_B_KEY_EXT 2
#define INP_B_KEY_MEN 1
#define OUT_B_PPM 0
#define INP_D_TRM_LH_UP 7
#define INP_D_TRM_LH_DWN 6
#define INP_D_TRM_RV_DWN 5
#define INP_D_TRM_RV_UP 4
#define INP_D_TRM_LV_DWN 3
#define INP_D_TRM_LV_UP 2
#define INP_D_TRM_RH_DWN 1
#define INP_D_TRM_RH_UP 0
#define INP_E_PPM_IN 7
#define INP_E_ID2 6
#define INP_E_Trainer 5
#define INP_E_Gear 4
#define OUT_E_BUZZER 3
#define INP_E_ElevDR 2
#if defined(JETI) || defined(FRSKY) || defined(ARDUPILOT) || defined(NMEA) || defined(MAVLINK)
#define INP_C_ThrCt 6
#define INP_C_AileDR 7
#else
#define INP_E_ThrCt 0
#define INP_E_AileDR 1
#endif
#define OUT_G_SIM_CTL 4 //1 : phone-jack=ppm_in
#define INP_G_ID1 3
#define OUT_G_HAPTIC 2
#define INP_G_RF_POW 1
#define INP_G_RuddDR 0
// Keys driver
#define TRIMS_PRESSED() (~PIND)
#define KEYS_PRESSED() (~PINB)
#define DBLKEYS_PRESSED_RGT_LFT(i) ((in & ((1<<INP_B_KEY_RGT) + (1<<INP_B_KEY_LFT))) == ((1<<INP_B_KEY_RGT) + (1<<INP_B_KEY_LFT)))
#define DBLKEYS_PRESSED_UP_DWN(i) ((in & ((1<<INP_B_KEY_UP) + (1<<INP_B_KEY_DWN))) == ((1<<INP_B_KEY_UP) + (1<<INP_B_KEY_DWN)))
#define DBLKEYS_PRESSED_RGT_UP(i) ((in & ((1<<INP_B_KEY_RGT) + (1<<INP_B_KEY_UP))) == ((1<<INP_B_KEY_RGT) + (1<<INP_B_KEY_UP)))
#define DBLKEYS_PRESSED_LFT_DWN(i) ((in & ((1<<INP_B_KEY_LFT) + (1<<INP_B_KEY_DWN))) == ((1<<INP_B_KEY_LFT) + (1<<INP_B_KEY_DWN)))
// LCD driver
#define PORTA_LCD_DAT PORTA
#define PORTC_LCD_CTRL PORTC
#define OUT_C_LCD_E 5
#define OUT_C_LCD_RnW 4
#define OUT_C_LCD_A0 3
#define OUT_C_LCD_RES 2
#define OUT_C_LCD_CS1 1
// Rotary encoder driver
#if defined(ROTARY_ENCODER_NAVIGATION)
extern uint8_t RotEncoder ;
void rotencPoll();
#endif
// USB fake driver
#define usbPlugged() false
#endif
+138
View File
@@ -0,0 +1,138 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "opentx.h"
#define delay_1us() _delay_us(1)
#define delay_2us() _delay_us(2)
void delay_1_5us(uint16_t ms)
{
for (uint16_t i=0; i<ms; i++) delay_1us();
}
void lcdSendCtl(uint8_t val)
{
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
#ifdef LCD_MULTIPLEX
DDRA = 0xFF; // set LCD_DAT pins to output
#endif
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_A0);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
PORTA_LCD_DAT = val;
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_E);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0);
#ifdef LCD_MULTIPLEX
DDRA = 0x00; // set LCD_DAT pins to input
#endif
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS1);
}
#if defined(PCBSTD) && defined(VOICE)
volatile uint8_t LcdLock ;
#define LCD_LOCK() LcdLock = 1
#define LCD_UNLOCK() LcdLock = 0
#else
#define LCD_LOCK()
#define LCD_UNLOCK()
#endif
const static pm_uchar lcdInitSequence[] PROGMEM =
{
0xe2, //Initialize the internal functions
0xae, //DON = 0: display OFF
0xa1, //ADC = 1: reverse direction(SEG132->SEG1)
0xA6, //REV = 0: non-reverse display
0xA4, //EON = 0: normal display. non-entire
0xA2, // Select LCD bias=0
0xC0, //SHL = 0: normal direction (COM1->COM64)
0x2F, //Control power circuit operation VC=VR=VF=1
0x25, //Select int resistance ratio R2 R1 R0 =5
0x81, //Set reference voltage Mode
0x22, // 24 SV5 SV4 SV3 SV2 SV1 SV0 = 0x18
0xAF //DON = 1: display ON
};
inline void lcdInit()
{
// /home/thus/txt/datasheets/lcd/KS0713.pdf
// ~/txt/flieger/ST7565RV17.pdf from http://www.glyn.de/content.asp?wdid=132&sid=
LCD_LOCK();
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES); //LCD_RES
delay_2us();
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); // f524 sbi 0x15, 2 IOADR-PORTC_LCD_CTRL; 21 1
delay_1_5us(1500);
for (uint8_t i=0; i<12; i++) {
lcdSendCtl(pgm_read_byte(&lcdInitSequence[i])) ;
}
g_eeGeneral.contrast = 0x22;
LCD_UNLOCK();
}
void lcdSetRefVolt(uint8_t val)
{
LCD_LOCK();
lcdSendCtl(0x81);
lcdSendCtl(val);
LCD_UNLOCK();
}
void lcdRefresh()
{
LCD_LOCK();
uint8_t *p=displayBuf;
for(uint8_t y=0; y < 8; y++) {
lcdSendCtl(0x04);
lcdSendCtl(0x10); //column addr 0
lcdSendCtl( y | 0xB0); //page addr y
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
#ifdef LCD_MULTIPLEX
DDRA = 0xFF; // set LCD_DAT pins to output
#endif
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
for (xcoord_t x=LCD_W; x>0; --x) {
PORTA_LCD_DAT = *p++;
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_E);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
}
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0);
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS1);
}
LCD_UNLOCK();
}
+155
View File
@@ -0,0 +1,155 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "../../opentx.h"
struct t_voice Voice ;
void pushPrompt(uint16_t value)
{
#ifdef SIMU
printf("playFile(\"%04d.ad4\")\n", value); fflush(stdout);
#endif
struct t_voice *vptr;
vptr = voiceaddress();
if (vptr->VoiceQueueCount < VOICE_Q_LENGTH) {
vptr->VoiceQueue[vptr->VoiceQueueInIndex++] = value;
vptr->VoiceQueueInIndex &= (VOICE_Q_LENGTH - 1);
vptr->VoiceQueueCount += 1;
}
}
void pushCustomPrompt(uint8_t value)
{
pushPrompt(PROMPT_CUSTOM_BASE + value);
}
void pushNumberPrompt(uint8_t value)
{
pushPrompt(PROMPT_I18N_BASE + value);
}
struct t_voice *voiceaddress()
{
return &Voice ;
}
void t_voice::voice_process(void)
{
if (Backlight)
VoiceLatch |= BACKLIGHT_BIT;
else
VoiceLatch &= ~BACKLIGHT_BIT;
if (VoiceState == V_IDLE) {
PORTB |= (1 << OUT_B_LIGHT); // Latch clock high
if (VoiceQueueCount) {
VoiceSerial = VoiceQueue[VoiceQueueOutIndex++];
VoiceQueueOutIndex &= (VOICE_Q_LENGTH - 1);
VoiceQueueCount -= 1;
VoiceTimer = 17;
if (VoiceSerial & 0x8000) { // Looking for sound volume 1F0-1F7
VoiceTimer = 40;
}
VoiceLatch &= ~VOICE_CLOCK_BIT & ~VOICE_DATA_BIT ;
if (VoiceSerial & 0x8000) {
VoiceLatch |= VOICE_DATA_BIT;
}
PORTA_LCD_DAT = VoiceLatch ; // Latch data set
PORTB &= ~(1<<OUT_B_LIGHT) ; // Latch clock low
VoiceCounter = 31;
VoiceState = V_CLOCKING;
}
else {
PORTA_LCD_DAT = VoiceLatch; // Latch data set
PORTB &= ~(1 << OUT_B_LIGHT); // Latch clock low
}
}
else if (VoiceState == V_STARTUP) {
PORTB |= (1<<OUT_B_LIGHT) ; // Latch clock high
VoiceLatch |= VOICE_CLOCK_BIT | VOICE_DATA_BIT ;
PORTA_LCD_DAT = VoiceLatch ; // Latch data set
if (g_blinkTmr10ms > 60) { // Give module 1.4 secs to initialise
VoiceState = V_WAIT_START_BUSY_OFF ;
}
PORTB &= ~(1<<OUT_B_LIGHT) ; // Latch clock low
}
else if (VoiceState != V_CLOCKING) {
uint8_t busy;
PORTA_LCD_DAT = VoiceLatch; // Latch data set
PORTB |= (1 << OUT_B_LIGHT); // Drive high,pullup enabled
DDRB &= ~(1 << OUT_B_LIGHT); // Change to input
// delay to allow input to settle
asm(" rjmp 1f");
asm("1:");
asm(" nop");
asm(" rjmp 1f");
asm("1:");
busy = PINB & 0x80;
DDRB |= (1 << OUT_B_LIGHT); // Change to output
// The next bit guarantees the backlight output gets clocked out
if (VoiceState == V_WAIT_BUSY_ON) { // check for busy processing here
if (busy == 0) { // Busy is active
VoiceState = V_WAIT_BUSY_OFF;
}
else {
if (--VoiceTimer == 0) {
VoiceState = V_WAIT_BUSY_OFF;
}
}
}
else if (VoiceState == V_WAIT_BUSY_OFF) { // check for busy processing here
if (busy) { // Busy is inactive
VoiceTimer = 3;
VoiceState = V_WAIT_BUSY_DELAY;
}
}
else if (VoiceState == V_WAIT_BUSY_DELAY) {
if (--VoiceTimer == 0) {
VoiceState = V_IDLE;
}
}
else if (VoiceState == V_WAIT_START_BUSY_OFF) { // check for busy processing here
if (busy) { // Busy is inactive
VoiceTimer = 20 ;
VoiceState = V_WAIT_BUSY_DELAY ;
}
}
PORTB &= ~(1 << OUT_B_LIGHT); // Latch clock low
}
}
+139
View File
@@ -0,0 +1,139 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - Thomas Husterer
*
* opentx is based on code named
* gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/,
* er9x by Erez Raviv: http://code.google.com/p/er9x/,
* and the original (and ongoing) project by
* Thomas Husterer, th9x: http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
// Bits in VoiceLatch
#define VOICE_CLOCK_BIT 0x01
#define VOICE_DATA_BIT 0x02
#define BACKLIGHT_BIT 0x04
#define SPARE_BIT 0x08
#if defined(CPUM64)
#define VOICE_Q_LENGTH 8
#else
#define VOICE_Q_LENGTH 16
#endif
// Voice states
#define V_STARTUP 0
#define V_IDLE 1
#define V_CLOCKING 2
#define V_WAIT_BUSY_ON 3
#define V_WAIT_BUSY_OFF 4
#define V_WAIT_BUSY_DELAY 5
#define V_WAIT_START_BUSY_OFF 6
#define PROMPT_CUSTOM_BASE 0
#define PROMPT_I18N_BASE 256
#define PROMPT_SYSTEM_BASE 480
struct t_voice
{
uint16_t VoiceQueue[VOICE_Q_LENGTH] ;
uint8_t Backlight ;
uint8_t VoiceLatch ;
uint8_t VoiceCounter ;
uint8_t VoiceTimer ;
uint16_t VoiceSerial ;
uint8_t VoiceState ;
uint8_t VoiceQueueCount ;
uint8_t VoiceQueueInIndex ;
uint8_t VoiceQueueOutIndex ;
void voice_process( void ) ;
};
extern void pushPrompt(uint16_t value);
extern void pushCustomPrompt(uint8_t value);
extern void pushNumberPrompt(uint8_t value);
extern struct t_voice *voiceaddress( void ) ;
extern struct t_voice Voice ;
#define VOLUME_LEVEL_MAX 7
#define VOLUME_LEVEL_DEF 7
#define setVolume(v) pushPrompt((v) | 0xFFF0)
inline bool isPlaying()
{
#if defined(SIMU)
return false;
#else
return Voice.VoiceState != V_IDLE;
#endif
}
/*
* Handle the Voice output
* Check for LcdLocked (in interrupt), and voice_enabled
*/
#define VOICE_DRIVER() \
if ( LcdLock == 0 ) { /* LCD not in use */ \
struct t_voice *vptr; \
vptr = voiceaddress(); \
if ( vptr->VoiceState == V_CLOCKING ) { \
if ( vptr->VoiceTimer ) { \
vptr->VoiceTimer -= 1; \
} \
else { \
PORTB |= (1<<OUT_B_LIGHT); /* Latch clock high */ \
if ((vptr->VoiceCounter & 1) == 0) { \
vptr->VoiceLatch &= ~VOICE_DATA_BIT; \
if ( vptr->VoiceSerial & 0x4000 ) { \
vptr->VoiceLatch |= VOICE_DATA_BIT; \
} \
vptr->VoiceSerial <<= 1; \
} \
vptr->VoiceLatch ^= VOICE_CLOCK_BIT; \
PORTA_LCD_DAT = vptr->VoiceLatch; /* Latch data set */ \
PORTB &= ~(1<<OUT_B_LIGHT); /* Latch clock low */ \
if ( --vptr->VoiceCounter == 0 ) { \
vptr->VoiceState = V_WAIT_BUSY_ON; \
vptr->VoiceTimer = 5; /* 50 mS */ \
} \
} \
} \
}
#define I18N_PLAY_FUNCTION(lng, x, ...) void x(__VA_ARGS__)
#define PLAY_FUNCTION(x, ...) void x(__VA_ARGS__)
#define PUSH_CUSTOM_PROMPT(p, ...) pushCustomPrompt((p))
#define PUSH_NUMBER_PROMPT(p) pushNumberPrompt((p))
#define PUSH_SYSTEM_PROMPT(p) pushNumberPrompt(PROMPT_SYSTEM_BASE-PROMPT_I18N_BASE+(p))
#define PLAY_NUMBER(n, u, a) playNumber((n), (u), (a))
#define PLAY_DURATION(d) playDuration((d))
#define IS_PLAYING(id) (0) /* isPlaying() */
#define PLAY_VALUE(v, id) playValue((v))
@@ -0,0 +1,105 @@
/**
******************************************************************************
* @file system_stm32f2xx.h
* @author MCD Application Team
* @version V1.1.3
* @date 05-March-2012
* @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Header File.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2012 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/** @addtogroup CMSIS
* @{
*/
/** @addtogroup stm32f2xx_system
* @{
*/
/**
* @brief Define to prevent recursive inclusion
*/
#ifndef __SYSTEM_STM32F2XX_H
#define __SYSTEM_STM32F2XX_H
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup STM32F2xx_System_Includes
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F2xx_System_Exported_types
* @{
*/
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
/**
* @}
*/
/** @addtogroup STM32F2xx_System_Exported_Constants
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F2xx_System_Exported_Macros
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F2xx_System_Exported_Functions
* @{
*/
extern void SystemInit(void);
extern void SystemCoreClockUpdate(void);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /*__SYSTEM_STM32F2XX_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
@@ -0,0 +1,512 @@
/**
******************************************************************************
* @file startup_stm32f2xx.s
* @author MCD Application Team
* @version V1.1.3
* @date 05-March-2012
* @brief STM32F2xx Devices vector table for RIDE7 toolchain.
* This module performs:
* - Set the initial SP
* - Set the initial PC == Reset_Handler,
* - Set the vector table entries with the exceptions ISR address
* - Configure the system clock and the external SRAM mounted on
* STM322xG-EVAL board to be used as data memory (optional,
* to be enabled by user)
* - Branches to main in the C library (which eventually
* calls main()).
* After Reset the Cortex-M3 processor is in Thread mode,
* priority is Privileged, and the Stack is set to Main.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2012 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
.syntax unified
.cpu cortex-m3
.fpu softvfp
.thumb
.global g_pfnVectors
.global Default_Handler
/* start address for the initialization values of the .data section.
defined in linker script */
.word _sidata
/* start address for the .data section. defined in linker script */
.word _sdata
/* end address for the .data section. defined in linker script */
.word _edata
/* start address for the .bss section. defined in linker script */
.word _sbss
/* end address for the .bss section. defined in linker script */
.word _ebss
/* stack used for SystemInit_ExtMemCtl; always internal RAM used */
/**
* @brief This is the code that gets called when the processor first
* starts execution following a reset event. Only the absolutely
* necessary set is performed, after which the application
* supplied main() routine is called.
* @param None
* @retval : None
*/
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
/* Copy the data segment initializers from flash to SRAM */
movs r1, #0
b LoopCopyDataInit
CopyDataInit:
ldr r3, =_sidata
ldr r3, [r3, r1]
str r3, [r0, r1]
adds r1, r1, #4
LoopCopyDataInit:
ldr r0, =_sdata
ldr r3, =_edata
adds r2, r0, r1
cmp r2, r3
bcc CopyDataInit
ldr r2, =_sbss
b LoopFillZerobss
/* Zero fill the bss segment. */
FillZerobss:
movs r3, #0
str r3, [r2], #4
LoopFillZerobss:
ldr r3, = _ebss
cmp r2, r3
bcc FillZerobss
/* Call the clock system intitialization function.*/
bl SystemInit
/* Call the application's entry point.*/
bl main
bx lr
.size Reset_Handler, .-Reset_Handler
/**
* @brief This is the code that gets called when the processor receives an
* unexpected interrupt. This simply enters an infinite loop, preserving
* the system state for examination by a debugger.
* @param None
* @retval None
*/
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
b Infinite_Loop
.size Default_Handler, .-Default_Handler
/******************************************************************************
*
* The minimal vector table for a Cortex M3. Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
*******************************************************************************/
.section .isr_vector,"a",%progbits
.type g_pfnVectors, %object
.size g_pfnVectors, .-g_pfnVectors
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word DebugMon_Handler
.word 0
.word PendSV_Handler
.word SysTick_Handler
/* External Interrupts */
.word WWDG_IRQHandler /* Window WatchDog */
.word PVD_IRQHandler /* PVD through EXTI Line detection */
.word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXTI line */
.word RTC_WKUP_IRQHandler /* RTC Wakeup through the EXTI line */
.word FLASH_IRQHandler /* FLASH */
.word RCC_IRQHandler /* RCC */
.word EXTI0_IRQHandler /* EXTI Line0 */
.word EXTI1_IRQHandler /* EXTI Line1 */
.word EXTI2_IRQHandler /* EXTI Line2 */
.word EXTI3_IRQHandler /* EXTI Line3 */
.word EXTI4_IRQHandler /* EXTI Line4 */
.word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */
.word DMA1_Stream1_IRQHandler /* DMA1 Stream 1 */
.word DMA1_Stream2_IRQHandler /* DMA1 Stream 2 */
.word DMA1_Stream3_IRQHandler /* DMA1 Stream 3 */
.word DMA1_Stream4_IRQHandler /* DMA1 Stream 4 */
.word DMA1_Stream5_IRQHandler /* DMA1 Stream 5 */
.word DMA1_Stream6_IRQHandler /* DMA1 Stream 6 */
.word ADC_IRQHandler /* ADC1, ADC2 and ADC3s */
.word CAN1_TX_IRQHandler /* CAN1 TX */
.word CAN1_RX0_IRQHandler /* CAN1 RX0 */
.word CAN1_RX1_IRQHandler /* CAN1 RX1 */
.word CAN1_SCE_IRQHandler /* CAN1 SCE */
.word EXTI9_5_IRQHandler /* External Line[9:5]s */
.word TIM1_BRK_TIM9_IRQHandler /* TIM1 Break and TIM9 */
.word TIM1_UP_TIM10_IRQHandler /* TIM1 Update and TIM10 */
.word TIM1_TRG_COM_TIM11_IRQHandler /* TIM1 Trigger and Commutation and TIM11 */
.word TIM1_CC_IRQHandler /* TIM1 Capture Compare */
.word TIM2_IRQHandler /* TIM2 */
.word TIM3_IRQHandler /* TIM3 */
.word TIM4_IRQHandler /* TIM4 */
.word I2C1_EV_IRQHandler /* I2C1 Event */
.word I2C1_ER_IRQHandler /* I2C1 Error */
.word I2C2_EV_IRQHandler /* I2C2 Event */
.word I2C2_ER_IRQHandler /* I2C2 Error */
.word SPI1_IRQHandler /* SPI1 */
.word SPI2_IRQHandler /* SPI2 */
.word USART1_IRQHandler /* USART1 */
.word USART2_IRQHandler /* USART2 */
.word USART3_IRQHandler /* USART3 */
.word EXTI15_10_IRQHandler /* External Line[15:10]s */
.word RTC_Alarm_IRQHandler /* RTC Alarm (A and B) through EXTI Line */
.word OTG_FS_WKUP_IRQHandler /* USB OTG FS Wakeup through EXTI line */
.word TIM8_BRK_TIM12_IRQHandler /* TIM8 Break and TIM12 */
.word TIM8_UP_TIM13_IRQHandler /* TIM8 Update and TIM13 */
.word TIM8_TRG_COM_TIM14_IRQHandler /* TIM8 Trigger and Commutation and TIM14 */
.word TIM8_CC_IRQHandler /* TIM8 Capture Compare */
.word DMA1_Stream7_IRQHandler /* DMA1 Stream7 */
.word FSMC_IRQHandler /* FSMC */
.word SDIO_IRQHandler /* SDIO */
.word TIM5_IRQHandler /* TIM5 */
.word SPI3_IRQHandler /* SPI3 */
.word UART4_IRQHandler /* UART4 */
.word UART5_IRQHandler /* UART5 */
.word TIM6_DAC_IRQHandler /* TIM6 and DAC1&2 underrun errors */
.word TIM7_IRQHandler /* TIM7 */
.word DMA2_Stream0_IRQHandler /* DMA2 Stream 0 */
.word DMA2_Stream1_IRQHandler /* DMA2 Stream 1 */
.word DMA2_Stream2_IRQHandler /* DMA2 Stream 2 */
.word DMA2_Stream3_IRQHandler /* DMA2 Stream 3 */
.word DMA2_Stream4_IRQHandler /* DMA2 Stream 4 */
.word ETH_IRQHandler /* Ethernet */
.word ETH_WKUP_IRQHandler /* Ethernet Wakeup through EXTI line */
.word CAN2_TX_IRQHandler /* CAN2 TX */
.word CAN2_RX0_IRQHandler /* CAN2 RX0 */
.word CAN2_RX1_IRQHandler /* CAN2 RX1 */
.word CAN2_SCE_IRQHandler /* CAN2 SCE */
.word OTG_FS_IRQHandler /* USB OTG FS */
.word DMA2_Stream5_IRQHandler /* DMA2 Stream 5 */
.word DMA2_Stream6_IRQHandler /* DMA2 Stream 6 */
.word DMA2_Stream7_IRQHandler /* DMA2 Stream 7 */
.word USART6_IRQHandler /* USART6 */
.word I2C3_EV_IRQHandler /* I2C3 event */
.word I2C3_ER_IRQHandler /* I2C3 error */
.word OTG_HS_EP1_OUT_IRQHandler /* USB OTG HS End Point 1 Out */
.word OTG_HS_EP1_IN_IRQHandler /* USB OTG HS End Point 1 In */
.word OTG_HS_WKUP_IRQHandler /* USB OTG HS Wakeup through EXTI */
.word OTG_HS_IRQHandler /* USB OTG HS */
.word DCMI_IRQHandler /* DCMI */
.word CRYP_IRQHandler /* CRYP crypto */
.word HASH_RNG_IRQHandler /* Hash and Rng */
/*******************************************************************************
*
* Provide weak aliases for each Exception handler to the Default_Handler.
* As they are weak aliases, any function with the same name will override
* this definition.
*
*******************************************************************************/
.weak NMI_Handler
.thumb_set NMI_Handler,Default_Handler
.weak HardFault_Handler
.thumb_set HardFault_Handler,Default_Handler
.weak MemManage_Handler
.thumb_set MemManage_Handler,Default_Handler
.weak BusFault_Handler
.thumb_set BusFault_Handler,Default_Handler
.weak UsageFault_Handler
.thumb_set UsageFault_Handler,Default_Handler
.weak SVC_Handler
.thumb_set SVC_Handler,Default_Handler
.weak DebugMon_Handler
.thumb_set DebugMon_Handler,Default_Handler
.weak PendSV_Handler
.thumb_set PendSV_Handler,Default_Handler
.weak SysTick_Handler
.thumb_set SysTick_Handler,Default_Handler
.weak WWDG_IRQHandler
.thumb_set WWDG_IRQHandler,Default_Handler
.weak PVD_IRQHandler
.thumb_set PVD_IRQHandler,Default_Handler
.weak TAMP_STAMP_IRQHandler
.thumb_set TAMP_STAMP_IRQHandler,Default_Handler
.weak RTC_WKUP_IRQHandler
.thumb_set RTC_WKUP_IRQHandler,Default_Handler
.weak FLASH_IRQHandler
.thumb_set FLASH_IRQHandler,Default_Handler
.weak RCC_IRQHandler
.thumb_set RCC_IRQHandler,Default_Handler
.weak EXTI0_IRQHandler
.thumb_set EXTI0_IRQHandler,Default_Handler
.weak EXTI1_IRQHandler
.thumb_set EXTI1_IRQHandler,Default_Handler
.weak EXTI2_IRQHandler
.thumb_set EXTI2_IRQHandler,Default_Handler
.weak EXTI3_IRQHandler
.thumb_set EXTI3_IRQHandler,Default_Handler
.weak EXTI4_IRQHandler
.thumb_set EXTI4_IRQHandler,Default_Handler
.weak DMA1_Stream0_IRQHandler
.thumb_set DMA1_Stream0_IRQHandler,Default_Handler
.weak DMA1_Stream1_IRQHandler
.thumb_set DMA1_Stream1_IRQHandler,Default_Handler
.weak DMA1_Stream2_IRQHandler
.thumb_set DMA1_Stream2_IRQHandler,Default_Handler
.weak DMA1_Stream3_IRQHandler
.thumb_set DMA1_Stream3_IRQHandler,Default_Handler
.weak DMA1_Stream4_IRQHandler
.thumb_set DMA1_Stream4_IRQHandler,Default_Handler
.weak DMA1_Stream5_IRQHandler
.thumb_set DMA1_Stream5_IRQHandler,Default_Handler
.weak DMA1_Stream6_IRQHandler
.thumb_set DMA1_Stream6_IRQHandler,Default_Handler
.weak ADC_IRQHandler
.thumb_set ADC_IRQHandler,Default_Handler
.weak CAN1_TX_IRQHandler
.thumb_set CAN1_TX_IRQHandler,Default_Handler
.weak CAN1_RX0_IRQHandler
.thumb_set CAN1_RX0_IRQHandler,Default_Handler
.weak CAN1_RX1_IRQHandler
.thumb_set CAN1_RX1_IRQHandler,Default_Handler
.weak CAN1_SCE_IRQHandler
.thumb_set CAN1_SCE_IRQHandler,Default_Handler
.weak EXTI9_5_IRQHandler
.thumb_set EXTI9_5_IRQHandler,Default_Handler
.weak TIM1_BRK_TIM9_IRQHandler
.thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler
.weak TIM1_UP_TIM10_IRQHandler
.thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler
.weak TIM1_TRG_COM_TIM11_IRQHandler
.thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler
.weak TIM1_CC_IRQHandler
.thumb_set TIM1_CC_IRQHandler,Default_Handler
.weak TIM2_IRQHandler
.thumb_set TIM2_IRQHandler,Default_Handler
.weak TIM3_IRQHandler
.thumb_set TIM3_IRQHandler,Default_Handler
.weak TIM4_IRQHandler
.thumb_set TIM4_IRQHandler,Default_Handler
.weak I2C1_EV_IRQHandler
.thumb_set I2C1_EV_IRQHandler,Default_Handler
.weak I2C1_ER_IRQHandler
.thumb_set I2C1_ER_IRQHandler,Default_Handler
.weak I2C2_EV_IRQHandler
.thumb_set I2C2_EV_IRQHandler,Default_Handler
.weak I2C2_ER_IRQHandler
.thumb_set I2C2_ER_IRQHandler,Default_Handler
.weak SPI1_IRQHandler
.thumb_set SPI1_IRQHandler,Default_Handler
.weak SPI2_IRQHandler
.thumb_set SPI2_IRQHandler,Default_Handler
.weak USART1_IRQHandler
.thumb_set USART1_IRQHandler,Default_Handler
.weak USART2_IRQHandler
.thumb_set USART2_IRQHandler,Default_Handler
.weak USART3_IRQHandler
.thumb_set USART3_IRQHandler,Default_Handler
.weak EXTI15_10_IRQHandler
.thumb_set EXTI15_10_IRQHandler,Default_Handler
.weak RTC_Alarm_IRQHandler
.thumb_set RTC_Alarm_IRQHandler,Default_Handler
.weak OTG_FS_WKUP_IRQHandler
.thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler
.weak TIM8_BRK_TIM12_IRQHandler
.thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler
.weak TIM8_UP_TIM13_IRQHandler
.thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler
.weak TIM8_TRG_COM_TIM14_IRQHandler
.thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler
.weak TIM8_CC_IRQHandler
.thumb_set TIM8_CC_IRQHandler,Default_Handler
.weak DMA1_Stream7_IRQHandler
.thumb_set DMA1_Stream7_IRQHandler,Default_Handler
.weak FSMC_IRQHandler
.thumb_set FSMC_IRQHandler,Default_Handler
.weak SDIO_IRQHandler
.thumb_set SDIO_IRQHandler,Default_Handler
.weak TIM5_IRQHandler
.thumb_set TIM5_IRQHandler,Default_Handler
.weak SPI3_IRQHandler
.thumb_set SPI3_IRQHandler,Default_Handler
.weak UART4_IRQHandler
.thumb_set UART4_IRQHandler,Default_Handler
.weak UART5_IRQHandler
.thumb_set UART5_IRQHandler,Default_Handler
.weak TIM6_DAC_IRQHandler
.thumb_set TIM6_DAC_IRQHandler,Default_Handler
.weak TIM7_IRQHandler
.thumb_set TIM7_IRQHandler,Default_Handler
.weak DMA2_Stream0_IRQHandler
.thumb_set DMA2_Stream0_IRQHandler,Default_Handler
.weak DMA2_Stream1_IRQHandler
.thumb_set DMA2_Stream1_IRQHandler,Default_Handler
.weak DMA2_Stream2_IRQHandler
.thumb_set DMA2_Stream2_IRQHandler,Default_Handler
.weak DMA2_Stream3_IRQHandler
.thumb_set DMA2_Stream3_IRQHandler,Default_Handler
.weak DMA2_Stream4_IRQHandler
.thumb_set DMA2_Stream4_IRQHandler,Default_Handler
.weak ETH_IRQHandler
.thumb_set ETH_IRQHandler,Default_Handler
.weak ETH_WKUP_IRQHandler
.thumb_set ETH_WKUP_IRQHandler,Default_Handler
.weak CAN2_TX_IRQHandler
.thumb_set CAN2_TX_IRQHandler,Default_Handler
.weak CAN2_RX0_IRQHandler
.thumb_set CAN2_RX0_IRQHandler,Default_Handler
.weak CAN2_RX1_IRQHandler
.thumb_set CAN2_RX1_IRQHandler,Default_Handler
.weak CAN2_SCE_IRQHandler
.thumb_set CAN2_SCE_IRQHandler,Default_Handler
.weak OTG_FS_IRQHandler
.thumb_set OTG_FS_IRQHandler,Default_Handler
.weak DMA2_Stream5_IRQHandler
.thumb_set DMA2_Stream5_IRQHandler,Default_Handler
.weak DMA2_Stream6_IRQHandler
.thumb_set DMA2_Stream6_IRQHandler,Default_Handler
.weak DMA2_Stream7_IRQHandler
.thumb_set DMA2_Stream7_IRQHandler,Default_Handler
.weak USART6_IRQHandler
.thumb_set USART6_IRQHandler,Default_Handler
.weak I2C3_EV_IRQHandler
.thumb_set I2C3_EV_IRQHandler,Default_Handler
.weak I2C3_ER_IRQHandler
.thumb_set I2C3_ER_IRQHandler,Default_Handler
.weak OTG_HS_EP1_OUT_IRQHandler
.thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler
.weak OTG_HS_EP1_IN_IRQHandler
.thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler
.weak OTG_HS_WKUP_IRQHandler
.thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler
.weak OTG_HS_IRQHandler
.thumb_set OTG_HS_IRQHandler,Default_Handler
.weak DCMI_IRQHandler
.thumb_set DCMI_IRQHandler,Default_Handler
.weak CRYP_IRQHandler
.thumb_set CRYP_IRQHandler,Default_Handler
.weak HASH_RNG_IRQHandler
.thumb_set HASH_RNG_IRQHandler,Default_Handler
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Some files were not shown because too many files have changed in this diff Show More