Directory transmitter renamed to radio
This commit is contained in:
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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 ]
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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 ***/
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 ;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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 **/
|
||||
|
||||
@@ -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 **/
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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 ***/
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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))
|
||||
+6968
File diff suppressed because it is too large
Load Diff
+105
@@ -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>© 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****/
|
||||
+512
@@ -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>© 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
Reference in New Issue
Block a user