Review line ending handling (#4820)
* New line end handling rules * Normalize all the line endings
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
#define sticks_4x1_width 18
|
||||
#define sticks_4x1_height 32
|
||||
static unsigned char sticks_4x1_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x88, 0x00, 0x44, 0x00, 0x00,
|
||||
0xfe, 0x24, 0x01, 0x44, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x20, 0x00,
|
||||
0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x70, 0x88, 0x00, 0x20, 0x00, 0x00,
|
||||
0x20, 0x24, 0x01, 0x20, 0x00, 0x00, 0x70, 0x88, 0x00, 0x20, 0x20, 0x00,
|
||||
0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x44, 0x38, 0x00, 0x00, 0x10, 0x00,
|
||||
0x92, 0x10, 0x00, 0x00, 0x10, 0x00, 0x44, 0x38, 0x00, 0x10, 0x10, 0x00,
|
||||
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x88, 0x00,
|
||||
0x92, 0xfc, 0x01, 0x00, 0x88, 0x00, 0x44, 0x00, 0x00, 0x10, 0x00, 0x00 };
|
||||
#define sticks_4x1_width 18
|
||||
#define sticks_4x1_height 32
|
||||
static unsigned char sticks_4x1_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x88, 0x00, 0x44, 0x00, 0x00,
|
||||
0xfe, 0x24, 0x01, 0x44, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x20, 0x00,
|
||||
0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x70, 0x88, 0x00, 0x20, 0x00, 0x00,
|
||||
0x20, 0x24, 0x01, 0x20, 0x00, 0x00, 0x70, 0x88, 0x00, 0x20, 0x20, 0x00,
|
||||
0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x44, 0x38, 0x00, 0x00, 0x10, 0x00,
|
||||
0x92, 0x10, 0x00, 0x00, 0x10, 0x00, 0x44, 0x38, 0x00, 0x10, 0x10, 0x00,
|
||||
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x88, 0x00,
|
||||
0x92, 0xfc, 0x01, 0x00, 0x88, 0x00, 0x44, 0x00, 0x00, 0x10, 0x00, 0x00 };
|
||||
|
||||
+175
-175
@@ -1,175 +1,175 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 _BUZZER_H_
|
||||
#define _BUZZER_H_
|
||||
|
||||
#if defined(BUZZER)
|
||||
extern uint8_t g_beepCnt;
|
||||
extern uint8_t beepAgain;
|
||||
extern uint8_t beepAgainOrig;
|
||||
extern uint8_t beepOn;
|
||||
extern bool warble;
|
||||
extern bool warbleC;
|
||||
#if defined(HAPTIC)
|
||||
extern uint8_t hapticTick;
|
||||
#endif /* HAPTIC */
|
||||
#endif /* BUZZER */
|
||||
|
||||
#if defined(BUZZER)
|
||||
|
||||
#if defined(CPUARM) && !defined(SIMU)
|
||||
inline void _beep(uint8_t b)
|
||||
{
|
||||
buzzerSound(b);
|
||||
}
|
||||
#else /* CPUARM && !SIMU */
|
||||
inline void _beep(uint8_t b)
|
||||
{
|
||||
g_beepCnt = b;
|
||||
}
|
||||
#endif /* CPUARM && !SIMU */
|
||||
|
||||
void beep(uint8_t val);
|
||||
#else /* BUZZER */
|
||||
inline void beep(uint8_t) { }
|
||||
#endif /* BUZZER */
|
||||
|
||||
#if !defined(AUDIO)
|
||||
|
||||
#if defined(BUZZER)
|
||||
#if defined(VOICE)
|
||||
#define AUDIO_HELLO() PUSH_SYSTEM_PROMPT(AUDIO_HELLO)
|
||||
#define AUDIO_BYE()
|
||||
#define AUDIO_TX_BATTERY_LOW() PUSH_SYSTEM_PROMPT(AU_TX_BATTERY_LOW)
|
||||
#define AUDIO_INACTIVITY() PUSH_SYSTEM_PROMPT(AU_INACTIVITY)
|
||||
#define AUDIO_ERROR_MESSAGE(e) PUSH_SYSTEM_PROMPT((e))
|
||||
#define AUDIO_TIMER_MINUTE(t) playDuration(t)
|
||||
// TODO
|
||||
#define AUDIO_TIMER_30() PUSH_SYSTEM_PROMPT(AU_TIMER_30)
|
||||
#define AUDIO_TIMER_20() PUSH_SYSTEM_PROMPT(AU_TIMER_20)
|
||||
#else
|
||||
#define AUDIO_HELLO()
|
||||
#define AUDIO_BYE()
|
||||
#define AUDIO_TX_BATTERY_LOW() beep(4)
|
||||
#define AUDIO_INACTIVITY() beep(3)
|
||||
#define AUDIO_ERROR_MESSAGE(e) beep(4)
|
||||
#define AUDIO_TIMER_MINUTE(t) beep(2)
|
||||
// TODO
|
||||
#define AUDIO_TIMER_30() { beepAgain=2; beep(2); }
|
||||
#define AUDIO_TIMER_20() { beepAgain=1; beep(2); }
|
||||
#endif
|
||||
|
||||
#define AUDIO_KEY_PRESS() beep(0)
|
||||
#define AUDIO_KEY_ERROR() beep(2)
|
||||
#define AUDIO_WARNING2() beep(2)
|
||||
#define AUDIO_WARNING1() beep(3)
|
||||
#define AUDIO_ERROR() beep(4)
|
||||
#define AUDIO_MIX_WARNING(x) beep(1)
|
||||
#define AUDIO_POT_MIDDLE() beep(2)
|
||||
#define AUDIO_TIMER_COUNTDOWN(idx, val) beep(2)
|
||||
#define AUDIO_TIMER_ELAPSED(idx) beep(3)
|
||||
#define AUDIO_VARIO_UP() _beep(1)
|
||||
#define AUDIO_VARIO_DOWN() _beep(1)
|
||||
#define AUDIO_TRIM_PRESS(f) { if (!IS_KEY_FIRST(event)) warble = true; beep(1); }
|
||||
#define AUDIO_TRIM_MIDDLE() beep(2)
|
||||
#define AUDIO_TRIM_MIN() beep(2)
|
||||
#define AUDIO_TRIM_MAX() beep(2)
|
||||
#define AUDIO_PLAY(p) beep(3)
|
||||
|
||||
#define IS_AUDIO_BUSY() (g_beepCnt || beepAgain || beepOn)
|
||||
#else /* BUZZER */
|
||||
#define AUDIO_HELLO()
|
||||
#define AUDIO_BYE()
|
||||
#define AUDIO_TX_BATTERY_LOW()
|
||||
#define AUDIO_INACTIVITY()
|
||||
#define AUDIO_ERROR_MESSAGE(e)
|
||||
#define AUDIO_TIMER_MINUTE(t)
|
||||
#define AUDIO_TIMER_30()
|
||||
#define AUDIO_TIMER_20()
|
||||
#define AUDIO_WARNING2()
|
||||
#define AUDIO_WARNING1()
|
||||
#define AUDIO_ERROR()
|
||||
#define AUDIO_MIX_WARNING(x)
|
||||
#define AUDIO_POT_MIDDLE()
|
||||
#define AUDIO_TIMER_LT10(m, x)
|
||||
#define AUDIO_TIMER_00(m)
|
||||
#define AUDIO_VARIO_UP()
|
||||
#define AUDIO_VARIO_DOWN()
|
||||
#define AUDIO_TRIM(event, f)
|
||||
#define AUDIO_TRIM_MIDDLE(f)
|
||||
#define AUDIO_TRIM_END(f)
|
||||
#define AUDIO_PLAY(p)
|
||||
#define IS_AUDIO_BUSY() false
|
||||
#endif /* BUZZER */
|
||||
|
||||
#define AUDIO_RESET()
|
||||
#define AUDIO_FLUSH()
|
||||
|
||||
#define PLAY_PHASE_OFF(phase)
|
||||
#define PLAY_PHASE_ON(phase)
|
||||
#define PLAY_SWITCH_MOVED(sw)
|
||||
#define PLAY_LOGICAL_SWITCH_OFF(sw)
|
||||
#define PLAY_LOGICAL_SWITCH_ON(sw)
|
||||
#define PLAY_MODEL_NAME()
|
||||
#define START_SILENCE_PERIOD()
|
||||
#endif /* !AUDIO */
|
||||
|
||||
#if !defined(CPUARM)
|
||||
#if defined(BUZZER)
|
||||
inline void BUZZER_HEARTBEAT()
|
||||
{
|
||||
if (g_beepCnt) {
|
||||
if (!beepAgainOrig) {
|
||||
beepAgainOrig = g_beepCnt;
|
||||
beepOn = true;
|
||||
}
|
||||
g_beepCnt--;
|
||||
}
|
||||
else {
|
||||
if (beepAgain && beepAgainOrig) {
|
||||
beepOn = !beepOn;
|
||||
g_beepCnt = beepOn ? beepAgainOrig : 8;
|
||||
if (beepOn) beepAgain--;
|
||||
}
|
||||
else {
|
||||
beepAgainOrig = 0;
|
||||
beepOn = false;
|
||||
warble = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (beepOn) {
|
||||
warbleC = warble && !warbleC;
|
||||
if (warbleC)
|
||||
buzzerOff();
|
||||
else
|
||||
buzzerOn();
|
||||
}
|
||||
else {
|
||||
buzzerOff();
|
||||
}
|
||||
}
|
||||
#else // BUZZER
|
||||
#define BUZZER_HEARTBEAT()
|
||||
#endif // BUZZER
|
||||
#endif // CPUARM
|
||||
|
||||
#endif // _BUZZER_H_
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 _BUZZER_H_
|
||||
#define _BUZZER_H_
|
||||
|
||||
#if defined(BUZZER)
|
||||
extern uint8_t g_beepCnt;
|
||||
extern uint8_t beepAgain;
|
||||
extern uint8_t beepAgainOrig;
|
||||
extern uint8_t beepOn;
|
||||
extern bool warble;
|
||||
extern bool warbleC;
|
||||
#if defined(HAPTIC)
|
||||
extern uint8_t hapticTick;
|
||||
#endif /* HAPTIC */
|
||||
#endif /* BUZZER */
|
||||
|
||||
#if defined(BUZZER)
|
||||
|
||||
#if defined(CPUARM) && !defined(SIMU)
|
||||
inline void _beep(uint8_t b)
|
||||
{
|
||||
buzzerSound(b);
|
||||
}
|
||||
#else /* CPUARM && !SIMU */
|
||||
inline void _beep(uint8_t b)
|
||||
{
|
||||
g_beepCnt = b;
|
||||
}
|
||||
#endif /* CPUARM && !SIMU */
|
||||
|
||||
void beep(uint8_t val);
|
||||
#else /* BUZZER */
|
||||
inline void beep(uint8_t) { }
|
||||
#endif /* BUZZER */
|
||||
|
||||
#if !defined(AUDIO)
|
||||
|
||||
#if defined(BUZZER)
|
||||
#if defined(VOICE)
|
||||
#define AUDIO_HELLO() PUSH_SYSTEM_PROMPT(AUDIO_HELLO)
|
||||
#define AUDIO_BYE()
|
||||
#define AUDIO_TX_BATTERY_LOW() PUSH_SYSTEM_PROMPT(AU_TX_BATTERY_LOW)
|
||||
#define AUDIO_INACTIVITY() PUSH_SYSTEM_PROMPT(AU_INACTIVITY)
|
||||
#define AUDIO_ERROR_MESSAGE(e) PUSH_SYSTEM_PROMPT((e))
|
||||
#define AUDIO_TIMER_MINUTE(t) playDuration(t)
|
||||
// TODO
|
||||
#define AUDIO_TIMER_30() PUSH_SYSTEM_PROMPT(AU_TIMER_30)
|
||||
#define AUDIO_TIMER_20() PUSH_SYSTEM_PROMPT(AU_TIMER_20)
|
||||
#else
|
||||
#define AUDIO_HELLO()
|
||||
#define AUDIO_BYE()
|
||||
#define AUDIO_TX_BATTERY_LOW() beep(4)
|
||||
#define AUDIO_INACTIVITY() beep(3)
|
||||
#define AUDIO_ERROR_MESSAGE(e) beep(4)
|
||||
#define AUDIO_TIMER_MINUTE(t) beep(2)
|
||||
// TODO
|
||||
#define AUDIO_TIMER_30() { beepAgain=2; beep(2); }
|
||||
#define AUDIO_TIMER_20() { beepAgain=1; beep(2); }
|
||||
#endif
|
||||
|
||||
#define AUDIO_KEY_PRESS() beep(0)
|
||||
#define AUDIO_KEY_ERROR() beep(2)
|
||||
#define AUDIO_WARNING2() beep(2)
|
||||
#define AUDIO_WARNING1() beep(3)
|
||||
#define AUDIO_ERROR() beep(4)
|
||||
#define AUDIO_MIX_WARNING(x) beep(1)
|
||||
#define AUDIO_POT_MIDDLE() beep(2)
|
||||
#define AUDIO_TIMER_COUNTDOWN(idx, val) beep(2)
|
||||
#define AUDIO_TIMER_ELAPSED(idx) beep(3)
|
||||
#define AUDIO_VARIO_UP() _beep(1)
|
||||
#define AUDIO_VARIO_DOWN() _beep(1)
|
||||
#define AUDIO_TRIM_PRESS(f) { if (!IS_KEY_FIRST(event)) warble = true; beep(1); }
|
||||
#define AUDIO_TRIM_MIDDLE() beep(2)
|
||||
#define AUDIO_TRIM_MIN() beep(2)
|
||||
#define AUDIO_TRIM_MAX() beep(2)
|
||||
#define AUDIO_PLAY(p) beep(3)
|
||||
|
||||
#define IS_AUDIO_BUSY() (g_beepCnt || beepAgain || beepOn)
|
||||
#else /* BUZZER */
|
||||
#define AUDIO_HELLO()
|
||||
#define AUDIO_BYE()
|
||||
#define AUDIO_TX_BATTERY_LOW()
|
||||
#define AUDIO_INACTIVITY()
|
||||
#define AUDIO_ERROR_MESSAGE(e)
|
||||
#define AUDIO_TIMER_MINUTE(t)
|
||||
#define AUDIO_TIMER_30()
|
||||
#define AUDIO_TIMER_20()
|
||||
#define AUDIO_WARNING2()
|
||||
#define AUDIO_WARNING1()
|
||||
#define AUDIO_ERROR()
|
||||
#define AUDIO_MIX_WARNING(x)
|
||||
#define AUDIO_POT_MIDDLE()
|
||||
#define AUDIO_TIMER_LT10(m, x)
|
||||
#define AUDIO_TIMER_00(m)
|
||||
#define AUDIO_VARIO_UP()
|
||||
#define AUDIO_VARIO_DOWN()
|
||||
#define AUDIO_TRIM(event, f)
|
||||
#define AUDIO_TRIM_MIDDLE(f)
|
||||
#define AUDIO_TRIM_END(f)
|
||||
#define AUDIO_PLAY(p)
|
||||
#define IS_AUDIO_BUSY() false
|
||||
#endif /* BUZZER */
|
||||
|
||||
#define AUDIO_RESET()
|
||||
#define AUDIO_FLUSH()
|
||||
|
||||
#define PLAY_PHASE_OFF(phase)
|
||||
#define PLAY_PHASE_ON(phase)
|
||||
#define PLAY_SWITCH_MOVED(sw)
|
||||
#define PLAY_LOGICAL_SWITCH_OFF(sw)
|
||||
#define PLAY_LOGICAL_SWITCH_ON(sw)
|
||||
#define PLAY_MODEL_NAME()
|
||||
#define START_SILENCE_PERIOD()
|
||||
#endif /* !AUDIO */
|
||||
|
||||
#if !defined(CPUARM)
|
||||
#if defined(BUZZER)
|
||||
inline void BUZZER_HEARTBEAT()
|
||||
{
|
||||
if (g_beepCnt) {
|
||||
if (!beepAgainOrig) {
|
||||
beepAgainOrig = g_beepCnt;
|
||||
beepOn = true;
|
||||
}
|
||||
g_beepCnt--;
|
||||
}
|
||||
else {
|
||||
if (beepAgain && beepAgainOrig) {
|
||||
beepOn = !beepOn;
|
||||
g_beepCnt = beepOn ? beepAgainOrig : 8;
|
||||
if (beepOn) beepAgain--;
|
||||
}
|
||||
else {
|
||||
beepAgainOrig = 0;
|
||||
beepOn = false;
|
||||
warble = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (beepOn) {
|
||||
warbleC = warble && !warbleC;
|
||||
if (warbleC)
|
||||
buzzerOff();
|
||||
else
|
||||
buzzerOn();
|
||||
}
|
||||
else {
|
||||
buzzerOff();
|
||||
}
|
||||
}
|
||||
#else // BUZZER
|
||||
#define BUZZER_HEARTBEAT()
|
||||
#endif // BUZZER
|
||||
#endif // CPUARM
|
||||
|
||||
#endif // _BUZZER_H_
|
||||
|
||||
+180
-180
@@ -1,180 +1,180 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 <string.h>
|
||||
#include "opentx.h"
|
||||
|
||||
#if defined(SIMU) && !defined(SIMU_DISKIO)
|
||||
#define __disk_read(...) (RES_OK)
|
||||
#define __disk_write(...) (RES_OK)
|
||||
#endif
|
||||
|
||||
#if 0 // set to 1 to enable traces
|
||||
#define TRACE_DISK_CACHE(...) TRACE(__VA_ARGS__)
|
||||
#else
|
||||
#define TRACE_DISK_CACHE(...)
|
||||
#endif
|
||||
|
||||
DiskCache diskCache;
|
||||
|
||||
DiskCacheBlock::DiskCacheBlock():
|
||||
startSector(0),
|
||||
endSector(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool DiskCacheBlock::read(BYTE * buff, DWORD sector, UINT count)
|
||||
{
|
||||
if (sector >= startSector && (sector+count) <= endSector) {
|
||||
TRACE_DISK_CACHE("\tcache read(%u, %u) from %p", (uint32_t)sector, (uint32_t)count, this);
|
||||
memcpy(buff, data + ((sector - startSector) * BLOCK_SIZE), count * BLOCK_SIZE);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DRESULT DiskCacheBlock::fill(BYTE drv, BYTE * buff, DWORD sector, UINT count)
|
||||
{
|
||||
DRESULT res = __disk_read(drv, data, sector, DISK_CACHE_BLOCK_SECTORS);
|
||||
if (res != RES_OK) {
|
||||
return res;
|
||||
}
|
||||
startSector = sector;
|
||||
endSector = sector + DISK_CACHE_BLOCK_SECTORS;
|
||||
memcpy(buff, data, count * BLOCK_SIZE);
|
||||
TRACE_DISK_CACHE("\tcache %p FILLED from read(%u, %u)", this, (uint32_t)sector, (uint32_t)count);
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
void DiskCacheBlock::free(DWORD sector, UINT count)
|
||||
{
|
||||
if (sector < endSector && (sector+count) > startSector) {
|
||||
TRACE_DISK_CACHE("\tINVALIDATING disk cache block %p (%u)", this, startSector);
|
||||
endSector = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DiskCacheBlock::free()
|
||||
{
|
||||
endSector = 0;
|
||||
}
|
||||
|
||||
bool DiskCacheBlock::empty() const
|
||||
{
|
||||
return (endSector == 0);
|
||||
}
|
||||
|
||||
DiskCache::DiskCache():
|
||||
lastBlock(0)
|
||||
{
|
||||
stats.noHits = 0;
|
||||
stats.noMisses = 0;
|
||||
stats.noWrites = 0;
|
||||
blocks = new DiskCacheBlock[DISK_CACHE_BLOCKS_NUM];
|
||||
}
|
||||
|
||||
void DiskCache::clear()
|
||||
{
|
||||
lastBlock = 0;
|
||||
stats.noHits = 0;
|
||||
stats.noMisses = 0;
|
||||
stats.noWrites = 0;
|
||||
for (int n=0; n<DISK_CACHE_BLOCKS_NUM; ++n) {
|
||||
blocks[n].free();
|
||||
}
|
||||
}
|
||||
|
||||
DRESULT DiskCache::read(BYTE drv, BYTE * buff, DWORD sector, UINT count)
|
||||
{
|
||||
// TODO: check if not caching first sectors would improve anything
|
||||
// if (sector < 1000) {
|
||||
// ++stats.noMisses;
|
||||
// return __disk_read(drv, buff, sector, count);
|
||||
// }
|
||||
|
||||
// if read is bigger than cache block, then read it directly without using cache
|
||||
if (count > DISK_CACHE_BLOCK_SECTORS) {
|
||||
TRACE_DISK_CACHE("\t\t big read(%u, %u)", (uint32_t)sector, (uint32_t)count);
|
||||
return __disk_read(drv, buff, sector, count);
|
||||
}
|
||||
|
||||
// if block + cache block size is beyond the end of the disk, then read it directly without using cache
|
||||
if (sector+DISK_CACHE_BLOCK_SECTORS >= sdGetNoSectors()) {
|
||||
TRACE_DISK_CACHE("\t\t cache would be beyond end of disk %u (%u)", (uint32_t)sector, sdGetNoSectors());
|
||||
return __disk_read(drv, buff, sector, count);
|
||||
}
|
||||
|
||||
for (int n=0; n<DISK_CACHE_BLOCKS_NUM; ++n) {
|
||||
if (blocks[n].read(buff, sector, count)) {
|
||||
++stats.noHits;
|
||||
return RES_OK;
|
||||
}
|
||||
}
|
||||
|
||||
++stats.noMisses;
|
||||
|
||||
// find free block
|
||||
for (int n=0; n<DISK_CACHE_BLOCKS_NUM; ++n) {
|
||||
if (blocks[n].empty()) {
|
||||
TRACE_DISK_CACHE("\t\t using free block");
|
||||
return blocks[n].fill(drv, buff, sector, count);
|
||||
}
|
||||
}
|
||||
|
||||
// use next block (round robin)
|
||||
// TODO: use better strategy to select which used block gets used here
|
||||
if (++lastBlock >= DISK_CACHE_BLOCKS_NUM) {
|
||||
lastBlock = 0;
|
||||
}
|
||||
|
||||
return blocks[lastBlock].fill(drv, buff, sector, count);
|
||||
}
|
||||
|
||||
DRESULT DiskCache::write(BYTE drv, const BYTE* buff, DWORD sector, UINT count)
|
||||
{
|
||||
++stats.noWrites;
|
||||
for(int n=0; n < DISK_CACHE_BLOCKS_NUM; ++n) {
|
||||
blocks[n].free(sector, count);
|
||||
}
|
||||
return __disk_write(drv, buff, sector, count);
|
||||
}
|
||||
|
||||
const DiskCacheStats & DiskCache::getStats() const
|
||||
{
|
||||
return stats;
|
||||
}
|
||||
|
||||
int DiskCache::getHitRate() const
|
||||
{
|
||||
uint32_t all = stats.noHits + stats.noMisses;
|
||||
if (all == 0) return 0;
|
||||
return (stats.noHits * 1000) / all;
|
||||
}
|
||||
|
||||
DRESULT disk_read(BYTE drv, BYTE * buff, DWORD sector, UINT count)
|
||||
{
|
||||
return diskCache.read(drv, buff, sector, count);
|
||||
}
|
||||
|
||||
|
||||
DRESULT disk_write(BYTE drv, const BYTE * buff, DWORD sector, UINT count)
|
||||
{
|
||||
return diskCache.write(drv, buff, sector, count);
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 <string.h>
|
||||
#include "opentx.h"
|
||||
|
||||
#if defined(SIMU) && !defined(SIMU_DISKIO)
|
||||
#define __disk_read(...) (RES_OK)
|
||||
#define __disk_write(...) (RES_OK)
|
||||
#endif
|
||||
|
||||
#if 0 // set to 1 to enable traces
|
||||
#define TRACE_DISK_CACHE(...) TRACE(__VA_ARGS__)
|
||||
#else
|
||||
#define TRACE_DISK_CACHE(...)
|
||||
#endif
|
||||
|
||||
DiskCache diskCache;
|
||||
|
||||
DiskCacheBlock::DiskCacheBlock():
|
||||
startSector(0),
|
||||
endSector(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool DiskCacheBlock::read(BYTE * buff, DWORD sector, UINT count)
|
||||
{
|
||||
if (sector >= startSector && (sector+count) <= endSector) {
|
||||
TRACE_DISK_CACHE("\tcache read(%u, %u) from %p", (uint32_t)sector, (uint32_t)count, this);
|
||||
memcpy(buff, data + ((sector - startSector) * BLOCK_SIZE), count * BLOCK_SIZE);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DRESULT DiskCacheBlock::fill(BYTE drv, BYTE * buff, DWORD sector, UINT count)
|
||||
{
|
||||
DRESULT res = __disk_read(drv, data, sector, DISK_CACHE_BLOCK_SECTORS);
|
||||
if (res != RES_OK) {
|
||||
return res;
|
||||
}
|
||||
startSector = sector;
|
||||
endSector = sector + DISK_CACHE_BLOCK_SECTORS;
|
||||
memcpy(buff, data, count * BLOCK_SIZE);
|
||||
TRACE_DISK_CACHE("\tcache %p FILLED from read(%u, %u)", this, (uint32_t)sector, (uint32_t)count);
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
void DiskCacheBlock::free(DWORD sector, UINT count)
|
||||
{
|
||||
if (sector < endSector && (sector+count) > startSector) {
|
||||
TRACE_DISK_CACHE("\tINVALIDATING disk cache block %p (%u)", this, startSector);
|
||||
endSector = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DiskCacheBlock::free()
|
||||
{
|
||||
endSector = 0;
|
||||
}
|
||||
|
||||
bool DiskCacheBlock::empty() const
|
||||
{
|
||||
return (endSector == 0);
|
||||
}
|
||||
|
||||
DiskCache::DiskCache():
|
||||
lastBlock(0)
|
||||
{
|
||||
stats.noHits = 0;
|
||||
stats.noMisses = 0;
|
||||
stats.noWrites = 0;
|
||||
blocks = new DiskCacheBlock[DISK_CACHE_BLOCKS_NUM];
|
||||
}
|
||||
|
||||
void DiskCache::clear()
|
||||
{
|
||||
lastBlock = 0;
|
||||
stats.noHits = 0;
|
||||
stats.noMisses = 0;
|
||||
stats.noWrites = 0;
|
||||
for (int n=0; n<DISK_CACHE_BLOCKS_NUM; ++n) {
|
||||
blocks[n].free();
|
||||
}
|
||||
}
|
||||
|
||||
DRESULT DiskCache::read(BYTE drv, BYTE * buff, DWORD sector, UINT count)
|
||||
{
|
||||
// TODO: check if not caching first sectors would improve anything
|
||||
// if (sector < 1000) {
|
||||
// ++stats.noMisses;
|
||||
// return __disk_read(drv, buff, sector, count);
|
||||
// }
|
||||
|
||||
// if read is bigger than cache block, then read it directly without using cache
|
||||
if (count > DISK_CACHE_BLOCK_SECTORS) {
|
||||
TRACE_DISK_CACHE("\t\t big read(%u, %u)", (uint32_t)sector, (uint32_t)count);
|
||||
return __disk_read(drv, buff, sector, count);
|
||||
}
|
||||
|
||||
// if block + cache block size is beyond the end of the disk, then read it directly without using cache
|
||||
if (sector+DISK_CACHE_BLOCK_SECTORS >= sdGetNoSectors()) {
|
||||
TRACE_DISK_CACHE("\t\t cache would be beyond end of disk %u (%u)", (uint32_t)sector, sdGetNoSectors());
|
||||
return __disk_read(drv, buff, sector, count);
|
||||
}
|
||||
|
||||
for (int n=0; n<DISK_CACHE_BLOCKS_NUM; ++n) {
|
||||
if (blocks[n].read(buff, sector, count)) {
|
||||
++stats.noHits;
|
||||
return RES_OK;
|
||||
}
|
||||
}
|
||||
|
||||
++stats.noMisses;
|
||||
|
||||
// find free block
|
||||
for (int n=0; n<DISK_CACHE_BLOCKS_NUM; ++n) {
|
||||
if (blocks[n].empty()) {
|
||||
TRACE_DISK_CACHE("\t\t using free block");
|
||||
return blocks[n].fill(drv, buff, sector, count);
|
||||
}
|
||||
}
|
||||
|
||||
// use next block (round robin)
|
||||
// TODO: use better strategy to select which used block gets used here
|
||||
if (++lastBlock >= DISK_CACHE_BLOCKS_NUM) {
|
||||
lastBlock = 0;
|
||||
}
|
||||
|
||||
return blocks[lastBlock].fill(drv, buff, sector, count);
|
||||
}
|
||||
|
||||
DRESULT DiskCache::write(BYTE drv, const BYTE* buff, DWORD sector, UINT count)
|
||||
{
|
||||
++stats.noWrites;
|
||||
for(int n=0; n < DISK_CACHE_BLOCKS_NUM; ++n) {
|
||||
blocks[n].free(sector, count);
|
||||
}
|
||||
return __disk_write(drv, buff, sector, count);
|
||||
}
|
||||
|
||||
const DiskCacheStats & DiskCache::getStats() const
|
||||
{
|
||||
return stats;
|
||||
}
|
||||
|
||||
int DiskCache::getHitRate() const
|
||||
{
|
||||
uint32_t all = stats.noHits + stats.noMisses;
|
||||
if (all == 0) return 0;
|
||||
return (stats.noHits * 1000) / all;
|
||||
}
|
||||
|
||||
DRESULT disk_read(BYTE drv, BYTE * buff, DWORD sector, UINT count)
|
||||
{
|
||||
return diskCache.read(drv, buff, sector, count);
|
||||
}
|
||||
|
||||
|
||||
DRESULT disk_write(BYTE drv, const BYTE * buff, DWORD sector, UINT count)
|
||||
{
|
||||
return diskCache.write(drv, buff, sector, count);
|
||||
}
|
||||
|
||||
+74
-74
@@ -1,74 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 _DISK_CACHE_H_
|
||||
#define _DISK_CACHE_H_
|
||||
|
||||
#include "diskio.h"
|
||||
#include "sdio_sd.h"
|
||||
|
||||
// tunable parameters
|
||||
#define DISK_CACHE_BLOCKS_NUM 32 // no cache blocks
|
||||
#define DISK_CACHE_BLOCK_SECTORS 16 // no sectors
|
||||
|
||||
#define DISK_CACHE_BLOCK_SIZE (DISK_CACHE_BLOCK_SECTORS * BLOCK_SIZE)
|
||||
|
||||
class DiskCacheBlock
|
||||
{
|
||||
public:
|
||||
DiskCacheBlock();
|
||||
bool read(BYTE* buff, DWORD sector, UINT count);
|
||||
DRESULT fill(BYTE drv, BYTE* buff, DWORD sector, UINT count);
|
||||
void free(DWORD sector, UINT count);
|
||||
void free();
|
||||
bool empty() const;
|
||||
|
||||
private:
|
||||
uint8_t data[DISK_CACHE_BLOCK_SIZE];
|
||||
DWORD startSector;
|
||||
DWORD endSector;
|
||||
};
|
||||
|
||||
struct DiskCacheStats
|
||||
{
|
||||
uint32_t noHits;
|
||||
uint32_t noMisses;
|
||||
uint32_t noWrites;
|
||||
};
|
||||
|
||||
class DiskCache
|
||||
{
|
||||
public:
|
||||
DiskCache();
|
||||
DRESULT read(BYTE drv, BYTE* buff, DWORD sector, UINT count);
|
||||
DRESULT write(BYTE drv, const BYTE* buff, DWORD sector, UINT count);
|
||||
const DiskCacheStats & getStats() const;
|
||||
int getHitRate() const;
|
||||
void clear();
|
||||
|
||||
private:
|
||||
DiskCacheStats stats;
|
||||
uint32_t lastBlock;
|
||||
DiskCacheBlock * blocks;
|
||||
};
|
||||
|
||||
extern DiskCache diskCache;
|
||||
|
||||
#endif // _DISK_CACHE_H_
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 _DISK_CACHE_H_
|
||||
#define _DISK_CACHE_H_
|
||||
|
||||
#include "diskio.h"
|
||||
#include "sdio_sd.h"
|
||||
|
||||
// tunable parameters
|
||||
#define DISK_CACHE_BLOCKS_NUM 32 // no cache blocks
|
||||
#define DISK_CACHE_BLOCK_SECTORS 16 // no sectors
|
||||
|
||||
#define DISK_CACHE_BLOCK_SIZE (DISK_CACHE_BLOCK_SECTORS * BLOCK_SIZE)
|
||||
|
||||
class DiskCacheBlock
|
||||
{
|
||||
public:
|
||||
DiskCacheBlock();
|
||||
bool read(BYTE* buff, DWORD sector, UINT count);
|
||||
DRESULT fill(BYTE drv, BYTE* buff, DWORD sector, UINT count);
|
||||
void free(DWORD sector, UINT count);
|
||||
void free();
|
||||
bool empty() const;
|
||||
|
||||
private:
|
||||
uint8_t data[DISK_CACHE_BLOCK_SIZE];
|
||||
DWORD startSector;
|
||||
DWORD endSector;
|
||||
};
|
||||
|
||||
struct DiskCacheStats
|
||||
{
|
||||
uint32_t noHits;
|
||||
uint32_t noMisses;
|
||||
uint32_t noWrites;
|
||||
};
|
||||
|
||||
class DiskCache
|
||||
{
|
||||
public:
|
||||
DiskCache();
|
||||
DRESULT read(BYTE drv, BYTE* buff, DWORD sector, UINT count);
|
||||
DRESULT write(BYTE drv, const BYTE* buff, DWORD sector, UINT count);
|
||||
const DiskCacheStats & getStats() const;
|
||||
int getHitRate() const;
|
||||
void clear();
|
||||
|
||||
private:
|
||||
DiskCacheStats stats;
|
||||
uint32_t lastBlock;
|
||||
DiskCacheBlock * blocks;
|
||||
};
|
||||
|
||||
extern DiskCache diskCache;
|
||||
|
||||
#endif // _DISK_CACHE_H_
|
||||
|
||||
+82
-82
@@ -1,82 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 _DMA_FIFO_H_
|
||||
#define _DMA_FIFO_H_
|
||||
|
||||
#include "definitions.h"
|
||||
|
||||
template <int N>
|
||||
class DMAFifo
|
||||
{
|
||||
public:
|
||||
DMAFifo(DMA_Stream_TypeDef * stream):
|
||||
stream(stream),
|
||||
ridx(0)
|
||||
{
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
ridx = 0;
|
||||
}
|
||||
|
||||
uint32_t size()
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
uint8_t last(int index)
|
||||
{
|
||||
return fifo[(2*N - stream->NDTR - index) & (N-1)];
|
||||
}
|
||||
|
||||
bool isEmpty()
|
||||
{
|
||||
#if defined(SIMU)
|
||||
return true;
|
||||
#endif
|
||||
return (ridx == N - stream->NDTR);
|
||||
}
|
||||
|
||||
bool pop(uint8_t & element)
|
||||
{
|
||||
if (isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
element = fifo[ridx];
|
||||
ridx = (ridx+1) & (N-1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t * buffer()
|
||||
{
|
||||
return fifo;
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t fifo[N];
|
||||
DMA_Stream_TypeDef * stream;
|
||||
volatile uint32_t ridx;
|
||||
};
|
||||
|
||||
#endif // _DMA_FIFO_H_
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 _DMA_FIFO_H_
|
||||
#define _DMA_FIFO_H_
|
||||
|
||||
#include "definitions.h"
|
||||
|
||||
template <int N>
|
||||
class DMAFifo
|
||||
{
|
||||
public:
|
||||
DMAFifo(DMA_Stream_TypeDef * stream):
|
||||
stream(stream),
|
||||
ridx(0)
|
||||
{
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
ridx = 0;
|
||||
}
|
||||
|
||||
uint32_t size()
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
uint8_t last(int index)
|
||||
{
|
||||
return fifo[(2*N - stream->NDTR - index) & (N-1)];
|
||||
}
|
||||
|
||||
bool isEmpty()
|
||||
{
|
||||
#if defined(SIMU)
|
||||
return true;
|
||||
#endif
|
||||
return (ridx == N - stream->NDTR);
|
||||
}
|
||||
|
||||
bool pop(uint8_t & element)
|
||||
{
|
||||
if (isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
element = fifo[ridx];
|
||||
ridx = (ridx+1) & (N-1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t * buffer()
|
||||
{
|
||||
return fifo;
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t fifo[N];
|
||||
DMA_Stream_TypeDef * stream;
|
||||
volatile uint32_t ridx;
|
||||
};
|
||||
|
||||
#endif // _DMA_FIFO_H_
|
||||
|
||||
+105
-105
@@ -1,105 +1,105 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 _FIFO_H_
|
||||
#define _FIFO_H_
|
||||
|
||||
template <class T, int N>
|
||||
class Fifo
|
||||
{
|
||||
static_assert((N > 1) & !(N & (N - 1)), "Fifo size must be a power of two!");
|
||||
|
||||
public:
|
||||
Fifo():
|
||||
widx(0),
|
||||
ridx(0)
|
||||
{
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
widx = ridx = 0;
|
||||
}
|
||||
|
||||
void push(T element)
|
||||
{
|
||||
uint32_t next = (widx+1) & (N-1);
|
||||
if (next != ridx) {
|
||||
fifo[widx] = element;
|
||||
widx = next;
|
||||
}
|
||||
}
|
||||
|
||||
bool pop(T & element)
|
||||
{
|
||||
if (isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
element = fifo[ridx];
|
||||
ridx = (ridx+1) & (N-1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool isEmpty() const
|
||||
{
|
||||
return (ridx == widx);
|
||||
}
|
||||
|
||||
bool isFull()
|
||||
{
|
||||
uint32_t next = (widx+1) & (N-1);
|
||||
return (next == ridx);
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
while (!isEmpty()) {};
|
||||
}
|
||||
|
||||
uint32_t size() const
|
||||
{
|
||||
return (N + widx - ridx) & (N-1);
|
||||
}
|
||||
|
||||
uint32_t hasSpace(uint32_t n) const
|
||||
{
|
||||
return (N > (size() + n));
|
||||
}
|
||||
|
||||
bool probe(T & element) const
|
||||
{
|
||||
if (isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
element = fifo[ridx];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
T fifo[N];
|
||||
volatile uint32_t widx;
|
||||
volatile uint32_t ridx;
|
||||
};
|
||||
|
||||
#endif // _FIFO_H_
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 _FIFO_H_
|
||||
#define _FIFO_H_
|
||||
|
||||
template <class T, int N>
|
||||
class Fifo
|
||||
{
|
||||
static_assert((N > 1) & !(N & (N - 1)), "Fifo size must be a power of two!");
|
||||
|
||||
public:
|
||||
Fifo():
|
||||
widx(0),
|
||||
ridx(0)
|
||||
{
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
widx = ridx = 0;
|
||||
}
|
||||
|
||||
void push(T element)
|
||||
{
|
||||
uint32_t next = (widx+1) & (N-1);
|
||||
if (next != ridx) {
|
||||
fifo[widx] = element;
|
||||
widx = next;
|
||||
}
|
||||
}
|
||||
|
||||
bool pop(T & element)
|
||||
{
|
||||
if (isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
element = fifo[ridx];
|
||||
ridx = (ridx+1) & (N-1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool isEmpty() const
|
||||
{
|
||||
return (ridx == widx);
|
||||
}
|
||||
|
||||
bool isFull()
|
||||
{
|
||||
uint32_t next = (widx+1) & (N-1);
|
||||
return (next == ridx);
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
while (!isEmpty()) {};
|
||||
}
|
||||
|
||||
uint32_t size() const
|
||||
{
|
||||
return (N + widx - ridx) & (N-1);
|
||||
}
|
||||
|
||||
uint32_t hasSpace(uint32_t n) const
|
||||
{
|
||||
return (N > (size() + n));
|
||||
}
|
||||
|
||||
bool probe(T & element) const
|
||||
{
|
||||
if (isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
element = fifo[ridx];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
T fifo[N];
|
||||
volatile uint32_t widx;
|
||||
volatile uint32_t ridx;
|
||||
};
|
||||
|
||||
#endif // _FIFO_H_
|
||||
|
||||
+56
-56
@@ -1,56 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 _FONTS_H_
|
||||
#define _FONTS_H_
|
||||
|
||||
#if defined(COLORLCD)
|
||||
|
||||
extern const uint16_t * const fontspecsTable[16];
|
||||
extern const uint8_t * const fontsTable[16];
|
||||
|
||||
#if defined(PCBHORUS)
|
||||
extern BitmapBuffer * fontCache[2];
|
||||
void loadFontCache();
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
extern const pm_uchar font_5x7[];
|
||||
extern const pm_uchar font_10x14[];
|
||||
|
||||
#if defined(BOLD_FONT) && ((!defined(CPUM64) && !defined(PCBMEGA2560)) || defined(TELEMETRY_NONE)) && !defined(BOOT)
|
||||
#define BOLD_SPECIFIC_FONT
|
||||
extern const pm_uchar font_5x7_B[];
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
extern const pm_uchar font_3x5[];
|
||||
extern const pm_uchar font_4x6[];
|
||||
extern const pm_uchar font_8x10[];
|
||||
extern const pm_uchar font_22x38_num[];
|
||||
extern const pm_uchar font_5x7_extra[];
|
||||
extern const pm_uchar font_10x14_extra[];
|
||||
extern const pm_uchar font_4x6_extra[];
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif // _FONTS_H_
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 _FONTS_H_
|
||||
#define _FONTS_H_
|
||||
|
||||
#if defined(COLORLCD)
|
||||
|
||||
extern const uint16_t * const fontspecsTable[16];
|
||||
extern const uint8_t * const fontsTable[16];
|
||||
|
||||
#if defined(PCBHORUS)
|
||||
extern BitmapBuffer * fontCache[2];
|
||||
void loadFontCache();
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
extern const pm_uchar font_5x7[];
|
||||
extern const pm_uchar font_10x14[];
|
||||
|
||||
#if defined(BOLD_FONT) && ((!defined(CPUM64) && !defined(PCBMEGA2560)) || defined(TELEMETRY_NONE)) && !defined(BOOT)
|
||||
#define BOLD_SPECIFIC_FONT
|
||||
extern const pm_uchar font_5x7_B[];
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
extern const pm_uchar font_3x5[];
|
||||
extern const pm_uchar font_4x6[];
|
||||
extern const pm_uchar font_8x10[];
|
||||
extern const pm_uchar font_22x38_num[];
|
||||
extern const pm_uchar font_5x7_extra[];
|
||||
extern const pm_uchar font_10x14_extra[];
|
||||
extern const pm_uchar font_4x6_extra[];
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif // _FONTS_H_
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+110
-110
@@ -1,110 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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"
|
||||
|
||||
const uint16_t font_tinsize_specs[] = {
|
||||
#include "font_tinsize.specs"
|
||||
};
|
||||
|
||||
const pm_uchar font_tinsize[] = {
|
||||
#include "font_tinsize.lbm"
|
||||
};
|
||||
|
||||
const uint16_t font_smlsize_specs[] = {
|
||||
#include "font_smlsize.specs"
|
||||
};
|
||||
|
||||
const pm_uchar font_smlsize[] = {
|
||||
#include "font_smlsize.lbm"
|
||||
};
|
||||
|
||||
const uint16_t font_stdsize_specs[] = {
|
||||
#include "font_stdsize.specs"
|
||||
};
|
||||
|
||||
const pm_uchar font_stdsize[] = {
|
||||
#include "font_stdsize.lbm"
|
||||
};
|
||||
|
||||
const uint16_t font_midsize_specs[] = {
|
||||
#include "font_midsize.specs"
|
||||
};
|
||||
|
||||
const pm_uchar font_midsize[] = {
|
||||
#include "font_midsize.lbm"
|
||||
};
|
||||
|
||||
const uint16_t font_dblsize_specs[] = {
|
||||
#include "font_dblsize.specs"
|
||||
};
|
||||
|
||||
const pm_uchar font_dblsize[] = {
|
||||
#include "font_dblsize.lbm"
|
||||
};
|
||||
|
||||
const uint16_t font_xxlsize_specs[] = {
|
||||
#include "font_xxlsize.specs"
|
||||
};
|
||||
|
||||
const pm_uchar font_xxlsize[] = {
|
||||
#include "font_xxlsize.lbm"
|
||||
};
|
||||
|
||||
const uint16_t font_stdsizebold_specs[] = {
|
||||
#include "font_stdsizebold.specs"
|
||||
};
|
||||
|
||||
const pm_uchar font_stdsizebold[] = {
|
||||
#include "font_stdsizebold.lbm"
|
||||
};
|
||||
|
||||
const uint16_t * const fontspecsTable[16] = {
|
||||
font_stdsize_specs, font_tinsize_specs, font_smlsize_specs, font_midsize_specs, font_dblsize_specs, font_xxlsize_specs, font_stdsize_specs, font_stdsize_specs,
|
||||
font_stdsizebold_specs, font_tinsize_specs, font_smlsize_specs, font_midsize_specs, font_dblsize_specs, font_xxlsize_specs, font_stdsize_specs, font_stdsize_specs
|
||||
};
|
||||
|
||||
const uint8_t * const fontsTable[16] = {
|
||||
font_stdsize, font_tinsize, font_smlsize, font_midsize, font_dblsize, font_xxlsize, font_stdsize, font_stdsize,
|
||||
font_stdsizebold, font_tinsize, font_smlsize, font_midsize, font_dblsize, font_xxlsize, font_stdsize, font_stdsize
|
||||
};
|
||||
|
||||
BitmapBuffer * fontCache[2] = { NULL, NULL };
|
||||
|
||||
BitmapBuffer * createFontCache(const uint8_t * font, LcdFlags fg, LcdFlags bg)
|
||||
{
|
||||
coord_t width = *((uint16_t *)font);
|
||||
coord_t height = *(((uint16_t *)font)+1);
|
||||
|
||||
BitmapBuffer * buffer = new BitmapBuffer(BMP_RGB565, width, height);
|
||||
if (buffer) {
|
||||
buffer->clear(bg);
|
||||
buffer->drawBitmapPattern(0, 0, font, fg);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void loadFontCache()
|
||||
{
|
||||
delete fontCache[0];
|
||||
delete fontCache[1];
|
||||
fontCache[0] = createFontCache(fontsTable[0], TEXT_COLOR, TEXT_BGCOLOR);
|
||||
fontCache[1] = createFontCache(fontsTable[0], TEXT_INVERTED_COLOR, TEXT_INVERTED_BGCOLOR);
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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"
|
||||
|
||||
const uint16_t font_tinsize_specs[] = {
|
||||
#include "font_tinsize.specs"
|
||||
};
|
||||
|
||||
const pm_uchar font_tinsize[] = {
|
||||
#include "font_tinsize.lbm"
|
||||
};
|
||||
|
||||
const uint16_t font_smlsize_specs[] = {
|
||||
#include "font_smlsize.specs"
|
||||
};
|
||||
|
||||
const pm_uchar font_smlsize[] = {
|
||||
#include "font_smlsize.lbm"
|
||||
};
|
||||
|
||||
const uint16_t font_stdsize_specs[] = {
|
||||
#include "font_stdsize.specs"
|
||||
};
|
||||
|
||||
const pm_uchar font_stdsize[] = {
|
||||
#include "font_stdsize.lbm"
|
||||
};
|
||||
|
||||
const uint16_t font_midsize_specs[] = {
|
||||
#include "font_midsize.specs"
|
||||
};
|
||||
|
||||
const pm_uchar font_midsize[] = {
|
||||
#include "font_midsize.lbm"
|
||||
};
|
||||
|
||||
const uint16_t font_dblsize_specs[] = {
|
||||
#include "font_dblsize.specs"
|
||||
};
|
||||
|
||||
const pm_uchar font_dblsize[] = {
|
||||
#include "font_dblsize.lbm"
|
||||
};
|
||||
|
||||
const uint16_t font_xxlsize_specs[] = {
|
||||
#include "font_xxlsize.specs"
|
||||
};
|
||||
|
||||
const pm_uchar font_xxlsize[] = {
|
||||
#include "font_xxlsize.lbm"
|
||||
};
|
||||
|
||||
const uint16_t font_stdsizebold_specs[] = {
|
||||
#include "font_stdsizebold.specs"
|
||||
};
|
||||
|
||||
const pm_uchar font_stdsizebold[] = {
|
||||
#include "font_stdsizebold.lbm"
|
||||
};
|
||||
|
||||
const uint16_t * const fontspecsTable[16] = {
|
||||
font_stdsize_specs, font_tinsize_specs, font_smlsize_specs, font_midsize_specs, font_dblsize_specs, font_xxlsize_specs, font_stdsize_specs, font_stdsize_specs,
|
||||
font_stdsizebold_specs, font_tinsize_specs, font_smlsize_specs, font_midsize_specs, font_dblsize_specs, font_xxlsize_specs, font_stdsize_specs, font_stdsize_specs
|
||||
};
|
||||
|
||||
const uint8_t * const fontsTable[16] = {
|
||||
font_stdsize, font_tinsize, font_smlsize, font_midsize, font_dblsize, font_xxlsize, font_stdsize, font_stdsize,
|
||||
font_stdsizebold, font_tinsize, font_smlsize, font_midsize, font_dblsize, font_xxlsize, font_stdsize, font_stdsize
|
||||
};
|
||||
|
||||
BitmapBuffer * fontCache[2] = { NULL, NULL };
|
||||
|
||||
BitmapBuffer * createFontCache(const uint8_t * font, LcdFlags fg, LcdFlags bg)
|
||||
{
|
||||
coord_t width = *((uint16_t *)font);
|
||||
coord_t height = *(((uint16_t *)font)+1);
|
||||
|
||||
BitmapBuffer * buffer = new BitmapBuffer(BMP_RGB565, width, height);
|
||||
if (buffer) {
|
||||
buffer->clear(bg);
|
||||
buffer->drawBitmapPattern(0, 0, font, fg);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void loadFontCache()
|
||||
{
|
||||
delete fontCache[0];
|
||||
delete fontCache[1];
|
||||
fontCache[0] = createFontCache(fontsTable[0], TEXT_COLOR, TEXT_BGCOLOR);
|
||||
fontCache[1] = createFontCache(fontsTable[0], TEXT_INVERTED_COLOR, TEXT_INVERTED_BGCOLOR);
|
||||
}
|
||||
|
||||
@@ -1,153 +1,153 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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"
|
||||
|
||||
enum AboutScreens {
|
||||
ABOUT_OPENTX,
|
||||
ABOUT_HARDWARE,
|
||||
ABOUT_BERTRAND,
|
||||
ABOUT_ANDRE,
|
||||
ABOUT_MIKE,
|
||||
ABOUT_KJELL,
|
||||
ABOUT_MARTIN,
|
||||
ABOUT_ROMOLO,
|
||||
ABOUT_ROB,
|
||||
ABOUT_PARENTS,
|
||||
ABOUT_END,
|
||||
ABOUT_COUNT,
|
||||
};
|
||||
|
||||
#define ABOUT_X 62
|
||||
#define ABOUT_INDENT 16
|
||||
|
||||
bool menuAboutView(event_t event)
|
||||
{
|
||||
static uint8_t screenIndex = 0;
|
||||
static uint8_t greyIndex = 0;
|
||||
|
||||
switch (event) {
|
||||
case EVT_ENTRY:
|
||||
screenIndex = 0;
|
||||
greyIndex = 0;
|
||||
break;
|
||||
#if defined(PCBX12S)
|
||||
case EVT_KEY_FIRST(KEY_PGDN):
|
||||
#elif defined(PCBX10)
|
||||
case EVT_KEY_BREAK(KEY_PGDN):
|
||||
#endif
|
||||
screenIndex < ABOUT_PARENTS ? screenIndex++ : screenIndex = ABOUT_OPENTX;
|
||||
greyIndex = 0;
|
||||
break;
|
||||
case EVT_KEY_FIRST(KEY_PGUP):
|
||||
#if defined(PCBX10)
|
||||
case EVT_KEY_LONG(KEY_PGDN):
|
||||
#endif
|
||||
screenIndex > ABOUT_OPENTX ? screenIndex-- : screenIndex = ABOUT_PARENTS;
|
||||
greyIndex = 0;
|
||||
killEvents(event);
|
||||
break;
|
||||
case EVT_KEY_FIRST(KEY_EXIT):
|
||||
chainMenu(menuMainView);
|
||||
break;
|
||||
}
|
||||
|
||||
theme->drawBackground();
|
||||
theme->drawTopbarBackground(0);
|
||||
|
||||
uint8_t screenDuration = 150;
|
||||
|
||||
switch (screenIndex) {
|
||||
case ABOUT_OPENTX:
|
||||
case ABOUT_END:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_OPENTX_1);
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP + FH, STR_ABOUT_OPENTX_2);
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_OPENTX_3);
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP + 3*FH, STR_ABOUT_OPENTX_4);
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP + 4*FH, STR_ABOUT_OPENTX_5);
|
||||
screenDuration = 255;
|
||||
break;
|
||||
|
||||
case ABOUT_BERTRAND:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_BERTRAND_1, INVERS);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_BERTRAND_2);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_BERTRAND_3);
|
||||
break;
|
||||
|
||||
case ABOUT_ANDRE:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_ANDRE_1, INVERS);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_ANDRE_2);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_ANDRE_3);
|
||||
break;
|
||||
|
||||
case ABOUT_MIKE:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_MIKE_1, INVERS);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_MIKE_2);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_MIKE_3);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 3*FH, STR_ABOUT_MIKE_4);
|
||||
break;
|
||||
|
||||
case ABOUT_KJELL:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_KJELL_1, INVERS);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_KJELL_2);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_KJELL_3);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 3*FH, STR_ABOUT_KJELL_4);
|
||||
break;
|
||||
|
||||
case ABOUT_MARTIN:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_MARTIN_1, INVERS);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_MARTIN_2);
|
||||
break;
|
||||
|
||||
case ABOUT_ROMOLO:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_ROMOLO_1, INVERS);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_ROMOLO_2);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_ROMOLO_3);
|
||||
break;
|
||||
|
||||
case ABOUT_ROB:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_ROB_1, INVERS);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_ROB_2);
|
||||
break;
|
||||
|
||||
case ABOUT_HARDWARE:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, "FrSky", INVERS);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_HARDWARE_2);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_HARDWARE_3);
|
||||
break;
|
||||
|
||||
case ABOUT_PARENTS:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_PARENTS_1, INVERS);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_PARENTS_2);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_PARENTS_3);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 3*FH, STR_ABOUT_PARENTS_4);
|
||||
screenDuration = 255;
|
||||
break;
|
||||
}
|
||||
|
||||
if (++greyIndex == screenDuration) {
|
||||
greyIndex = 0;
|
||||
if (++screenIndex == ABOUT_COUNT) {
|
||||
chainMenu(menuMainView);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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"
|
||||
|
||||
enum AboutScreens {
|
||||
ABOUT_OPENTX,
|
||||
ABOUT_HARDWARE,
|
||||
ABOUT_BERTRAND,
|
||||
ABOUT_ANDRE,
|
||||
ABOUT_MIKE,
|
||||
ABOUT_KJELL,
|
||||
ABOUT_MARTIN,
|
||||
ABOUT_ROMOLO,
|
||||
ABOUT_ROB,
|
||||
ABOUT_PARENTS,
|
||||
ABOUT_END,
|
||||
ABOUT_COUNT,
|
||||
};
|
||||
|
||||
#define ABOUT_X 62
|
||||
#define ABOUT_INDENT 16
|
||||
|
||||
bool menuAboutView(event_t event)
|
||||
{
|
||||
static uint8_t screenIndex = 0;
|
||||
static uint8_t greyIndex = 0;
|
||||
|
||||
switch (event) {
|
||||
case EVT_ENTRY:
|
||||
screenIndex = 0;
|
||||
greyIndex = 0;
|
||||
break;
|
||||
#if defined(PCBX12S)
|
||||
case EVT_KEY_FIRST(KEY_PGDN):
|
||||
#elif defined(PCBX10)
|
||||
case EVT_KEY_BREAK(KEY_PGDN):
|
||||
#endif
|
||||
screenIndex < ABOUT_PARENTS ? screenIndex++ : screenIndex = ABOUT_OPENTX;
|
||||
greyIndex = 0;
|
||||
break;
|
||||
case EVT_KEY_FIRST(KEY_PGUP):
|
||||
#if defined(PCBX10)
|
||||
case EVT_KEY_LONG(KEY_PGDN):
|
||||
#endif
|
||||
screenIndex > ABOUT_OPENTX ? screenIndex-- : screenIndex = ABOUT_PARENTS;
|
||||
greyIndex = 0;
|
||||
killEvents(event);
|
||||
break;
|
||||
case EVT_KEY_FIRST(KEY_EXIT):
|
||||
chainMenu(menuMainView);
|
||||
break;
|
||||
}
|
||||
|
||||
theme->drawBackground();
|
||||
theme->drawTopbarBackground(0);
|
||||
|
||||
uint8_t screenDuration = 150;
|
||||
|
||||
switch (screenIndex) {
|
||||
case ABOUT_OPENTX:
|
||||
case ABOUT_END:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_OPENTX_1);
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP + FH, STR_ABOUT_OPENTX_2);
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_OPENTX_3);
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP + 3*FH, STR_ABOUT_OPENTX_4);
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP + 4*FH, STR_ABOUT_OPENTX_5);
|
||||
screenDuration = 255;
|
||||
break;
|
||||
|
||||
case ABOUT_BERTRAND:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_BERTRAND_1, INVERS);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_BERTRAND_2);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_BERTRAND_3);
|
||||
break;
|
||||
|
||||
case ABOUT_ANDRE:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_ANDRE_1, INVERS);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_ANDRE_2);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_ANDRE_3);
|
||||
break;
|
||||
|
||||
case ABOUT_MIKE:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_MIKE_1, INVERS);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_MIKE_2);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_MIKE_3);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 3*FH, STR_ABOUT_MIKE_4);
|
||||
break;
|
||||
|
||||
case ABOUT_KJELL:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_KJELL_1, INVERS);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_KJELL_2);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_KJELL_3);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 3*FH, STR_ABOUT_KJELL_4);
|
||||
break;
|
||||
|
||||
case ABOUT_MARTIN:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_MARTIN_1, INVERS);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_MARTIN_2);
|
||||
break;
|
||||
|
||||
case ABOUT_ROMOLO:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_ROMOLO_1, INVERS);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_ROMOLO_2);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_ROMOLO_3);
|
||||
break;
|
||||
|
||||
case ABOUT_ROB:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_ROB_1, INVERS);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_ROB_2);
|
||||
break;
|
||||
|
||||
case ABOUT_HARDWARE:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, "FrSky", INVERS);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_HARDWARE_2);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_HARDWARE_3);
|
||||
break;
|
||||
|
||||
case ABOUT_PARENTS:
|
||||
lcdDrawText(ABOUT_X, MENU_CONTENT_TOP, STR_ABOUT_PARENTS_1, INVERS);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + FH, STR_ABOUT_PARENTS_2);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 2*FH, STR_ABOUT_PARENTS_3);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, MENU_CONTENT_TOP + 3*FH, STR_ABOUT_PARENTS_4);
|
||||
screenDuration = 255;
|
||||
break;
|
||||
}
|
||||
|
||||
if (++greyIndex == screenDuration) {
|
||||
greyIndex = 0;
|
||||
if (++screenIndex == ABOUT_COUNT) {
|
||||
chainMenu(menuMainView);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,192 +1,192 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 RECT_OFFSET 80
|
||||
#define ROW_HEIGHT 42
|
||||
#define BAR_HEIGHT 13
|
||||
#define COLUMN_SIZE 200
|
||||
#define X_OFFSET 25
|
||||
#define Y_OFFSET 75
|
||||
#define Y_OUTBAR 15
|
||||
#define Y_MIXBAR 28
|
||||
#define LEG_COLORBOX 15
|
||||
|
||||
#define VIEW_CHANNELS_LIMIT_PCT (g_model.extendedLimits ? LIMIT_EXT_PERCENT : 100)
|
||||
|
||||
bool menuChannelsMonitor(event_t event, uint8_t page);
|
||||
bool menuLogicalSwitches(event_t);
|
||||
|
||||
template<int index>
|
||||
bool menuChannelsMonitor(event_t event)
|
||||
{
|
||||
lastMonitorPage = e_MonChannelsFirst + index;
|
||||
MENU(STR_MONITOR_CHANNELS[index], MONITOR_ICONS, menuTabMonitors, lastMonitorPage, 0, { 0 });
|
||||
return menuChannelsMonitor(event, index);
|
||||
}
|
||||
|
||||
const MenuHandlerFunc menuTabMonitors[] PROGMEM = {
|
||||
menuChannelsMonitor<0>,
|
||||
menuChannelsMonitor<1>,
|
||||
menuChannelsMonitor<2>,
|
||||
menuChannelsMonitor<3>,
|
||||
menuLogicalSwitches
|
||||
};
|
||||
|
||||
uint8_t lastMonitorPage = 0;
|
||||
|
||||
uint16_t posOnBar(int16_t value_to100)
|
||||
{
|
||||
return divRoundClosest((value_to100 + VIEW_CHANNELS_LIMIT_PCT) * COLUMN_SIZE, VIEW_CHANNELS_LIMIT_PCT * 2);
|
||||
}
|
||||
|
||||
void drawOutputBarLimits(coord_t left, coord_t right, coord_t y)
|
||||
{
|
||||
lcd->drawSolidVerticalLine(left, y, BAR_HEIGHT, TEXT_COLOR);
|
||||
lcd->drawSolidHorizontalLine(left, y, 3, TEXT_COLOR);
|
||||
lcd->drawSolidHorizontalLine(left, y + BAR_HEIGHT - 1, 3, TEXT_COLOR);
|
||||
|
||||
lcd->drawSolidVerticalLine(--right, y, BAR_HEIGHT, TEXT_COLOR);
|
||||
lcd->drawSolidHorizontalLine(right - 3, y, 3, TEXT_COLOR);
|
||||
lcd->drawSolidHorizontalLine(right - 3, y + BAR_HEIGHT - 1, 3, TEXT_COLOR);
|
||||
}
|
||||
|
||||
void drawSingleMixerBar(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t channel)
|
||||
{
|
||||
int16_t chanVal = calcRESXto100(ex_chans[channel]);
|
||||
const int16_t displayVal = chanVal;
|
||||
|
||||
// this could be handled nicer, but slower, by checking actual range for this mixer
|
||||
chanVal = limit<int16_t>(-VIEW_CHANNELS_LIMIT_PCT, chanVal, VIEW_CHANNELS_LIMIT_PCT);
|
||||
|
||||
lcdDrawSolidFilledRect(x, y, w, h, BARGRAPH_BGCOLOR);
|
||||
if (chanVal > 0) {
|
||||
lcdDrawSolidFilledRect(x + w / 2, y, divRoundClosest(chanVal * w, VIEW_CHANNELS_LIMIT_PCT * 2), h, BARGRAPH2_COLOR);
|
||||
lcdDrawNumber(x - 10 + w / 2, y - 2, displayVal, SMLSIZE | TEXT_COLOR | RIGHT, 0, NULL, "%");
|
||||
}
|
||||
else if (chanVal < 0) {
|
||||
const uint16_t endpoint = x + w / 2;
|
||||
const uint16_t size = divRoundClosest(-chanVal * w, VIEW_CHANNELS_LIMIT_PCT * 2);
|
||||
lcdDrawSolidFilledRect(endpoint - size, y, size, h, BARGRAPH2_COLOR);
|
||||
lcdDrawNumber(x + 10 + w / 2, y - 2, displayVal, SMLSIZE | TEXT_COLOR, 0, NULL, "%");
|
||||
}
|
||||
|
||||
lcd->drawSolidVerticalLine(x + w / 2, y, h, TEXT_COLOR);
|
||||
}
|
||||
|
||||
void drawSingleOutputBar(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t channel)
|
||||
{
|
||||
int16_t chanVal = calcRESXto100(channelOutputs[channel]);
|
||||
int16_t displayVal = chanVal;
|
||||
|
||||
chanVal = limit<int16_t>(-VIEW_CHANNELS_LIMIT_PCT, chanVal, VIEW_CHANNELS_LIMIT_PCT);
|
||||
|
||||
lcdDrawSolidFilledRect(x, y, w, h, BARGRAPH_BGCOLOR);
|
||||
if (chanVal > 0) {
|
||||
lcdDrawSolidFilledRect(x + w / 2, y, divRoundClosest(chanVal * w, VIEW_CHANNELS_LIMIT_PCT * 2), h, BARGRAPH1_COLOR);
|
||||
lcdDrawNumber(x - 10 + w / 2, y - 2, displayVal, SMLSIZE | TEXT_COLOR | RIGHT, 0, NULL, "%");
|
||||
}
|
||||
else if (chanVal < 0) {
|
||||
uint16_t endpoint = x + w / 2;
|
||||
uint16_t size = divRoundClosest(-chanVal * w, VIEW_CHANNELS_LIMIT_PCT * 2);
|
||||
lcdDrawSolidFilledRect(endpoint - size, y, size, h, BARGRAPH1_COLOR);
|
||||
lcdDrawNumber(x + 10 + w / 2, y - 2, displayVal, SMLSIZE | TEXT_COLOR, 0, NULL, "%");
|
||||
}
|
||||
|
||||
lcd->drawSolidVerticalLine(x + w / 2, y, h, TEXT_COLOR);
|
||||
}
|
||||
|
||||
void drawComboOutputBar(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t channel)
|
||||
{
|
||||
char chanString[] = "Ch32 ";
|
||||
int16_t chanVal = calcRESXto100(channelOutputs[channel]);
|
||||
LimitData * ld = limitAddress(channel);
|
||||
int usValue = PPM_CH_CENTER(channel) + channelOutputs[channel] / 2;
|
||||
const uint16_t limPos = ld ? posOnBar(calcRESXto100(ld->offset)) : 0;
|
||||
uint16_t valPos;
|
||||
|
||||
strAppendSigned(&chanString[2], channel + 1, 2);
|
||||
lcdDrawText(x, y, chanString, SMLSIZE | TEXT_COLOR | LEFT);
|
||||
|
||||
lcdDrawSizedText(x + 45, y, g_model.limitData[channel].name, sizeof(g_model.limitData[channel].name), SMLSIZE | TEXT_COLOR | LEFT | ZCHAR);
|
||||
lcdDrawNumber(x + w, y, usValue, SMLSIZE | TEXT_COLOR | RIGHT, 0, NULL, STR_US);
|
||||
|
||||
lcdDrawSolidFilledRect(x, y + Y_OUTBAR, w, h, BARGRAPH_BGCOLOR);
|
||||
lcd->drawSolidVerticalLine(x + limPos, y + Y_OUTBAR, h, MAINVIEW_GRAPHICS_COLOR);
|
||||
|
||||
if (chanVal > 0)
|
||||
lcdDrawNumber(x - 10 + w / 2, y + h, chanVal, SMLSIZE | TEXT_COLOR | RIGHT, 0, NULL, "%");
|
||||
else
|
||||
lcdDrawNumber(x + 10 + w / 2, y + h, chanVal, SMLSIZE | TEXT_COLOR, 0, NULL, "%");
|
||||
|
||||
chanVal = limit<int16_t>(-VIEW_CHANNELS_LIMIT_PCT, chanVal, VIEW_CHANNELS_LIMIT_PCT);
|
||||
valPos = posOnBar(chanVal);
|
||||
|
||||
if (valPos > limPos) {
|
||||
lcdDrawSolidFilledRect(x + limPos, y + Y_OUTBAR, valPos - limPos, h, BARGRAPH1_COLOR);
|
||||
}
|
||||
else if (valPos < limPos) {
|
||||
uint16_t endpoint = x + limPos;
|
||||
uint16_t size = limPos - valPos;
|
||||
lcdDrawSolidFilledRect(endpoint - size, y + Y_OUTBAR, size, h, BARGRAPH1_COLOR);
|
||||
}
|
||||
|
||||
if (ld && ld->revert) {
|
||||
drawOutputBarLimits(x + posOnBar(-100 - ld->max / 10), x + posOnBar(100 - ld->min / 10), y + Y_OUTBAR);
|
||||
lcd->drawBitmap(x - X_OFFSET + 7, y + 25, chanMonInvertedBitmap);
|
||||
}
|
||||
else if (ld) {
|
||||
drawOutputBarLimits(x + posOnBar(-100 + ld->min / 10), x + posOnBar(100 + ld->max / 10), y + Y_OUTBAR);
|
||||
}
|
||||
#if defined(OVERRIDE_CHANNEL_FUNCTION)
|
||||
if (safetyCh[channel] != OVERRIDE_CHANNEL_UNDEFINED)
|
||||
lcd->drawBitmap(x - X_OFFSET + 7, y + 7, chanMonLockedBitmap);
|
||||
#endif
|
||||
lcd->drawSolidVerticalLine(x + w / 2, y + Y_OUTBAR, h, TEXT_COLOR);
|
||||
}
|
||||
|
||||
coord_t drawChannelsMonitorLegend(coord_t x, const pm_char * s, int color)
|
||||
{
|
||||
lcdDrawSolidFilledRect(x, MENU_FOOTER_TOP + 2, LEG_COLORBOX + 2, LEG_COLORBOX + 2, BARGRAPH_BGCOLOR);
|
||||
lcdDrawSolidFilledRect(x + 1, MENU_FOOTER_TOP + 3, LEG_COLORBOX, LEG_COLORBOX, color);
|
||||
lcdDrawText(x + 20, MENU_FOOTER_TOP, s, TEXT_STATUSBAR_COLOR);
|
||||
return x + 25 + getTextWidth(s);
|
||||
}
|
||||
|
||||
bool menuChannelsMonitor(event_t event, uint8_t page)
|
||||
{
|
||||
uint8_t channel = 8 * page;
|
||||
coord_t x, y = Y_OFFSET;
|
||||
|
||||
x = drawChannelsMonitorLegend(MENUS_MARGIN_LEFT, STR_MONITOR_OUTPUT_DESC, BARGRAPH1_COLOR);
|
||||
drawChannelsMonitorLegend(x, STR_MONITOR_MIXER_DESC, BARGRAPH2_COLOR);
|
||||
|
||||
x = X_OFFSET;
|
||||
for (uint8_t i = 0; i < 8; i++, channel++, y += ROW_HEIGHT) {
|
||||
if (i == 4) {
|
||||
x = 1 + LCD_W / 2 + X_OFFSET;
|
||||
y = Y_OFFSET;
|
||||
}
|
||||
drawComboOutputBar(x, y, COLUMN_SIZE, BAR_HEIGHT, channel);
|
||||
drawSingleMixerBar(x, y + Y_MIXBAR + 1, COLUMN_SIZE, BAR_HEIGHT, channel);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 RECT_OFFSET 80
|
||||
#define ROW_HEIGHT 42
|
||||
#define BAR_HEIGHT 13
|
||||
#define COLUMN_SIZE 200
|
||||
#define X_OFFSET 25
|
||||
#define Y_OFFSET 75
|
||||
#define Y_OUTBAR 15
|
||||
#define Y_MIXBAR 28
|
||||
#define LEG_COLORBOX 15
|
||||
|
||||
#define VIEW_CHANNELS_LIMIT_PCT (g_model.extendedLimits ? LIMIT_EXT_PERCENT : 100)
|
||||
|
||||
bool menuChannelsMonitor(event_t event, uint8_t page);
|
||||
bool menuLogicalSwitches(event_t);
|
||||
|
||||
template<int index>
|
||||
bool menuChannelsMonitor(event_t event)
|
||||
{
|
||||
lastMonitorPage = e_MonChannelsFirst + index;
|
||||
MENU(STR_MONITOR_CHANNELS[index], MONITOR_ICONS, menuTabMonitors, lastMonitorPage, 0, { 0 });
|
||||
return menuChannelsMonitor(event, index);
|
||||
}
|
||||
|
||||
const MenuHandlerFunc menuTabMonitors[] PROGMEM = {
|
||||
menuChannelsMonitor<0>,
|
||||
menuChannelsMonitor<1>,
|
||||
menuChannelsMonitor<2>,
|
||||
menuChannelsMonitor<3>,
|
||||
menuLogicalSwitches
|
||||
};
|
||||
|
||||
uint8_t lastMonitorPage = 0;
|
||||
|
||||
uint16_t posOnBar(int16_t value_to100)
|
||||
{
|
||||
return divRoundClosest((value_to100 + VIEW_CHANNELS_LIMIT_PCT) * COLUMN_SIZE, VIEW_CHANNELS_LIMIT_PCT * 2);
|
||||
}
|
||||
|
||||
void drawOutputBarLimits(coord_t left, coord_t right, coord_t y)
|
||||
{
|
||||
lcd->drawSolidVerticalLine(left, y, BAR_HEIGHT, TEXT_COLOR);
|
||||
lcd->drawSolidHorizontalLine(left, y, 3, TEXT_COLOR);
|
||||
lcd->drawSolidHorizontalLine(left, y + BAR_HEIGHT - 1, 3, TEXT_COLOR);
|
||||
|
||||
lcd->drawSolidVerticalLine(--right, y, BAR_HEIGHT, TEXT_COLOR);
|
||||
lcd->drawSolidHorizontalLine(right - 3, y, 3, TEXT_COLOR);
|
||||
lcd->drawSolidHorizontalLine(right - 3, y + BAR_HEIGHT - 1, 3, TEXT_COLOR);
|
||||
}
|
||||
|
||||
void drawSingleMixerBar(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t channel)
|
||||
{
|
||||
int16_t chanVal = calcRESXto100(ex_chans[channel]);
|
||||
const int16_t displayVal = chanVal;
|
||||
|
||||
// this could be handled nicer, but slower, by checking actual range for this mixer
|
||||
chanVal = limit<int16_t>(-VIEW_CHANNELS_LIMIT_PCT, chanVal, VIEW_CHANNELS_LIMIT_PCT);
|
||||
|
||||
lcdDrawSolidFilledRect(x, y, w, h, BARGRAPH_BGCOLOR);
|
||||
if (chanVal > 0) {
|
||||
lcdDrawSolidFilledRect(x + w / 2, y, divRoundClosest(chanVal * w, VIEW_CHANNELS_LIMIT_PCT * 2), h, BARGRAPH2_COLOR);
|
||||
lcdDrawNumber(x - 10 + w / 2, y - 2, displayVal, SMLSIZE | TEXT_COLOR | RIGHT, 0, NULL, "%");
|
||||
}
|
||||
else if (chanVal < 0) {
|
||||
const uint16_t endpoint = x + w / 2;
|
||||
const uint16_t size = divRoundClosest(-chanVal * w, VIEW_CHANNELS_LIMIT_PCT * 2);
|
||||
lcdDrawSolidFilledRect(endpoint - size, y, size, h, BARGRAPH2_COLOR);
|
||||
lcdDrawNumber(x + 10 + w / 2, y - 2, displayVal, SMLSIZE | TEXT_COLOR, 0, NULL, "%");
|
||||
}
|
||||
|
||||
lcd->drawSolidVerticalLine(x + w / 2, y, h, TEXT_COLOR);
|
||||
}
|
||||
|
||||
void drawSingleOutputBar(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t channel)
|
||||
{
|
||||
int16_t chanVal = calcRESXto100(channelOutputs[channel]);
|
||||
int16_t displayVal = chanVal;
|
||||
|
||||
chanVal = limit<int16_t>(-VIEW_CHANNELS_LIMIT_PCT, chanVal, VIEW_CHANNELS_LIMIT_PCT);
|
||||
|
||||
lcdDrawSolidFilledRect(x, y, w, h, BARGRAPH_BGCOLOR);
|
||||
if (chanVal > 0) {
|
||||
lcdDrawSolidFilledRect(x + w / 2, y, divRoundClosest(chanVal * w, VIEW_CHANNELS_LIMIT_PCT * 2), h, BARGRAPH1_COLOR);
|
||||
lcdDrawNumber(x - 10 + w / 2, y - 2, displayVal, SMLSIZE | TEXT_COLOR | RIGHT, 0, NULL, "%");
|
||||
}
|
||||
else if (chanVal < 0) {
|
||||
uint16_t endpoint = x + w / 2;
|
||||
uint16_t size = divRoundClosest(-chanVal * w, VIEW_CHANNELS_LIMIT_PCT * 2);
|
||||
lcdDrawSolidFilledRect(endpoint - size, y, size, h, BARGRAPH1_COLOR);
|
||||
lcdDrawNumber(x + 10 + w / 2, y - 2, displayVal, SMLSIZE | TEXT_COLOR, 0, NULL, "%");
|
||||
}
|
||||
|
||||
lcd->drawSolidVerticalLine(x + w / 2, y, h, TEXT_COLOR);
|
||||
}
|
||||
|
||||
void drawComboOutputBar(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t channel)
|
||||
{
|
||||
char chanString[] = "Ch32 ";
|
||||
int16_t chanVal = calcRESXto100(channelOutputs[channel]);
|
||||
LimitData * ld = limitAddress(channel);
|
||||
int usValue = PPM_CH_CENTER(channel) + channelOutputs[channel] / 2;
|
||||
const uint16_t limPos = ld ? posOnBar(calcRESXto100(ld->offset)) : 0;
|
||||
uint16_t valPos;
|
||||
|
||||
strAppendSigned(&chanString[2], channel + 1, 2);
|
||||
lcdDrawText(x, y, chanString, SMLSIZE | TEXT_COLOR | LEFT);
|
||||
|
||||
lcdDrawSizedText(x + 45, y, g_model.limitData[channel].name, sizeof(g_model.limitData[channel].name), SMLSIZE | TEXT_COLOR | LEFT | ZCHAR);
|
||||
lcdDrawNumber(x + w, y, usValue, SMLSIZE | TEXT_COLOR | RIGHT, 0, NULL, STR_US);
|
||||
|
||||
lcdDrawSolidFilledRect(x, y + Y_OUTBAR, w, h, BARGRAPH_BGCOLOR);
|
||||
lcd->drawSolidVerticalLine(x + limPos, y + Y_OUTBAR, h, MAINVIEW_GRAPHICS_COLOR);
|
||||
|
||||
if (chanVal > 0)
|
||||
lcdDrawNumber(x - 10 + w / 2, y + h, chanVal, SMLSIZE | TEXT_COLOR | RIGHT, 0, NULL, "%");
|
||||
else
|
||||
lcdDrawNumber(x + 10 + w / 2, y + h, chanVal, SMLSIZE | TEXT_COLOR, 0, NULL, "%");
|
||||
|
||||
chanVal = limit<int16_t>(-VIEW_CHANNELS_LIMIT_PCT, chanVal, VIEW_CHANNELS_LIMIT_PCT);
|
||||
valPos = posOnBar(chanVal);
|
||||
|
||||
if (valPos > limPos) {
|
||||
lcdDrawSolidFilledRect(x + limPos, y + Y_OUTBAR, valPos - limPos, h, BARGRAPH1_COLOR);
|
||||
}
|
||||
else if (valPos < limPos) {
|
||||
uint16_t endpoint = x + limPos;
|
||||
uint16_t size = limPos - valPos;
|
||||
lcdDrawSolidFilledRect(endpoint - size, y + Y_OUTBAR, size, h, BARGRAPH1_COLOR);
|
||||
}
|
||||
|
||||
if (ld && ld->revert) {
|
||||
drawOutputBarLimits(x + posOnBar(-100 - ld->max / 10), x + posOnBar(100 - ld->min / 10), y + Y_OUTBAR);
|
||||
lcd->drawBitmap(x - X_OFFSET + 7, y + 25, chanMonInvertedBitmap);
|
||||
}
|
||||
else if (ld) {
|
||||
drawOutputBarLimits(x + posOnBar(-100 + ld->min / 10), x + posOnBar(100 + ld->max / 10), y + Y_OUTBAR);
|
||||
}
|
||||
#if defined(OVERRIDE_CHANNEL_FUNCTION)
|
||||
if (safetyCh[channel] != OVERRIDE_CHANNEL_UNDEFINED)
|
||||
lcd->drawBitmap(x - X_OFFSET + 7, y + 7, chanMonLockedBitmap);
|
||||
#endif
|
||||
lcd->drawSolidVerticalLine(x + w / 2, y + Y_OUTBAR, h, TEXT_COLOR);
|
||||
}
|
||||
|
||||
coord_t drawChannelsMonitorLegend(coord_t x, const pm_char * s, int color)
|
||||
{
|
||||
lcdDrawSolidFilledRect(x, MENU_FOOTER_TOP + 2, LEG_COLORBOX + 2, LEG_COLORBOX + 2, BARGRAPH_BGCOLOR);
|
||||
lcdDrawSolidFilledRect(x + 1, MENU_FOOTER_TOP + 3, LEG_COLORBOX, LEG_COLORBOX, color);
|
||||
lcdDrawText(x + 20, MENU_FOOTER_TOP, s, TEXT_STATUSBAR_COLOR);
|
||||
return x + 25 + getTextWidth(s);
|
||||
}
|
||||
|
||||
bool menuChannelsMonitor(event_t event, uint8_t page)
|
||||
{
|
||||
uint8_t channel = 8 * page;
|
||||
coord_t x, y = Y_OFFSET;
|
||||
|
||||
x = drawChannelsMonitorLegend(MENUS_MARGIN_LEFT, STR_MONITOR_OUTPUT_DESC, BARGRAPH1_COLOR);
|
||||
drawChannelsMonitorLegend(x, STR_MONITOR_MIXER_DESC, BARGRAPH2_COLOR);
|
||||
|
||||
x = X_OFFSET;
|
||||
for (uint8_t i = 0; i < 8; i++, channel++, y += ROW_HEIGHT) {
|
||||
if (i == 4) {
|
||||
x = 1 + LCD_W / 2 + X_OFFSET;
|
||||
y = Y_OFFSET;
|
||||
}
|
||||
drawComboOutputBar(x, y, COLUMN_SIZE, BAR_HEIGHT, channel);
|
||||
drawSingleMixerBar(x, y + Y_MIXBAR + 1, COLUMN_SIZE, BAR_HEIGHT, channel);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,238 +1,238 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 "stamp.h"
|
||||
|
||||
#define MENU_STATS_COLUMN1 (MENUS_MARGIN_LEFT + 120)
|
||||
#define MENU_STATS_COLUMN2 (LCD_W/2)
|
||||
#define MENU_STATS_COLUMN3 (LCD_W/2 + 120)
|
||||
|
||||
bool menuStatsGraph(event_t event)
|
||||
{
|
||||
switch(event) {
|
||||
case EVT_KEY_LONG(KEY_ENTER):
|
||||
g_eeGeneral.globalTimer = 0;
|
||||
storageDirty(EE_GENERAL);
|
||||
sessionTimer = 0;
|
||||
killEvents(event);
|
||||
break;
|
||||
}
|
||||
|
||||
MENU(STR_STATISTICS, STATS_ICONS, menuTabStats, e_StatsGraph, 0, { 0 });
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP, "Session");
|
||||
drawTimer(MENU_STATS_COLUMN1, MENU_CONTENT_TOP, sessionTimer, TIMEHOUR);
|
||||
lcdDrawText(MENU_STATS_COLUMN2, MENU_CONTENT_TOP, "Battery");
|
||||
drawTimer(MENU_STATS_COLUMN3, MENU_CONTENT_TOP, g_eeGeneral.globalTimer+sessionTimer, TIMEHOUR);
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+FH, "Throttle");
|
||||
drawTimer(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+FH, s_timeCumThr, TIMEHOUR);
|
||||
lcdDrawText(MENU_STATS_COLUMN2, MENU_CONTENT_TOP+FH, "Throttle %", TIMEHOUR);
|
||||
drawTimer(MENU_STATS_COLUMN3, MENU_CONTENT_TOP+FH, s_timeCum16ThrP/16, TIMEHOUR);
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+2*FH, "Timers");
|
||||
lcdDrawText(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+2*FH, "[1]", HEADER_COLOR);
|
||||
drawTimer(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, timersStates[0].val, TIMEHOUR);
|
||||
lcdDrawText(MENU_STATS_COLUMN2, MENU_CONTENT_TOP+2*FH, "[2]", HEADER_COLOR);
|
||||
drawTimer(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, timersStates[1].val, TIMEHOUR);
|
||||
#if TIMERS > 2
|
||||
lcdDrawText(MENU_STATS_COLUMN3, MENU_CONTENT_TOP+2*FH, "[3]", HEADER_COLOR);
|
||||
drawTimer(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, timersStates[2].val, TIMEHOUR);
|
||||
#endif
|
||||
|
||||
const coord_t x = 10;
|
||||
const coord_t y = 240;
|
||||
lcdDrawHorizontalLine(x-3, y, MAXTRACE+3+3, SOLID, TEXT_COLOR);
|
||||
lcdDrawVerticalLine(x, y-96, 96+3, SOLID, TEXT_COLOR);
|
||||
for (coord_t i=0; i<MAXTRACE; i+=6) {
|
||||
lcdDrawVerticalLine(x+i, y-1, 3, SOLID, TEXT_COLOR);
|
||||
}
|
||||
|
||||
uint16_t traceRd = s_traceWr > MAXTRACE ? s_traceWr - MAXTRACE : 0;
|
||||
coord_t prev_yv = (coord_t)-1;
|
||||
for (coord_t i=1; i<=MAXTRACE && traceRd<s_traceWr; i++, traceRd++) {
|
||||
uint8_t h = s_traceBuf[traceRd % MAXTRACE];
|
||||
coord_t yv = y - 2 - 3*h;
|
||||
if (prev_yv != (coord_t)-1) {
|
||||
if (prev_yv < yv) {
|
||||
for (int y=prev_yv; y<=yv; y++) {
|
||||
lcdDrawBitmapPattern(x + i - 3, y, LBM_POINT, TEXT_COLOR);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int y=yv; y<=prev_yv; y++) {
|
||||
lcdDrawBitmapPattern(x + i - 3, y, LBM_POINT, TEXT_COLOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
lcdDrawBitmapPattern(x + i - 3, yv, LBM_POINT, TEXT_COLOR);
|
||||
}
|
||||
prev_yv = yv;
|
||||
}
|
||||
|
||||
lcdDrawText(LCD_W/2, MENU_FOOTER_TOP+2, STR_MENUTORESET, CENTERED);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool menuStatsDebug(event_t event)
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
case EVT_KEY_FIRST(KEY_ENTER):
|
||||
maxMixerDuration = 0;
|
||||
#if defined(LUA)
|
||||
maxLuaInterval = 0;
|
||||
maxLuaDuration = 0;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
MENU("Debug", STATS_ICONS, menuTabStats, e_StatsDebug, 0, { 0 });
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP, "Free Mem");
|
||||
lcdDrawNumber(MENU_STATS_COLUMN1, MENU_CONTENT_TOP, availableMemory(), LEFT, 0, NULL, "b");
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+FH, STR_TMIXMAXMS);
|
||||
lcdDrawNumber(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+FH, DURATION_MS_PREC2(maxMixerDuration), PREC2|LEFT, 0, NULL, "ms");
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+2*FH, STR_FREESTACKMINB);
|
||||
lcdDrawText(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+2*FH+1, "[Menus]", HEADER_COLOR|SMLSIZE);
|
||||
lcdDrawNumber(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, menusStack.available(), LEFT);
|
||||
lcdDrawText(lcdNextPos+20, MENU_CONTENT_TOP+2*FH+1, "[Mix]", HEADER_COLOR|SMLSIZE);
|
||||
lcdDrawNumber(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, mixerStack.available(), LEFT);
|
||||
lcdDrawText(lcdNextPos+20, MENU_CONTENT_TOP+2*FH+1, "[Audio]", HEADER_COLOR|SMLSIZE);
|
||||
lcdDrawNumber(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, audioStack.available(), LEFT);
|
||||
|
||||
int line = 3;
|
||||
|
||||
#if defined(DISK_CACHE)
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+line*FH, "SD cache hits");
|
||||
lcdDrawNumber(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+line*FH, diskCache.getHitRate(), PREC1|LEFT, 0, NULL, "%");
|
||||
++line;
|
||||
#endif
|
||||
|
||||
#if defined(LUA)
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+line*FH, "Lua duration");
|
||||
lcdDrawNumber(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+line*FH, 10*maxLuaDuration, LEFT, 0, NULL, "ms");
|
||||
++line;
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+line*FH, "Lua interval");
|
||||
lcdDrawNumber(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+line*FH, 10*maxLuaInterval, LEFT, 0, NULL, "ms");
|
||||
++line;
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+line*FH, "Lua memory");
|
||||
lcdDrawText(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+line*FH+1, "[S]", HEADER_COLOR|SMLSIZE);
|
||||
lcdDrawNumber(lcdNextPos+5, MENU_CONTENT_TOP+line*FH, luaGetMemUsed(lsScripts), LEFT);
|
||||
lcdDrawText(lcdNextPos+20, MENU_CONTENT_TOP+line*FH+1, "[W]", HEADER_COLOR|SMLSIZE);
|
||||
lcdDrawNumber(lcdNextPos+5, MENU_CONTENT_TOP+line*FH, luaGetMemUsed(lsWidgets), LEFT);
|
||||
lcdDrawText(lcdNextPos+20, MENU_CONTENT_TOP+line*FH+1, "[B]", HEADER_COLOR|SMLSIZE);
|
||||
lcdDrawNumber(lcdNextPos+5, MENU_CONTENT_TOP+line*FH, luaExtraMemoryUsage, LEFT);
|
||||
++line;
|
||||
|
||||
#endif
|
||||
|
||||
lcdDrawText(LCD_W/2, MENU_FOOTER_TOP+2, STR_MENUTORESET, CENTERED);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool menuStatsAnalogs(event_t event)
|
||||
{
|
||||
MENU("Analogs", STATS_ICONS, menuTabStats, e_StatsAnalogs, 0, { 0 });
|
||||
|
||||
for (uint8_t i=0; i<NUM_ANALOGS; i++) {
|
||||
coord_t y = MENU_CONTENT_TOP + (i/2)*FH;
|
||||
coord_t x = MENUS_MARGIN_LEFT + (i & 1 ? LCD_W/2 : 0);
|
||||
lcdDrawNumber(x, y, i+1, LEADING0|LEFT, 2, NULL, ":");
|
||||
lcdDrawHexNumber(x+40, y, anaIn(i));
|
||||
#if defined(JITTER_MEASURE)
|
||||
lcdDrawNumber(x+100, y, rawJitter[i].get());
|
||||
lcdDrawNumber(x+140, y, avgJitter[i].get());
|
||||
lcdDrawNumber(x+180, y, (int16_t)calibratedAnalogs[CONVERT_MODE(i)]*250/256, PREC1);
|
||||
#else
|
||||
if (i < NUM_STICKS+NUM_POTS+NUM_SLIDERS)
|
||||
lcdDrawNumber(x+100, y, (int16_t)calibratedAnalogs[CONVERT_MODE(i)]*25/256);
|
||||
else if (i >= MOUSE1)
|
||||
lcdDrawNumber(x+100, y, (int16_t)calibratedAnalogs[CALIBRATED_MOUSE1+i-MOUSE1]*25/256);
|
||||
#endif
|
||||
}
|
||||
|
||||
// SWR
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+7*FH, "RAS");
|
||||
lcdDrawNumber(MENUS_MARGIN_LEFT+100, MENU_CONTENT_TOP+7*FH, telemetryData.swr.value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEBUG_TRACE_BUFFER)
|
||||
#define STATS_TRACES_INDEX_POS MENUS_MARGIN_LEFT
|
||||
#define STATS_TRACES_TIME_POS MENUS_MARGIN_LEFT + 4*10
|
||||
#define STATS_TRACES_EVENT_POS MENUS_MARGIN_LEFT + 14*10
|
||||
#define STATS_TRACES_DATA_POS MENUS_MARGIN_LEFT + 20*10
|
||||
|
||||
bool menuStatsTraces(event_t event)
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
case EVT_KEY_LONG(KEY_ENTER):
|
||||
dumpTraceBuffer();
|
||||
killEvents(event);
|
||||
break;
|
||||
}
|
||||
|
||||
SIMPLE_MENU("", STATS_ICONS, menuTabStats, e_StatsTraces, TRACE_BUFFER_LEN);
|
||||
|
||||
uint8_t k = 0;
|
||||
int8_t sub = menuVerticalPosition;
|
||||
|
||||
lcdDrawChar(STATS_TRACES_INDEX_POS, MENU_TITLE_TOP+2, '#', MENU_TITLE_COLOR);
|
||||
lcdDrawText(STATS_TRACES_TIME_POS, MENU_TITLE_TOP+2, "Time", MENU_TITLE_COLOR);
|
||||
lcdDrawText(STATS_TRACES_EVENT_POS, MENU_TITLE_TOP+2, "Event", MENU_TITLE_COLOR);
|
||||
lcdDrawText(STATS_TRACES_DATA_POS, MENU_TITLE_TOP+2, "Data", MENU_TITLE_COLOR);
|
||||
|
||||
for (uint8_t i=0; i<NUM_BODY_LINES; i++) {
|
||||
coord_t y = MENU_CONTENT_TOP + i * FH;
|
||||
k = i+menuVerticalOffset;
|
||||
|
||||
// item
|
||||
lcdDrawNumber(STATS_TRACES_INDEX_POS, y, k, LEFT | (sub==k ? INVERS : 0));
|
||||
|
||||
const struct TraceElement * te = getTraceElement(k);
|
||||
if (te) {
|
||||
// time
|
||||
putstime_t tme = te->time % SECS_PER_DAY;
|
||||
drawTimer(STATS_TRACES_TIME_POS, y, tme, TIMEHOUR|LEFT);
|
||||
// event
|
||||
lcdDrawNumber(STATS_TRACES_EVENT_POS, y, te->event, LEADING0|LEFT, 3);
|
||||
// data
|
||||
lcdDrawSizedText(STATS_TRACES_DATA_POS, y, "0x", 2);
|
||||
lcdDrawHexNumber(lcdNextPos, y, (uint16_t)(te->data >> 16));
|
||||
lcdDrawHexNumber(lcdNextPos, y, (uint16_t)(te->data & 0xFFFF));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // defined(DEBUG_TRACE_BUFFER)
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 "stamp.h"
|
||||
|
||||
#define MENU_STATS_COLUMN1 (MENUS_MARGIN_LEFT + 120)
|
||||
#define MENU_STATS_COLUMN2 (LCD_W/2)
|
||||
#define MENU_STATS_COLUMN3 (LCD_W/2 + 120)
|
||||
|
||||
bool menuStatsGraph(event_t event)
|
||||
{
|
||||
switch(event) {
|
||||
case EVT_KEY_LONG(KEY_ENTER):
|
||||
g_eeGeneral.globalTimer = 0;
|
||||
storageDirty(EE_GENERAL);
|
||||
sessionTimer = 0;
|
||||
killEvents(event);
|
||||
break;
|
||||
}
|
||||
|
||||
MENU(STR_STATISTICS, STATS_ICONS, menuTabStats, e_StatsGraph, 0, { 0 });
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP, "Session");
|
||||
drawTimer(MENU_STATS_COLUMN1, MENU_CONTENT_TOP, sessionTimer, TIMEHOUR);
|
||||
lcdDrawText(MENU_STATS_COLUMN2, MENU_CONTENT_TOP, "Battery");
|
||||
drawTimer(MENU_STATS_COLUMN3, MENU_CONTENT_TOP, g_eeGeneral.globalTimer+sessionTimer, TIMEHOUR);
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+FH, "Throttle");
|
||||
drawTimer(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+FH, s_timeCumThr, TIMEHOUR);
|
||||
lcdDrawText(MENU_STATS_COLUMN2, MENU_CONTENT_TOP+FH, "Throttle %", TIMEHOUR);
|
||||
drawTimer(MENU_STATS_COLUMN3, MENU_CONTENT_TOP+FH, s_timeCum16ThrP/16, TIMEHOUR);
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+2*FH, "Timers");
|
||||
lcdDrawText(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+2*FH, "[1]", HEADER_COLOR);
|
||||
drawTimer(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, timersStates[0].val, TIMEHOUR);
|
||||
lcdDrawText(MENU_STATS_COLUMN2, MENU_CONTENT_TOP+2*FH, "[2]", HEADER_COLOR);
|
||||
drawTimer(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, timersStates[1].val, TIMEHOUR);
|
||||
#if TIMERS > 2
|
||||
lcdDrawText(MENU_STATS_COLUMN3, MENU_CONTENT_TOP+2*FH, "[3]", HEADER_COLOR);
|
||||
drawTimer(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, timersStates[2].val, TIMEHOUR);
|
||||
#endif
|
||||
|
||||
const coord_t x = 10;
|
||||
const coord_t y = 240;
|
||||
lcdDrawHorizontalLine(x-3, y, MAXTRACE+3+3, SOLID, TEXT_COLOR);
|
||||
lcdDrawVerticalLine(x, y-96, 96+3, SOLID, TEXT_COLOR);
|
||||
for (coord_t i=0; i<MAXTRACE; i+=6) {
|
||||
lcdDrawVerticalLine(x+i, y-1, 3, SOLID, TEXT_COLOR);
|
||||
}
|
||||
|
||||
uint16_t traceRd = s_traceWr > MAXTRACE ? s_traceWr - MAXTRACE : 0;
|
||||
coord_t prev_yv = (coord_t)-1;
|
||||
for (coord_t i=1; i<=MAXTRACE && traceRd<s_traceWr; i++, traceRd++) {
|
||||
uint8_t h = s_traceBuf[traceRd % MAXTRACE];
|
||||
coord_t yv = y - 2 - 3*h;
|
||||
if (prev_yv != (coord_t)-1) {
|
||||
if (prev_yv < yv) {
|
||||
for (int y=prev_yv; y<=yv; y++) {
|
||||
lcdDrawBitmapPattern(x + i - 3, y, LBM_POINT, TEXT_COLOR);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int y=yv; y<=prev_yv; y++) {
|
||||
lcdDrawBitmapPattern(x + i - 3, y, LBM_POINT, TEXT_COLOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
lcdDrawBitmapPattern(x + i - 3, yv, LBM_POINT, TEXT_COLOR);
|
||||
}
|
||||
prev_yv = yv;
|
||||
}
|
||||
|
||||
lcdDrawText(LCD_W/2, MENU_FOOTER_TOP+2, STR_MENUTORESET, CENTERED);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool menuStatsDebug(event_t event)
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
case EVT_KEY_FIRST(KEY_ENTER):
|
||||
maxMixerDuration = 0;
|
||||
#if defined(LUA)
|
||||
maxLuaInterval = 0;
|
||||
maxLuaDuration = 0;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
MENU("Debug", STATS_ICONS, menuTabStats, e_StatsDebug, 0, { 0 });
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP, "Free Mem");
|
||||
lcdDrawNumber(MENU_STATS_COLUMN1, MENU_CONTENT_TOP, availableMemory(), LEFT, 0, NULL, "b");
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+FH, STR_TMIXMAXMS);
|
||||
lcdDrawNumber(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+FH, DURATION_MS_PREC2(maxMixerDuration), PREC2|LEFT, 0, NULL, "ms");
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+2*FH, STR_FREESTACKMINB);
|
||||
lcdDrawText(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+2*FH+1, "[Menus]", HEADER_COLOR|SMLSIZE);
|
||||
lcdDrawNumber(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, menusStack.available(), LEFT);
|
||||
lcdDrawText(lcdNextPos+20, MENU_CONTENT_TOP+2*FH+1, "[Mix]", HEADER_COLOR|SMLSIZE);
|
||||
lcdDrawNumber(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, mixerStack.available(), LEFT);
|
||||
lcdDrawText(lcdNextPos+20, MENU_CONTENT_TOP+2*FH+1, "[Audio]", HEADER_COLOR|SMLSIZE);
|
||||
lcdDrawNumber(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, audioStack.available(), LEFT);
|
||||
|
||||
int line = 3;
|
||||
|
||||
#if defined(DISK_CACHE)
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+line*FH, "SD cache hits");
|
||||
lcdDrawNumber(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+line*FH, diskCache.getHitRate(), PREC1|LEFT, 0, NULL, "%");
|
||||
++line;
|
||||
#endif
|
||||
|
||||
#if defined(LUA)
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+line*FH, "Lua duration");
|
||||
lcdDrawNumber(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+line*FH, 10*maxLuaDuration, LEFT, 0, NULL, "ms");
|
||||
++line;
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+line*FH, "Lua interval");
|
||||
lcdDrawNumber(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+line*FH, 10*maxLuaInterval, LEFT, 0, NULL, "ms");
|
||||
++line;
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+line*FH, "Lua memory");
|
||||
lcdDrawText(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+line*FH+1, "[S]", HEADER_COLOR|SMLSIZE);
|
||||
lcdDrawNumber(lcdNextPos+5, MENU_CONTENT_TOP+line*FH, luaGetMemUsed(lsScripts), LEFT);
|
||||
lcdDrawText(lcdNextPos+20, MENU_CONTENT_TOP+line*FH+1, "[W]", HEADER_COLOR|SMLSIZE);
|
||||
lcdDrawNumber(lcdNextPos+5, MENU_CONTENT_TOP+line*FH, luaGetMemUsed(lsWidgets), LEFT);
|
||||
lcdDrawText(lcdNextPos+20, MENU_CONTENT_TOP+line*FH+1, "[B]", HEADER_COLOR|SMLSIZE);
|
||||
lcdDrawNumber(lcdNextPos+5, MENU_CONTENT_TOP+line*FH, luaExtraMemoryUsage, LEFT);
|
||||
++line;
|
||||
|
||||
#endif
|
||||
|
||||
lcdDrawText(LCD_W/2, MENU_FOOTER_TOP+2, STR_MENUTORESET, CENTERED);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool menuStatsAnalogs(event_t event)
|
||||
{
|
||||
MENU("Analogs", STATS_ICONS, menuTabStats, e_StatsAnalogs, 0, { 0 });
|
||||
|
||||
for (uint8_t i=0; i<NUM_ANALOGS; i++) {
|
||||
coord_t y = MENU_CONTENT_TOP + (i/2)*FH;
|
||||
coord_t x = MENUS_MARGIN_LEFT + (i & 1 ? LCD_W/2 : 0);
|
||||
lcdDrawNumber(x, y, i+1, LEADING0|LEFT, 2, NULL, ":");
|
||||
lcdDrawHexNumber(x+40, y, anaIn(i));
|
||||
#if defined(JITTER_MEASURE)
|
||||
lcdDrawNumber(x+100, y, rawJitter[i].get());
|
||||
lcdDrawNumber(x+140, y, avgJitter[i].get());
|
||||
lcdDrawNumber(x+180, y, (int16_t)calibratedAnalogs[CONVERT_MODE(i)]*250/256, PREC1);
|
||||
#else
|
||||
if (i < NUM_STICKS+NUM_POTS+NUM_SLIDERS)
|
||||
lcdDrawNumber(x+100, y, (int16_t)calibratedAnalogs[CONVERT_MODE(i)]*25/256);
|
||||
else if (i >= MOUSE1)
|
||||
lcdDrawNumber(x+100, y, (int16_t)calibratedAnalogs[CALIBRATED_MOUSE1+i-MOUSE1]*25/256);
|
||||
#endif
|
||||
}
|
||||
|
||||
// SWR
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+7*FH, "RAS");
|
||||
lcdDrawNumber(MENUS_MARGIN_LEFT+100, MENU_CONTENT_TOP+7*FH, telemetryData.swr.value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEBUG_TRACE_BUFFER)
|
||||
#define STATS_TRACES_INDEX_POS MENUS_MARGIN_LEFT
|
||||
#define STATS_TRACES_TIME_POS MENUS_MARGIN_LEFT + 4*10
|
||||
#define STATS_TRACES_EVENT_POS MENUS_MARGIN_LEFT + 14*10
|
||||
#define STATS_TRACES_DATA_POS MENUS_MARGIN_LEFT + 20*10
|
||||
|
||||
bool menuStatsTraces(event_t event)
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
case EVT_KEY_LONG(KEY_ENTER):
|
||||
dumpTraceBuffer();
|
||||
killEvents(event);
|
||||
break;
|
||||
}
|
||||
|
||||
SIMPLE_MENU("", STATS_ICONS, menuTabStats, e_StatsTraces, TRACE_BUFFER_LEN);
|
||||
|
||||
uint8_t k = 0;
|
||||
int8_t sub = menuVerticalPosition;
|
||||
|
||||
lcdDrawChar(STATS_TRACES_INDEX_POS, MENU_TITLE_TOP+2, '#', MENU_TITLE_COLOR);
|
||||
lcdDrawText(STATS_TRACES_TIME_POS, MENU_TITLE_TOP+2, "Time", MENU_TITLE_COLOR);
|
||||
lcdDrawText(STATS_TRACES_EVENT_POS, MENU_TITLE_TOP+2, "Event", MENU_TITLE_COLOR);
|
||||
lcdDrawText(STATS_TRACES_DATA_POS, MENU_TITLE_TOP+2, "Data", MENU_TITLE_COLOR);
|
||||
|
||||
for (uint8_t i=0; i<NUM_BODY_LINES; i++) {
|
||||
coord_t y = MENU_CONTENT_TOP + i * FH;
|
||||
k = i+menuVerticalOffset;
|
||||
|
||||
// item
|
||||
lcdDrawNumber(STATS_TRACES_INDEX_POS, y, k, LEFT | (sub==k ? INVERS : 0));
|
||||
|
||||
const struct TraceElement * te = getTraceElement(k);
|
||||
if (te) {
|
||||
// time
|
||||
putstime_t tme = te->time % SECS_PER_DAY;
|
||||
drawTimer(STATS_TRACES_TIME_POS, y, tme, TIMEHOUR|LEFT);
|
||||
// event
|
||||
lcdDrawNumber(STATS_TRACES_EVENT_POS, y, te->event, LEADING0|LEFT, 3);
|
||||
// data
|
||||
lcdDrawSizedText(STATS_TRACES_DATA_POS, y, "0x", 2);
|
||||
lcdDrawHexNumber(lcdNextPos, y, (uint16_t)(te->data >> 16));
|
||||
lcdDrawHexNumber(lcdNextPos, y, (uint16_t)(te->data & 0xFFFF));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // defined(DEBUG_TRACE_BUFFER)
|
||||
|
||||
+76
-76
@@ -1,76 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 _HAPTIC_H_
|
||||
#define _HAPTIC_H_
|
||||
|
||||
#define HAPTIC_QUEUE_LENGTH 4
|
||||
|
||||
class hapticQueue
|
||||
{
|
||||
public:
|
||||
|
||||
hapticQueue();
|
||||
|
||||
// only difference between these two functions is that one does the
|
||||
// interupt queue (Now) and the other queues for playing ASAP.
|
||||
void play(uint8_t tLen, uint8_t tPause, uint8_t tRepeat=0);
|
||||
|
||||
inline bool busy() { return (buzzTimeLeft > 0); }
|
||||
|
||||
void event(uint8_t e);
|
||||
|
||||
// heartbeat is responsibile for issueing the haptic buzzs and general square waves
|
||||
// it is essentially the life of the class.
|
||||
void heartbeat();
|
||||
|
||||
// bool freeslots(uint8_t slots);
|
||||
|
||||
inline bool empty() {
|
||||
return (t_queueRidx == t_queueWidx);
|
||||
}
|
||||
|
||||
protected:
|
||||
inline uint8_t getHapticLength(uint8_t tLen) {
|
||||
return ((g_eeGeneral.hapticLength * 2) + tLen) * 2;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t t_queueRidx;
|
||||
uint8_t t_queueWidx;
|
||||
|
||||
uint8_t buzzTimeLeft;
|
||||
uint8_t buzzPause;
|
||||
|
||||
uint8_t hapticTick;
|
||||
|
||||
// queue arrays
|
||||
uint8_t queueHapticLength[HAPTIC_QUEUE_LENGTH];
|
||||
uint8_t queueHapticPause[HAPTIC_QUEUE_LENGTH];
|
||||
uint8_t queueHapticRepeat[HAPTIC_QUEUE_LENGTH];
|
||||
};
|
||||
|
||||
extern hapticQueue haptic;
|
||||
|
||||
#define IS_HAPTIC_BUSY() haptic.busy()
|
||||
#define HAPTIC_HEARTBEAT() haptic.heartbeat()
|
||||
|
||||
|
||||
#endif // _HAPTIC_H_
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 _HAPTIC_H_
|
||||
#define _HAPTIC_H_
|
||||
|
||||
#define HAPTIC_QUEUE_LENGTH 4
|
||||
|
||||
class hapticQueue
|
||||
{
|
||||
public:
|
||||
|
||||
hapticQueue();
|
||||
|
||||
// only difference between these two functions is that one does the
|
||||
// interupt queue (Now) and the other queues for playing ASAP.
|
||||
void play(uint8_t tLen, uint8_t tPause, uint8_t tRepeat=0);
|
||||
|
||||
inline bool busy() { return (buzzTimeLeft > 0); }
|
||||
|
||||
void event(uint8_t e);
|
||||
|
||||
// heartbeat is responsibile for issueing the haptic buzzs and general square waves
|
||||
// it is essentially the life of the class.
|
||||
void heartbeat();
|
||||
|
||||
// bool freeslots(uint8_t slots);
|
||||
|
||||
inline bool empty() {
|
||||
return (t_queueRidx == t_queueWidx);
|
||||
}
|
||||
|
||||
protected:
|
||||
inline uint8_t getHapticLength(uint8_t tLen) {
|
||||
return ((g_eeGeneral.hapticLength * 2) + tLen) * 2;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t t_queueRidx;
|
||||
uint8_t t_queueWidx;
|
||||
|
||||
uint8_t buzzTimeLeft;
|
||||
uint8_t buzzPause;
|
||||
|
||||
uint8_t hapticTick;
|
||||
|
||||
// queue arrays
|
||||
uint8_t queueHapticLength[HAPTIC_QUEUE_LENGTH];
|
||||
uint8_t queueHapticPause[HAPTIC_QUEUE_LENGTH];
|
||||
uint8_t queueHapticRepeat[HAPTIC_QUEUE_LENGTH];
|
||||
};
|
||||
|
||||
extern hapticQueue haptic;
|
||||
|
||||
#define IS_HAPTIC_BUSY() haptic.busy()
|
||||
#define HAPTIC_HEARTBEAT() haptic.heartbeat()
|
||||
|
||||
|
||||
#endif // _HAPTIC_H_
|
||||
|
||||
+113
-113
@@ -1,113 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 _KEYS_H_
|
||||
#define _KEYS_H_
|
||||
|
||||
#define EVT_KEY_MASK(e) ((e) & 0x1f)
|
||||
|
||||
#if defined(PCBHORUS)
|
||||
#define _MSK_KEY_BREAK 0x0200
|
||||
#define _MSK_KEY_REPT 0x0400
|
||||
#define _MSK_KEY_FIRST 0x0600
|
||||
#define _MSK_KEY_LONG 0x0800
|
||||
#define _MSK_KEY_FLAGS 0x0e00
|
||||
#define EVT_ENTRY 0x1000
|
||||
#define EVT_ENTRY_UP 0x2000
|
||||
#else
|
||||
#define _MSK_KEY_BREAK 0x20
|
||||
#define _MSK_KEY_REPT 0x40
|
||||
#define _MSK_KEY_FIRST 0x60
|
||||
#define _MSK_KEY_LONG 0x80
|
||||
#define _MSK_KEY_FLAGS 0xe0
|
||||
#define EVT_ENTRY 0xbf
|
||||
#define EVT_ENTRY_UP 0xbe
|
||||
#endif
|
||||
|
||||
// normal order of events is: FIRST, LONG, REPEAT, REPEAT, ..., BREAK
|
||||
#define EVT_KEY_FIRST(key) ((key)|_MSK_KEY_FIRST) // fired when key is pressed
|
||||
#define EVT_KEY_LONG(key) ((key)|_MSK_KEY_LONG) // fired when key is held pressed for a while
|
||||
#define EVT_KEY_REPT(key) ((key)|_MSK_KEY_REPT) // fired when key is held pressed long enough, fires multiple times with increasing speed
|
||||
#define EVT_KEY_BREAK(key) ((key)|_MSK_KEY_BREAK) // fired when key is released (short or long), but only if the event was not killed
|
||||
|
||||
#define IS_KEY_FIRST(evt) (((evt) & _MSK_KEY_FLAGS) == _MSK_KEY_FIRST)
|
||||
#define IS_KEY_LONG(evt) (((evt) & _MSK_KEY_FLAGS) == _MSK_KEY_LONG)
|
||||
#define IS_KEY_REPT(evt) (((evt) & _MSK_KEY_FLAGS) == _MSK_KEY_REPT)
|
||||
#define IS_KEY_BREAK(evt) (((evt) & _MSK_KEY_FLAGS) == _MSK_KEY_BREAK)
|
||||
|
||||
#if (defined(PCBHORUS) || defined(PCBFLAMENCO) || defined(PCBTARANIS)) && defined(ROTARY_ENCODER_NAVIGATION)
|
||||
typedef uint16_t event_t;
|
||||
#define EVT_ROTARY_BREAK EVT_KEY_BREAK(KEY_ENTER)
|
||||
#define EVT_ROTARY_LONG EVT_KEY_LONG(KEY_ENTER)
|
||||
#define EVT_ROTARY_LEFT 0xDF00
|
||||
#define EVT_ROTARY_RIGHT 0xDE00
|
||||
#define IS_NEXT_EVENT(event) (event==EVT_ROTARY_RIGHT)
|
||||
#define IS_PREVIOUS_EVENT(event) (event==EVT_ROTARY_LEFT)
|
||||
#elif defined(ROTARY_ENCODER_NAVIGATION)
|
||||
typedef uint8_t event_t;
|
||||
#define EVT_ROTARY_BREAK 0xcf
|
||||
#define EVT_ROTARY_LONG 0xce
|
||||
#define EVT_ROTARY_LEFT 0xdf
|
||||
#define EVT_ROTARY_RIGHT 0xde
|
||||
#define IS_NEXT_EVENT(event) (event==EVT_ROTARY_RIGHT || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_REPT(KEY_DOWN))
|
||||
#define IS_PREVIOUS_EVENT(event) (event==EVT_ROTARY_LEFT || event==EVT_KEY_FIRST(KEY_UP) || event==EVT_KEY_REPT(KEY_UP))
|
||||
#else
|
||||
typedef uint8_t event_t;
|
||||
#define IS_NEXT_EVENT(event) (event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_REPT(KEY_DOWN))
|
||||
#define IS_PREVIOUS_EVENT(event) (event==EVT_KEY_FIRST(KEY_UP) || event==EVT_KEY_REPT(KEY_UP))
|
||||
#endif
|
||||
|
||||
#if defined(COLORLCD)
|
||||
#define EVT_REFRESH 0xDD00
|
||||
#endif
|
||||
|
||||
class Key
|
||||
{
|
||||
private:
|
||||
uint8_t m_vals;
|
||||
uint8_t m_cnt;
|
||||
uint8_t m_state;
|
||||
public:
|
||||
void input(bool val);
|
||||
bool state() const { return m_vals > 0; }
|
||||
void pauseEvents();
|
||||
void killEvents();
|
||||
uint8_t key() const;
|
||||
};
|
||||
|
||||
extern Key keys[NUM_KEYS];
|
||||
extern event_t s_evt;
|
||||
|
||||
#define putEvent(evt) s_evt = evt
|
||||
|
||||
void pauseEvents(event_t event);
|
||||
void killEvents(event_t event);
|
||||
|
||||
#if defined(CPUARM)
|
||||
bool clearKeyEvents();
|
||||
event_t getEvent(bool trim=false);
|
||||
#else
|
||||
void clearKeyEvents();
|
||||
event_t getEvent();
|
||||
#endif
|
||||
|
||||
uint8_t keyDown();
|
||||
|
||||
#endif // _KEYS_H_
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 _KEYS_H_
|
||||
#define _KEYS_H_
|
||||
|
||||
#define EVT_KEY_MASK(e) ((e) & 0x1f)
|
||||
|
||||
#if defined(PCBHORUS)
|
||||
#define _MSK_KEY_BREAK 0x0200
|
||||
#define _MSK_KEY_REPT 0x0400
|
||||
#define _MSK_KEY_FIRST 0x0600
|
||||
#define _MSK_KEY_LONG 0x0800
|
||||
#define _MSK_KEY_FLAGS 0x0e00
|
||||
#define EVT_ENTRY 0x1000
|
||||
#define EVT_ENTRY_UP 0x2000
|
||||
#else
|
||||
#define _MSK_KEY_BREAK 0x20
|
||||
#define _MSK_KEY_REPT 0x40
|
||||
#define _MSK_KEY_FIRST 0x60
|
||||
#define _MSK_KEY_LONG 0x80
|
||||
#define _MSK_KEY_FLAGS 0xe0
|
||||
#define EVT_ENTRY 0xbf
|
||||
#define EVT_ENTRY_UP 0xbe
|
||||
#endif
|
||||
|
||||
// normal order of events is: FIRST, LONG, REPEAT, REPEAT, ..., BREAK
|
||||
#define EVT_KEY_FIRST(key) ((key)|_MSK_KEY_FIRST) // fired when key is pressed
|
||||
#define EVT_KEY_LONG(key) ((key)|_MSK_KEY_LONG) // fired when key is held pressed for a while
|
||||
#define EVT_KEY_REPT(key) ((key)|_MSK_KEY_REPT) // fired when key is held pressed long enough, fires multiple times with increasing speed
|
||||
#define EVT_KEY_BREAK(key) ((key)|_MSK_KEY_BREAK) // fired when key is released (short or long), but only if the event was not killed
|
||||
|
||||
#define IS_KEY_FIRST(evt) (((evt) & _MSK_KEY_FLAGS) == _MSK_KEY_FIRST)
|
||||
#define IS_KEY_LONG(evt) (((evt) & _MSK_KEY_FLAGS) == _MSK_KEY_LONG)
|
||||
#define IS_KEY_REPT(evt) (((evt) & _MSK_KEY_FLAGS) == _MSK_KEY_REPT)
|
||||
#define IS_KEY_BREAK(evt) (((evt) & _MSK_KEY_FLAGS) == _MSK_KEY_BREAK)
|
||||
|
||||
#if (defined(PCBHORUS) || defined(PCBFLAMENCO) || defined(PCBTARANIS)) && defined(ROTARY_ENCODER_NAVIGATION)
|
||||
typedef uint16_t event_t;
|
||||
#define EVT_ROTARY_BREAK EVT_KEY_BREAK(KEY_ENTER)
|
||||
#define EVT_ROTARY_LONG EVT_KEY_LONG(KEY_ENTER)
|
||||
#define EVT_ROTARY_LEFT 0xDF00
|
||||
#define EVT_ROTARY_RIGHT 0xDE00
|
||||
#define IS_NEXT_EVENT(event) (event==EVT_ROTARY_RIGHT)
|
||||
#define IS_PREVIOUS_EVENT(event) (event==EVT_ROTARY_LEFT)
|
||||
#elif defined(ROTARY_ENCODER_NAVIGATION)
|
||||
typedef uint8_t event_t;
|
||||
#define EVT_ROTARY_BREAK 0xcf
|
||||
#define EVT_ROTARY_LONG 0xce
|
||||
#define EVT_ROTARY_LEFT 0xdf
|
||||
#define EVT_ROTARY_RIGHT 0xde
|
||||
#define IS_NEXT_EVENT(event) (event==EVT_ROTARY_RIGHT || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_REPT(KEY_DOWN))
|
||||
#define IS_PREVIOUS_EVENT(event) (event==EVT_ROTARY_LEFT || event==EVT_KEY_FIRST(KEY_UP) || event==EVT_KEY_REPT(KEY_UP))
|
||||
#else
|
||||
typedef uint8_t event_t;
|
||||
#define IS_NEXT_EVENT(event) (event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_REPT(KEY_DOWN))
|
||||
#define IS_PREVIOUS_EVENT(event) (event==EVT_KEY_FIRST(KEY_UP) || event==EVT_KEY_REPT(KEY_UP))
|
||||
#endif
|
||||
|
||||
#if defined(COLORLCD)
|
||||
#define EVT_REFRESH 0xDD00
|
||||
#endif
|
||||
|
||||
class Key
|
||||
{
|
||||
private:
|
||||
uint8_t m_vals;
|
||||
uint8_t m_cnt;
|
||||
uint8_t m_state;
|
||||
public:
|
||||
void input(bool val);
|
||||
bool state() const { return m_vals > 0; }
|
||||
void pauseEvents();
|
||||
void killEvents();
|
||||
uint8_t key() const;
|
||||
};
|
||||
|
||||
extern Key keys[NUM_KEYS];
|
||||
extern event_t s_evt;
|
||||
|
||||
#define putEvent(evt) s_evt = evt
|
||||
|
||||
void pauseEvents(event_t event);
|
||||
void killEvents(event_t event);
|
||||
|
||||
#if defined(CPUARM)
|
||||
bool clearKeyEvents();
|
||||
event_t getEvent(bool trim=false);
|
||||
#else
|
||||
void clearKeyEvents();
|
||||
event_t getEvent();
|
||||
#endif
|
||||
|
||||
uint8_t keyDown();
|
||||
|
||||
#endif // _KEYS_H_
|
||||
|
||||
+9
-9
@@ -20,13 +20,13 @@
|
||||
|
||||
#ifndef _PWR_H_
|
||||
#define _PWR_H_
|
||||
|
||||
enum PowerState {
|
||||
e_power_on,
|
||||
e_power_trainer,
|
||||
e_power_usb,
|
||||
e_power_off,
|
||||
e_power_press,
|
||||
};
|
||||
|
||||
|
||||
enum PowerState {
|
||||
e_power_on,
|
||||
e_power_trainer,
|
||||
e_power_usb,
|
||||
e_power_off,
|
||||
e_power_press,
|
||||
};
|
||||
|
||||
#endif // _PWR_H_
|
||||
|
||||
+63
-63
@@ -1,63 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 _RTC_H_
|
||||
#define _RTC_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#define SECS_PER_HOUR 3600ul
|
||||
#define SECS_PER_DAY 86400ul
|
||||
#define TM_YEAR_BASE 1900
|
||||
|
||||
#define TIME_T_MIN (-LONG_MAX)
|
||||
#define TIME_T_MAX (LONG_MAX)
|
||||
|
||||
typedef long int gtime_t;
|
||||
|
||||
struct gtm
|
||||
{
|
||||
int8_t tm_sec; /* Seconds. [0-60] (1 leap second) */
|
||||
int8_t tm_min; /* Minutes. [0-59] */
|
||||
int8_t tm_hour; /* Hours. [0-23] */
|
||||
int8_t tm_mday; /* Day. [1-31] */
|
||||
int8_t tm_mon; /* Month. [0-11] */
|
||||
uint8_t tm_year; /* Year - 1900. Limited to the year 2155. */
|
||||
int8_t tm_wday; /* Day of week. [0-6] */
|
||||
int16_t tm_yday; /* Day of year. [0-365] Needed internally for calculations */
|
||||
};
|
||||
|
||||
extern gtime_t g_rtcTime;
|
||||
extern uint8_t g_ms100; // global to allow time set function to reset to zero
|
||||
|
||||
void rtcInit();
|
||||
void rtcSetTime(const struct gtm * tm);
|
||||
gtime_t gmktime (struct gtm *tm);
|
||||
uint8_t rtcAdjust(uint16_t year, uint8_t mon, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec);
|
||||
|
||||
#if defined(__cplusplus) && !defined(SIMU)
|
||||
extern "C" {
|
||||
#endif
|
||||
void gettime(struct gtm * tm);
|
||||
#if defined(__cplusplus) && !defined(SIMU)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _RTC_H_
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 _RTC_H_
|
||||
#define _RTC_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#define SECS_PER_HOUR 3600ul
|
||||
#define SECS_PER_DAY 86400ul
|
||||
#define TM_YEAR_BASE 1900
|
||||
|
||||
#define TIME_T_MIN (-LONG_MAX)
|
||||
#define TIME_T_MAX (LONG_MAX)
|
||||
|
||||
typedef long int gtime_t;
|
||||
|
||||
struct gtm
|
||||
{
|
||||
int8_t tm_sec; /* Seconds. [0-60] (1 leap second) */
|
||||
int8_t tm_min; /* Minutes. [0-59] */
|
||||
int8_t tm_hour; /* Hours. [0-23] */
|
||||
int8_t tm_mday; /* Day. [1-31] */
|
||||
int8_t tm_mon; /* Month. [0-11] */
|
||||
uint8_t tm_year; /* Year - 1900. Limited to the year 2155. */
|
||||
int8_t tm_wday; /* Day of week. [0-6] */
|
||||
int16_t tm_yday; /* Day of year. [0-365] Needed internally for calculations */
|
||||
};
|
||||
|
||||
extern gtime_t g_rtcTime;
|
||||
extern uint8_t g_ms100; // global to allow time set function to reset to zero
|
||||
|
||||
void rtcInit();
|
||||
void rtcSetTime(const struct gtm * tm);
|
||||
gtime_t gmktime (struct gtm *tm);
|
||||
uint8_t rtcAdjust(uint16_t year, uint8_t mon, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec);
|
||||
|
||||
#if defined(__cplusplus) && !defined(SIMU)
|
||||
extern "C" {
|
||||
#endif
|
||||
void gettime(struct gtm * tm);
|
||||
#if defined(__cplusplus) && !defined(SIMU)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _RTC_H_
|
||||
|
||||
+16
-16
@@ -20,20 +20,20 @@
|
||||
|
||||
#ifndef _SERIAL_H_
|
||||
#define _SERIAL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void serialPutc(char c);
|
||||
void serialPrintf(const char *format, ...);
|
||||
void serialCrlf();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define serialPrint(...) do { serialPrintf(__VA_ARGS__); serialCrlf(); } while(0)
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void serialPutc(char c);
|
||||
void serialPrintf(const char *format, ...);
|
||||
void serialCrlf();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define serialPrint(...) do { serialPrintf(__VA_ARGS__); serialCrlf(); } while(0)
|
||||
|
||||
#endif // _SERIAL_H_
|
||||
|
||||
|
||||
|
||||
+137
-137
@@ -1,137 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include "opentx.h"
|
||||
#include "timers.h"
|
||||
|
||||
void eeLoadModel(uint8_t index)
|
||||
{
|
||||
if (index < MAX_MODELS) {
|
||||
|
||||
preModelLoad();
|
||||
|
||||
uint16_t size = eeLoadModelData(index);
|
||||
|
||||
#if defined(SIMU) && defined(EEPROM_ZONE_SIZE)
|
||||
if (sizeof(uint16_t) + sizeof(g_model) > EEPROM_ZONE_SIZE) {
|
||||
TRACE("Model data size can't exceed %d bytes (%d bytes)", int(EEPROM_ZONE_SIZE-sizeof(uint16_t)), (int)sizeof(g_model));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SIMU)
|
||||
if (size > 0 && size != sizeof(g_model)) {
|
||||
TRACE("Model data read=%d bytes vs %d bytes\n", size, (int)sizeof(ModelData));
|
||||
}
|
||||
#endif
|
||||
|
||||
bool alarms = true;
|
||||
if (size < EEPROM_MIN_MODEL_SIZE) { // if not loaded a fair amount
|
||||
modelDefault(index) ;
|
||||
storageCheck(true);
|
||||
alarms = false;
|
||||
}
|
||||
|
||||
postModelLoad(alarms);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t eeFindEmptyModel(uint8_t id, bool down)
|
||||
{
|
||||
uint8_t i = id;
|
||||
for (;;) {
|
||||
i = (MAX_MODELS + (down ? i+1 : i-1)) % MAX_MODELS;
|
||||
if (!eeModelExists(i)) break;
|
||||
if (i == id) return 0xff; // no free space in directory left
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void selectModel(uint8_t sub)
|
||||
{
|
||||
#if !defined(COLORLCD)
|
||||
showMessageBox(STR_LOADINGMODEL);
|
||||
#endif
|
||||
storageFlushCurrentModel();
|
||||
storageCheck(true); // force writing of current model data before this is changed
|
||||
g_eeGeneral.currModel = sub;
|
||||
storageDirty(EE_GENERAL);
|
||||
eeLoadModel(sub);
|
||||
}
|
||||
|
||||
#if defined(CPUARM)
|
||||
ModelHeader modelHeaders[MAX_MODELS];
|
||||
void eeLoadModelHeaders()
|
||||
{
|
||||
for (uint32_t i=0; i<MAX_MODELS; i++) {
|
||||
eeLoadModelHeader(i, &modelHeaders[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void storageReadRadioSettings()
|
||||
{
|
||||
if (!eepromOpen() || !eeLoadGeneral()) {
|
||||
storageEraseAll(true);
|
||||
}
|
||||
else {
|
||||
eeLoadModelHeaders();
|
||||
}
|
||||
|
||||
#if defined(CPUARM)
|
||||
for (uint8_t i=0; languagePacks[i]!=NULL; i++) {
|
||||
if (!strncmp(g_eeGeneral.ttsLanguage, languagePacks[i]->id, 2)) {
|
||||
currentLanguagePackIdx = i;
|
||||
currentLanguagePack = languagePacks[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void storageReadCurrentModel()
|
||||
{
|
||||
eeLoadModel(g_eeGeneral.currModel);
|
||||
}
|
||||
|
||||
void storageReadAll()
|
||||
{
|
||||
storageReadRadioSettings();
|
||||
storageReadCurrentModel();
|
||||
}
|
||||
|
||||
void storageEraseAll(bool warn)
|
||||
{
|
||||
TRACE("storageEraseAll");
|
||||
|
||||
generalDefault();
|
||||
modelDefault(0);
|
||||
|
||||
if (warn) {
|
||||
ALERT(STR_STORAGE_WARNING, STR_BAD_RADIO_DATA, AU_BAD_RADIODATA);
|
||||
}
|
||||
|
||||
RAISE_ALERT(STR_STORAGE_WARNING, STR_STORAGE_FORMAT, NULL, AU_NONE);
|
||||
|
||||
storageFormat();
|
||||
storageDirty(EE_GENERAL|EE_MODEL);
|
||||
storageCheck(true);
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include "opentx.h"
|
||||
#include "timers.h"
|
||||
|
||||
void eeLoadModel(uint8_t index)
|
||||
{
|
||||
if (index < MAX_MODELS) {
|
||||
|
||||
preModelLoad();
|
||||
|
||||
uint16_t size = eeLoadModelData(index);
|
||||
|
||||
#if defined(SIMU) && defined(EEPROM_ZONE_SIZE)
|
||||
if (sizeof(uint16_t) + sizeof(g_model) > EEPROM_ZONE_SIZE) {
|
||||
TRACE("Model data size can't exceed %d bytes (%d bytes)", int(EEPROM_ZONE_SIZE-sizeof(uint16_t)), (int)sizeof(g_model));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SIMU)
|
||||
if (size > 0 && size != sizeof(g_model)) {
|
||||
TRACE("Model data read=%d bytes vs %d bytes\n", size, (int)sizeof(ModelData));
|
||||
}
|
||||
#endif
|
||||
|
||||
bool alarms = true;
|
||||
if (size < EEPROM_MIN_MODEL_SIZE) { // if not loaded a fair amount
|
||||
modelDefault(index) ;
|
||||
storageCheck(true);
|
||||
alarms = false;
|
||||
}
|
||||
|
||||
postModelLoad(alarms);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t eeFindEmptyModel(uint8_t id, bool down)
|
||||
{
|
||||
uint8_t i = id;
|
||||
for (;;) {
|
||||
i = (MAX_MODELS + (down ? i+1 : i-1)) % MAX_MODELS;
|
||||
if (!eeModelExists(i)) break;
|
||||
if (i == id) return 0xff; // no free space in directory left
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void selectModel(uint8_t sub)
|
||||
{
|
||||
#if !defined(COLORLCD)
|
||||
showMessageBox(STR_LOADINGMODEL);
|
||||
#endif
|
||||
storageFlushCurrentModel();
|
||||
storageCheck(true); // force writing of current model data before this is changed
|
||||
g_eeGeneral.currModel = sub;
|
||||
storageDirty(EE_GENERAL);
|
||||
eeLoadModel(sub);
|
||||
}
|
||||
|
||||
#if defined(CPUARM)
|
||||
ModelHeader modelHeaders[MAX_MODELS];
|
||||
void eeLoadModelHeaders()
|
||||
{
|
||||
for (uint32_t i=0; i<MAX_MODELS; i++) {
|
||||
eeLoadModelHeader(i, &modelHeaders[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void storageReadRadioSettings()
|
||||
{
|
||||
if (!eepromOpen() || !eeLoadGeneral()) {
|
||||
storageEraseAll(true);
|
||||
}
|
||||
else {
|
||||
eeLoadModelHeaders();
|
||||
}
|
||||
|
||||
#if defined(CPUARM)
|
||||
for (uint8_t i=0; languagePacks[i]!=NULL; i++) {
|
||||
if (!strncmp(g_eeGeneral.ttsLanguage, languagePacks[i]->id, 2)) {
|
||||
currentLanguagePackIdx = i;
|
||||
currentLanguagePack = languagePacks[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void storageReadCurrentModel()
|
||||
{
|
||||
eeLoadModel(g_eeGeneral.currModel);
|
||||
}
|
||||
|
||||
void storageReadAll()
|
||||
{
|
||||
storageReadRadioSettings();
|
||||
storageReadCurrentModel();
|
||||
}
|
||||
|
||||
void storageEraseAll(bool warn)
|
||||
{
|
||||
TRACE("storageEraseAll");
|
||||
|
||||
generalDefault();
|
||||
modelDefault(0);
|
||||
|
||||
if (warn) {
|
||||
ALERT(STR_STORAGE_WARNING, STR_BAD_RADIO_DATA, AU_BAD_RADIODATA);
|
||||
}
|
||||
|
||||
RAISE_ALERT(STR_STORAGE_WARNING, STR_STORAGE_FORMAT, NULL, AU_NONE);
|
||||
|
||||
storageFormat();
|
||||
storageDirty(EE_GENERAL|EE_MODEL);
|
||||
storageCheck(true);
|
||||
}
|
||||
|
||||
@@ -18,25 +18,25 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#define EEPROM_MIN_MODEL_SIZE 256
|
||||
|
||||
uint16_t eeLoadModelData(uint8_t id);
|
||||
uint16_t eeLoadGeneralSettingsData();
|
||||
|
||||
bool eeModelExists(uint8_t id);
|
||||
void eeLoadModel(uint8_t id);
|
||||
bool eeConvert();
|
||||
void ConvertModel(int id, int version);
|
||||
uint8_t eeFindEmptyModel(uint8_t id, bool down);
|
||||
void selectModel(uint8_t sub);
|
||||
|
||||
#if defined(CPUARM)
|
||||
extern ModelHeader modelHeaders[MAX_MODELS];
|
||||
void eeLoadModelHeader(uint8_t id, ModelHeader *header);
|
||||
void eeLoadModelHeaders();
|
||||
#else
|
||||
#define eeLoadModelHeaders()
|
||||
#endif
|
||||
#define EEPROM_MIN_MODEL_SIZE 256
|
||||
|
||||
uint16_t eeLoadModelData(uint8_t id);
|
||||
uint16_t eeLoadGeneralSettingsData();
|
||||
|
||||
bool eeModelExists(uint8_t id);
|
||||
void eeLoadModel(uint8_t id);
|
||||
bool eeConvert();
|
||||
void ConvertModel(int id, int version);
|
||||
uint8_t eeFindEmptyModel(uint8_t id, bool down);
|
||||
void selectModel(uint8_t sub);
|
||||
|
||||
#if defined(CPUARM)
|
||||
extern ModelHeader modelHeaders[MAX_MODELS];
|
||||
void eeLoadModelHeader(uint8_t id, ModelHeader *header);
|
||||
void eeLoadModelHeaders();
|
||||
#else
|
||||
#define eeLoadModelHeaders()
|
||||
#endif
|
||||
|
||||
void storageReadRadioSettings();
|
||||
void storageReadCurrentModel();
|
||||
|
||||
+1304
-1304
File diff suppressed because it is too large
Load Diff
+116
-116
@@ -1,116 +1,116 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include "debug.h"
|
||||
|
||||
#undef errno
|
||||
extern int errno;
|
||||
extern int _end;
|
||||
extern int _heap_end;
|
||||
|
||||
unsigned char * heap = (unsigned char *)&_end;
|
||||
|
||||
extern caddr_t _sbrk(int nbytes)
|
||||
{
|
||||
if (heap + nbytes < (unsigned char *)&_heap_end) {
|
||||
unsigned char * prev_heap = heap;
|
||||
heap += nbytes;
|
||||
return (caddr_t)prev_heap;
|
||||
}
|
||||
else {
|
||||
errno = ENOMEM;
|
||||
return ((void *)-1);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(SEMIHOSTING)
|
||||
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)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void _exit(int status)
|
||||
{
|
||||
TRACE("_exit(%d)", status);
|
||||
for (;;);
|
||||
}
|
||||
|
||||
extern void _kill(int pid, int sig)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
extern int _getpid()
|
||||
{
|
||||
return -1 ;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include "debug.h"
|
||||
|
||||
#undef errno
|
||||
extern int errno;
|
||||
extern int _end;
|
||||
extern int _heap_end;
|
||||
|
||||
unsigned char * heap = (unsigned char *)&_end;
|
||||
|
||||
extern caddr_t _sbrk(int nbytes)
|
||||
{
|
||||
if (heap + nbytes < (unsigned char *)&_heap_end) {
|
||||
unsigned char * prev_heap = heap;
|
||||
heap += nbytes;
|
||||
return (caddr_t)prev_heap;
|
||||
}
|
||||
else {
|
||||
errno = ENOMEM;
|
||||
return ((void *)-1);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(SEMIHOSTING)
|
||||
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)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void _exit(int status)
|
||||
{
|
||||
TRACE("_exit(%d)", status);
|
||||
for (;;);
|
||||
}
|
||||
|
||||
extern void _kill(int pid, int sig)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
extern int _getpid()
|
||||
{
|
||||
return -1 ;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+364
-364
@@ -1,364 +1,364 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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;
|
||||
#else
|
||||
uint8_t RotPosition;
|
||||
int8_t LastRotaryValue;
|
||||
int8_t Rotary_diff;
|
||||
int8_t RotaryControl;
|
||||
uint8_t RotEncoder;
|
||||
#endif
|
||||
|
||||
void rotencPoll()
|
||||
{
|
||||
#if defined(TELEMETREZ)
|
||||
if (TrotCount != LastTrotCount) {
|
||||
rotencValue[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 ) {
|
||||
rotencValue[0] -= 1;
|
||||
}
|
||||
else {
|
||||
rotencValue[0] += 1;
|
||||
}
|
||||
RotPosition = rotary;
|
||||
}
|
||||
#endif // TELEMETREZ
|
||||
}
|
||||
#else
|
||||
#define ROTENC_DOWN() (0)
|
||||
#endif // ROTARY_ENCODER_NAVIGATION
|
||||
|
||||
void boardInit()
|
||||
{
|
||||
#if !defined(SIMU)
|
||||
// Set up I/O port data directions and initial states
|
||||
DDRA = 0xff; PORTA = 0x00; // LCD data
|
||||
DDRB = 0x81; PORTB = 0x7e; //pullups keys+nc
|
||||
#if defined(TELEMETRY_MOD_14051) || defined(TELEMETRY_MOD_14051_SWAPPED)
|
||||
DDRC = 0xff; PORTC = 0x00;
|
||||
#else
|
||||
DDRC = 0x3e; PORTC = 0xc1; //pullups nc
|
||||
#endif
|
||||
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)
|
||||
|
||||
adcInit();
|
||||
|
||||
#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(CPUM2561)
|
||||
#if defined(SP22)
|
||||
TCCR0A = (1<<WGM00)|(1<<COM0A1)|(1<<COM0A0); // inv. pwm mode, clk/64
|
||||
#else
|
||||
TCCR0A = (1<<WGM00)|(1<<COM0A1); // pwm mode, clk/64
|
||||
#endif
|
||||
TCCR0B = (0b011<<CS00);
|
||||
#else
|
||||
#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
|
||||
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 // !defined(SIMU)
|
||||
}
|
||||
|
||||
#if !defined(SIMU) && (defined(TELEMETRY_MOD_14051) || defined(TELEMETRY_MOD_14051_SWAPPED))
|
||||
uint8_t pf7_digital[MUX_PF7_DIGITAL_MAX - MUX_PF7_DIGITAL_MIN + 1];
|
||||
/**
|
||||
* Update ADC PF7 using 14051 multiplexer
|
||||
* X0 : Battery voltage
|
||||
* X1 : AIL SW
|
||||
* X2 : THR SW
|
||||
* X3 : TRIM LEFT VERTICAL UP
|
||||
* X4 : TRIM LEFT VERTICAL DOWN
|
||||
*/
|
||||
void processMultiplexAna()
|
||||
{
|
||||
static uint8_t muxNum = MUX_BATT;
|
||||
uint8_t nextMuxNum = muxNum-1;
|
||||
|
||||
switch (muxNum) {
|
||||
case MUX_BATT:
|
||||
s_anaFilt[TX_VOLTAGE] = s_anaFilt[X14051];
|
||||
nextMuxNum = MUX_MAX;
|
||||
break;
|
||||
case MUX_AIL:
|
||||
case MUX_THR:
|
||||
case MUX_TRM_LV_UP:
|
||||
case MUX_TRM_LV_DWN:
|
||||
// Digital switch depend from input voltage
|
||||
// take half voltage to determine digital state
|
||||
pf7_digital[muxNum - MUX_PF7_DIGITAL_MIN] = (s_anaFilt[X14051] >= (s_anaFilt[TX_VOLTAGE] / 2)) ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// set the mux number for the next ADC convert,
|
||||
// stabilize voltage before ADC read.
|
||||
muxNum = nextMuxNum;
|
||||
PORTC &= ~((1 << PC7) | (1 << PC6) | (1 << PC0));
|
||||
if(muxNum & 1) PORTC |= (1 << PC7); // Mux CTRL A
|
||||
if(muxNum & 2) PORTC |= (1 << PC6); // Mux CTRL B
|
||||
if(muxNum & 4) PORTC |= (1 << PC0); // Mux CTRL C
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(SIMU) && (defined(TELEMETRY_MOD_14051) || defined(TELEMETRY_MOD_14051_SWAPPED))
|
||||
#define THR_STATE() pf7_digital[PF7_THR]
|
||||
#define AIL_STATE() pf7_digital[PF7_AIL]
|
||||
#elif defined(TELEMETRY_JETI) || defined(TELEMETRY_FRSKY) || defined(TELEMETRY_ARDUPILOT) || defined(TELEMETRY_NMEA) || defined(TELEMETRY_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
|
||||
|
||||
uint8_t keyState(uint8_t index)
|
||||
{
|
||||
return keys[index].state();
|
||||
}
|
||||
|
||||
uint8_t switchState(uint8_t index)
|
||||
{
|
||||
uint8_t result = 0;
|
||||
|
||||
switch (index) {
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Trim switches ...
|
||||
uint8_t trimHelper(uint8_t negpin, uint8_t idx)
|
||||
{
|
||||
switch(idx){
|
||||
case 0: return negpin & TRIMS_GPIO_PIN_LHL;
|
||||
case 1: return negpin & TRIMS_GPIO_PIN_LHR;
|
||||
#if !defined(SIMU) && defined(TELEMETRY_MOD_14051_SWAPPED)
|
||||
case 2: return !pf7_digital[PF7_TRM_LV_DWN];
|
||||
case 3: return !pf7_digital[PF7_TRM_LV_UP];
|
||||
#else
|
||||
case 2: return negpin & TRIMS_GPIO_PIN_LVD;
|
||||
case 3: return negpin & TRIMS_GPIO_PIN_LVU;
|
||||
#endif
|
||||
case 4: return negpin & TRIMS_GPIO_PIN_RVD;
|
||||
case 5: return negpin & TRIMS_GPIO_PIN_RVU;
|
||||
case 6: return negpin & TRIMS_GPIO_PIN_RHL;
|
||||
case 7: return negpin & TRIMS_GPIO_PIN_RHR;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t trimDown(uint8_t idx)
|
||||
{
|
||||
return trimHelper(~PIND, idx);
|
||||
}
|
||||
|
||||
void readKeysAndTrims()
|
||||
{
|
||||
uint8_t index = KEY_MENU;
|
||||
|
||||
// User buttons ...
|
||||
uint8_t in = ~PINB;
|
||||
for (int i=1; i<7; i++) {
|
||||
keys[index].input(in & (1<<i));
|
||||
++index;
|
||||
}
|
||||
|
||||
// Trims ...
|
||||
in = ~PIND;
|
||||
for (int i=0; i<8; i++) {
|
||||
// INP_D_TRM_RH_UP 0 .. INP_D_TRM_LH_UP 7
|
||||
keys[index].input(trimHelper(in, i));
|
||||
++index;
|
||||
}
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
keys[index].input(ROTENC_DOWN()); // 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 backlightEnable()
|
||||
{
|
||||
bl_target = 15 - g_eeGeneral.blOnBright;
|
||||
}
|
||||
|
||||
void backlightDisable()
|
||||
{
|
||||
bl_target = g_eeGeneral.blOffBright;
|
||||
}
|
||||
|
||||
bool isBacklightEnabled()
|
||||
{
|
||||
return (bl_target==g_eeGeneral.blOnBright);
|
||||
}
|
||||
|
||||
void backlightFade() // called from per10ms()
|
||||
{
|
||||
if (bl_target != bl_current) {
|
||||
#if defined(CPUM2561)
|
||||
if (bl_target > bl_current)
|
||||
OCR0A = pgm_read_byte(&pwmtable[++bl_current]);
|
||||
else
|
||||
OCR0A = pgm_read_byte(&pwmtable[--bl_current]);
|
||||
#else
|
||||
if (bl_target > bl_current)
|
||||
OCR2 = pgm_read_byte(&pwmtable[++bl_current]);
|
||||
else
|
||||
OCR2 = pgm_read_byte(&pwmtable[--bl_current]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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;
|
||||
#else
|
||||
uint8_t RotPosition;
|
||||
int8_t LastRotaryValue;
|
||||
int8_t Rotary_diff;
|
||||
int8_t RotaryControl;
|
||||
uint8_t RotEncoder;
|
||||
#endif
|
||||
|
||||
void rotencPoll()
|
||||
{
|
||||
#if defined(TELEMETREZ)
|
||||
if (TrotCount != LastTrotCount) {
|
||||
rotencValue[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 ) {
|
||||
rotencValue[0] -= 1;
|
||||
}
|
||||
else {
|
||||
rotencValue[0] += 1;
|
||||
}
|
||||
RotPosition = rotary;
|
||||
}
|
||||
#endif // TELEMETREZ
|
||||
}
|
||||
#else
|
||||
#define ROTENC_DOWN() (0)
|
||||
#endif // ROTARY_ENCODER_NAVIGATION
|
||||
|
||||
void boardInit()
|
||||
{
|
||||
#if !defined(SIMU)
|
||||
// Set up I/O port data directions and initial states
|
||||
DDRA = 0xff; PORTA = 0x00; // LCD data
|
||||
DDRB = 0x81; PORTB = 0x7e; //pullups keys+nc
|
||||
#if defined(TELEMETRY_MOD_14051) || defined(TELEMETRY_MOD_14051_SWAPPED)
|
||||
DDRC = 0xff; PORTC = 0x00;
|
||||
#else
|
||||
DDRC = 0x3e; PORTC = 0xc1; //pullups nc
|
||||
#endif
|
||||
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)
|
||||
|
||||
adcInit();
|
||||
|
||||
#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(CPUM2561)
|
||||
#if defined(SP22)
|
||||
TCCR0A = (1<<WGM00)|(1<<COM0A1)|(1<<COM0A0); // inv. pwm mode, clk/64
|
||||
#else
|
||||
TCCR0A = (1<<WGM00)|(1<<COM0A1); // pwm mode, clk/64
|
||||
#endif
|
||||
TCCR0B = (0b011<<CS00);
|
||||
#else
|
||||
#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
|
||||
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 // !defined(SIMU)
|
||||
}
|
||||
|
||||
#if !defined(SIMU) && (defined(TELEMETRY_MOD_14051) || defined(TELEMETRY_MOD_14051_SWAPPED))
|
||||
uint8_t pf7_digital[MUX_PF7_DIGITAL_MAX - MUX_PF7_DIGITAL_MIN + 1];
|
||||
/**
|
||||
* Update ADC PF7 using 14051 multiplexer
|
||||
* X0 : Battery voltage
|
||||
* X1 : AIL SW
|
||||
* X2 : THR SW
|
||||
* X3 : TRIM LEFT VERTICAL UP
|
||||
* X4 : TRIM LEFT VERTICAL DOWN
|
||||
*/
|
||||
void processMultiplexAna()
|
||||
{
|
||||
static uint8_t muxNum = MUX_BATT;
|
||||
uint8_t nextMuxNum = muxNum-1;
|
||||
|
||||
switch (muxNum) {
|
||||
case MUX_BATT:
|
||||
s_anaFilt[TX_VOLTAGE] = s_anaFilt[X14051];
|
||||
nextMuxNum = MUX_MAX;
|
||||
break;
|
||||
case MUX_AIL:
|
||||
case MUX_THR:
|
||||
case MUX_TRM_LV_UP:
|
||||
case MUX_TRM_LV_DWN:
|
||||
// Digital switch depend from input voltage
|
||||
// take half voltage to determine digital state
|
||||
pf7_digital[muxNum - MUX_PF7_DIGITAL_MIN] = (s_anaFilt[X14051] >= (s_anaFilt[TX_VOLTAGE] / 2)) ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// set the mux number for the next ADC convert,
|
||||
// stabilize voltage before ADC read.
|
||||
muxNum = nextMuxNum;
|
||||
PORTC &= ~((1 << PC7) | (1 << PC6) | (1 << PC0));
|
||||
if(muxNum & 1) PORTC |= (1 << PC7); // Mux CTRL A
|
||||
if(muxNum & 2) PORTC |= (1 << PC6); // Mux CTRL B
|
||||
if(muxNum & 4) PORTC |= (1 << PC0); // Mux CTRL C
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(SIMU) && (defined(TELEMETRY_MOD_14051) || defined(TELEMETRY_MOD_14051_SWAPPED))
|
||||
#define THR_STATE() pf7_digital[PF7_THR]
|
||||
#define AIL_STATE() pf7_digital[PF7_AIL]
|
||||
#elif defined(TELEMETRY_JETI) || defined(TELEMETRY_FRSKY) || defined(TELEMETRY_ARDUPILOT) || defined(TELEMETRY_NMEA) || defined(TELEMETRY_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
|
||||
|
||||
uint8_t keyState(uint8_t index)
|
||||
{
|
||||
return keys[index].state();
|
||||
}
|
||||
|
||||
uint8_t switchState(uint8_t index)
|
||||
{
|
||||
uint8_t result = 0;
|
||||
|
||||
switch (index) {
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Trim switches ...
|
||||
uint8_t trimHelper(uint8_t negpin, uint8_t idx)
|
||||
{
|
||||
switch(idx){
|
||||
case 0: return negpin & TRIMS_GPIO_PIN_LHL;
|
||||
case 1: return negpin & TRIMS_GPIO_PIN_LHR;
|
||||
#if !defined(SIMU) && defined(TELEMETRY_MOD_14051_SWAPPED)
|
||||
case 2: return !pf7_digital[PF7_TRM_LV_DWN];
|
||||
case 3: return !pf7_digital[PF7_TRM_LV_UP];
|
||||
#else
|
||||
case 2: return negpin & TRIMS_GPIO_PIN_LVD;
|
||||
case 3: return negpin & TRIMS_GPIO_PIN_LVU;
|
||||
#endif
|
||||
case 4: return negpin & TRIMS_GPIO_PIN_RVD;
|
||||
case 5: return negpin & TRIMS_GPIO_PIN_RVU;
|
||||
case 6: return negpin & TRIMS_GPIO_PIN_RHL;
|
||||
case 7: return negpin & TRIMS_GPIO_PIN_RHR;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t trimDown(uint8_t idx)
|
||||
{
|
||||
return trimHelper(~PIND, idx);
|
||||
}
|
||||
|
||||
void readKeysAndTrims()
|
||||
{
|
||||
uint8_t index = KEY_MENU;
|
||||
|
||||
// User buttons ...
|
||||
uint8_t in = ~PINB;
|
||||
for (int i=1; i<7; i++) {
|
||||
keys[index].input(in & (1<<i));
|
||||
++index;
|
||||
}
|
||||
|
||||
// Trims ...
|
||||
in = ~PIND;
|
||||
for (int i=0; i<8; i++) {
|
||||
// INP_D_TRM_RH_UP 0 .. INP_D_TRM_LH_UP 7
|
||||
keys[index].input(trimHelper(in, i));
|
||||
++index;
|
||||
}
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
keys[index].input(ROTENC_DOWN()); // 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 backlightEnable()
|
||||
{
|
||||
bl_target = 15 - g_eeGeneral.blOnBright;
|
||||
}
|
||||
|
||||
void backlightDisable()
|
||||
{
|
||||
bl_target = g_eeGeneral.blOffBright;
|
||||
}
|
||||
|
||||
bool isBacklightEnabled()
|
||||
{
|
||||
return (bl_target==g_eeGeneral.blOnBright);
|
||||
}
|
||||
|
||||
void backlightFade() // called from per10ms()
|
||||
{
|
||||
if (bl_target != bl_current) {
|
||||
#if defined(CPUM2561)
|
||||
if (bl_target > bl_current)
|
||||
OCR0A = pgm_read_byte(&pwmtable[++bl_current]);
|
||||
else
|
||||
OCR0A = pgm_read_byte(&pwmtable[--bl_current]);
|
||||
#else
|
||||
if (bl_target > bl_current)
|
||||
OCR2 = pgm_read_byte(&pwmtable[++bl_current]);
|
||||
else
|
||||
OCR2 = pgm_read_byte(&pwmtable[--bl_current]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+260
-260
@@ -1,260 +1,260 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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_
|
||||
|
||||
#include "../common/avr/board_avr.h"
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
// Board driver
|
||||
void boardInit(void);
|
||||
#define boardOff() pwrOff()
|
||||
|
||||
// Keys
|
||||
#define KEYS_GPIO_REG_MENU pinb
|
||||
#define KEYS_GPIO_PIN_MENU (1<<1)
|
||||
#define KEYS_GPIO_REG_EXIT pinb
|
||||
#define KEYS_GPIO_PIN_EXIT (1<<2)
|
||||
#define KEYS_GPIO_REG_RIGHT pinb
|
||||
#define KEYS_GPIO_PIN_RIGHT (1<<5)
|
||||
#define KEYS_GPIO_REG_LEFT pinb
|
||||
#define KEYS_GPIO_PIN_LEFT (1<<6)
|
||||
#define KEYS_GPIO_REG_UP pinb
|
||||
#define KEYS_GPIO_PIN_UP (1<<4)
|
||||
#define KEYS_GPIO_REG_DOWN pinb
|
||||
#define KEYS_GPIO_PIN_DOWN (1<<3)
|
||||
|
||||
// Trims
|
||||
#define TRIMS_GPIO_REG_LHL pind
|
||||
#define TRIMS_GPIO_PIN_LHL (1<<6)
|
||||
#define TRIMS_GPIO_REG_LVD pind
|
||||
#define TRIMS_GPIO_PIN_LVD (1<<3)
|
||||
#define TRIMS_GPIO_REG_RVU pind
|
||||
#define TRIMS_GPIO_PIN_RVU (1<<4)
|
||||
#define TRIMS_GPIO_REG_RHL pind
|
||||
#define TRIMS_GPIO_PIN_RHL (1<<1)
|
||||
#define TRIMS_GPIO_REG_LHR pind
|
||||
#define TRIMS_GPIO_PIN_LHR (1<<7)
|
||||
#define TRIMS_GPIO_REG_LVU pind
|
||||
#define TRIMS_GPIO_PIN_LVU (1<<2)
|
||||
#define TRIMS_GPIO_REG_RVD pind
|
||||
#define TRIMS_GPIO_PIN_RVD (1<<5)
|
||||
#define TRIMS_GPIO_REG_RHR pind
|
||||
#define TRIMS_GPIO_PIN_RHR (1<<0)
|
||||
|
||||
#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 OUT_G_SIM_CTL 4 // 1 : phone-jack=ppm_in
|
||||
#define SLAVE_MODE() checkSlaveMode()
|
||||
#define JACK_PPM_OUT() PORTG &= ~(1<<OUT_G_SIM_CTL)
|
||||
#define JACK_PPM_IN() PORTG |= (1<<OUT_G_SIM_CTL)
|
||||
|
||||
// Backlight driver
|
||||
#define OUT_B_LIGHT 7
|
||||
#if defined(PWM_BACKLIGHT)
|
||||
void backlightEnable();
|
||||
void backlightDisable();
|
||||
bool isBacklightEnabled();
|
||||
void backlightFade();
|
||||
#elif defined(SP22)
|
||||
#define backlightEnable() PORTB &= ~(1<<OUT_B_LIGHT)
|
||||
#define backlightDisable() PORTB |= (1<<OUT_B_LIGHT)
|
||||
#define isBacklightEnabled() (~PORTB & (1<<OUT_B_LIGHT))
|
||||
#else
|
||||
#define backlightEnable() PORTB |= (1<<OUT_B_LIGHT)
|
||||
#define backlightDisable() PORTB &= ~(1<<OUT_B_LIGHT)
|
||||
#define isBacklightEnabled() (PORTB & (1<<OUT_B_LIGHT))
|
||||
#endif
|
||||
#if defined(VOICE) && !defined(SIMU)
|
||||
#define BACKLIGHT_ENABLE() Voice.Backlight = 1
|
||||
#define BACKLIGHT_DISABLE() Voice.Backlight = 0
|
||||
#else
|
||||
#define BACKLIGHT_ENABLE() backlightEnable()
|
||||
#define BACKLIGHT_DISABLE() backlightDisable()
|
||||
#endif
|
||||
|
||||
#define OUT_B_PPM 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(TELEMETRY_JETI) || defined(TELEMETRY_FRSKY) || defined(TELEMETRY_ARDUPILOT) || defined(TELEMETRY_NMEA) || defined(TELEMETRY_MAVLINK)
|
||||
#define INP_C_ThrCt 6
|
||||
#define INP_C_AileDR 7
|
||||
#else
|
||||
#define INP_E_ThrCt 0
|
||||
#define INP_E_AileDR 1
|
||||
#endif
|
||||
|
||||
#define INP_G_ID1 3
|
||||
#define OUT_G_HAPTIC 2
|
||||
#define INP_G_RF_POW 1
|
||||
#define INP_G_RuddDR 0
|
||||
|
||||
// Rotary Encoder driver
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
extern uint8_t RotEncoder;
|
||||
#if defined(TELEMETREZ)
|
||||
#define ROTENC_DOWN() (RotEncoder != 0)
|
||||
#else
|
||||
#define ROTENC_DOWN() (RotEncoder & 0x20)
|
||||
#endif
|
||||
#else
|
||||
#define ROTENC_DOWN() (0)
|
||||
#endif
|
||||
|
||||
// Keys driver
|
||||
inline uint8_t keyDown()
|
||||
{
|
||||
return ((~PINB) & 0x7E) | ROTENC_DOWN();
|
||||
}
|
||||
|
||||
#if defined(TELEMETRY_MOD_14051) || defined(TELEMETRY_MOD_14051_SWAPPED)
|
||||
enum MuxInput {
|
||||
MUX_BATT,
|
||||
MUX_AIL,
|
||||
MUX_PF7_DIGITAL_MIN = MUX_AIL,
|
||||
MUX_THR,
|
||||
MUX_TRM_LV_UP,
|
||||
MUX_TRM_LV_DWN,
|
||||
MUX_PF7_DIGITAL_MAX = MUX_TRM_LV_DWN,
|
||||
MUX_MAX = MUX_PF7_DIGITAL_MAX
|
||||
};
|
||||
|
||||
enum Pf7Digital {
|
||||
PF7_AIL = MUX_AIL - MUX_PF7_DIGITAL_MIN,
|
||||
PF7_THR = MUX_THR - MUX_PF7_DIGITAL_MIN,
|
||||
PF7_TRM_LV_UP = MUX_TRM_LV_UP - MUX_PF7_DIGITAL_MIN,
|
||||
PF7_TRM_LV_DWN = MUX_TRM_LV_DWN - MUX_PF7_DIGITAL_MIN,
|
||||
};
|
||||
|
||||
extern uint8_t pf7_digital[MUX_PF7_DIGITAL_MAX - MUX_PF7_DIGITAL_MIN + 1];
|
||||
void processMultiplexAna();
|
||||
#endif
|
||||
|
||||
#if defined(TELEMETRY_MOD_14051_SWAPPED)
|
||||
#define TRIMS_PRESSED() (~PIND & ~0x0c || pf7_digital[PF7_TRM_LV_UP] || pf7_digital[PF7_TRM_LV_DWN])
|
||||
#else
|
||||
#define TRIMS_PRESSED() (~PIND)
|
||||
#endif
|
||||
#define KEYS_PRESSED() (~PINB)
|
||||
|
||||
// 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
|
||||
|
||||
// Haptic
|
||||
#define hapticOn() PORTG |= (1 << OUT_G_HAPTIC)
|
||||
#define hapticOff() PORTG &= ~(1 << OUT_G_HAPTIC)
|
||||
|
||||
// USB fake driver
|
||||
#define usbPlugged() false
|
||||
|
||||
// Buzzer driver
|
||||
#define buzzerOn() PORTE |= (1 << OUT_E_BUZZER)
|
||||
#define buzzerOff() PORTE &= ~(1 << OUT_E_BUZZER)
|
||||
|
||||
#endif // _BOARD_STOCK_H_
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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_
|
||||
|
||||
#include "../common/avr/board_avr.h"
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
// Board driver
|
||||
void boardInit(void);
|
||||
#define boardOff() pwrOff()
|
||||
|
||||
// Keys
|
||||
#define KEYS_GPIO_REG_MENU pinb
|
||||
#define KEYS_GPIO_PIN_MENU (1<<1)
|
||||
#define KEYS_GPIO_REG_EXIT pinb
|
||||
#define KEYS_GPIO_PIN_EXIT (1<<2)
|
||||
#define KEYS_GPIO_REG_RIGHT pinb
|
||||
#define KEYS_GPIO_PIN_RIGHT (1<<5)
|
||||
#define KEYS_GPIO_REG_LEFT pinb
|
||||
#define KEYS_GPIO_PIN_LEFT (1<<6)
|
||||
#define KEYS_GPIO_REG_UP pinb
|
||||
#define KEYS_GPIO_PIN_UP (1<<4)
|
||||
#define KEYS_GPIO_REG_DOWN pinb
|
||||
#define KEYS_GPIO_PIN_DOWN (1<<3)
|
||||
|
||||
// Trims
|
||||
#define TRIMS_GPIO_REG_LHL pind
|
||||
#define TRIMS_GPIO_PIN_LHL (1<<6)
|
||||
#define TRIMS_GPIO_REG_LVD pind
|
||||
#define TRIMS_GPIO_PIN_LVD (1<<3)
|
||||
#define TRIMS_GPIO_REG_RVU pind
|
||||
#define TRIMS_GPIO_PIN_RVU (1<<4)
|
||||
#define TRIMS_GPIO_REG_RHL pind
|
||||
#define TRIMS_GPIO_PIN_RHL (1<<1)
|
||||
#define TRIMS_GPIO_REG_LHR pind
|
||||
#define TRIMS_GPIO_PIN_LHR (1<<7)
|
||||
#define TRIMS_GPIO_REG_LVU pind
|
||||
#define TRIMS_GPIO_PIN_LVU (1<<2)
|
||||
#define TRIMS_GPIO_REG_RVD pind
|
||||
#define TRIMS_GPIO_PIN_RVD (1<<5)
|
||||
#define TRIMS_GPIO_REG_RHR pind
|
||||
#define TRIMS_GPIO_PIN_RHR (1<<0)
|
||||
|
||||
#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 OUT_G_SIM_CTL 4 // 1 : phone-jack=ppm_in
|
||||
#define SLAVE_MODE() checkSlaveMode()
|
||||
#define JACK_PPM_OUT() PORTG &= ~(1<<OUT_G_SIM_CTL)
|
||||
#define JACK_PPM_IN() PORTG |= (1<<OUT_G_SIM_CTL)
|
||||
|
||||
// Backlight driver
|
||||
#define OUT_B_LIGHT 7
|
||||
#if defined(PWM_BACKLIGHT)
|
||||
void backlightEnable();
|
||||
void backlightDisable();
|
||||
bool isBacklightEnabled();
|
||||
void backlightFade();
|
||||
#elif defined(SP22)
|
||||
#define backlightEnable() PORTB &= ~(1<<OUT_B_LIGHT)
|
||||
#define backlightDisable() PORTB |= (1<<OUT_B_LIGHT)
|
||||
#define isBacklightEnabled() (~PORTB & (1<<OUT_B_LIGHT))
|
||||
#else
|
||||
#define backlightEnable() PORTB |= (1<<OUT_B_LIGHT)
|
||||
#define backlightDisable() PORTB &= ~(1<<OUT_B_LIGHT)
|
||||
#define isBacklightEnabled() (PORTB & (1<<OUT_B_LIGHT))
|
||||
#endif
|
||||
#if defined(VOICE) && !defined(SIMU)
|
||||
#define BACKLIGHT_ENABLE() Voice.Backlight = 1
|
||||
#define BACKLIGHT_DISABLE() Voice.Backlight = 0
|
||||
#else
|
||||
#define BACKLIGHT_ENABLE() backlightEnable()
|
||||
#define BACKLIGHT_DISABLE() backlightDisable()
|
||||
#endif
|
||||
|
||||
#define OUT_B_PPM 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(TELEMETRY_JETI) || defined(TELEMETRY_FRSKY) || defined(TELEMETRY_ARDUPILOT) || defined(TELEMETRY_NMEA) || defined(TELEMETRY_MAVLINK)
|
||||
#define INP_C_ThrCt 6
|
||||
#define INP_C_AileDR 7
|
||||
#else
|
||||
#define INP_E_ThrCt 0
|
||||
#define INP_E_AileDR 1
|
||||
#endif
|
||||
|
||||
#define INP_G_ID1 3
|
||||
#define OUT_G_HAPTIC 2
|
||||
#define INP_G_RF_POW 1
|
||||
#define INP_G_RuddDR 0
|
||||
|
||||
// Rotary Encoder driver
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
extern uint8_t RotEncoder;
|
||||
#if defined(TELEMETREZ)
|
||||
#define ROTENC_DOWN() (RotEncoder != 0)
|
||||
#else
|
||||
#define ROTENC_DOWN() (RotEncoder & 0x20)
|
||||
#endif
|
||||
#else
|
||||
#define ROTENC_DOWN() (0)
|
||||
#endif
|
||||
|
||||
// Keys driver
|
||||
inline uint8_t keyDown()
|
||||
{
|
||||
return ((~PINB) & 0x7E) | ROTENC_DOWN();
|
||||
}
|
||||
|
||||
#if defined(TELEMETRY_MOD_14051) || defined(TELEMETRY_MOD_14051_SWAPPED)
|
||||
enum MuxInput {
|
||||
MUX_BATT,
|
||||
MUX_AIL,
|
||||
MUX_PF7_DIGITAL_MIN = MUX_AIL,
|
||||
MUX_THR,
|
||||
MUX_TRM_LV_UP,
|
||||
MUX_TRM_LV_DWN,
|
||||
MUX_PF7_DIGITAL_MAX = MUX_TRM_LV_DWN,
|
||||
MUX_MAX = MUX_PF7_DIGITAL_MAX
|
||||
};
|
||||
|
||||
enum Pf7Digital {
|
||||
PF7_AIL = MUX_AIL - MUX_PF7_DIGITAL_MIN,
|
||||
PF7_THR = MUX_THR - MUX_PF7_DIGITAL_MIN,
|
||||
PF7_TRM_LV_UP = MUX_TRM_LV_UP - MUX_PF7_DIGITAL_MIN,
|
||||
PF7_TRM_LV_DWN = MUX_TRM_LV_DWN - MUX_PF7_DIGITAL_MIN,
|
||||
};
|
||||
|
||||
extern uint8_t pf7_digital[MUX_PF7_DIGITAL_MAX - MUX_PF7_DIGITAL_MIN + 1];
|
||||
void processMultiplexAna();
|
||||
#endif
|
||||
|
||||
#if defined(TELEMETRY_MOD_14051_SWAPPED)
|
||||
#define TRIMS_PRESSED() (~PIND & ~0x0c || pf7_digital[PF7_TRM_LV_UP] || pf7_digital[PF7_TRM_LV_DWN])
|
||||
#else
|
||||
#define TRIMS_PRESSED() (~PIND)
|
||||
#endif
|
||||
#define KEYS_PRESSED() (~PINB)
|
||||
|
||||
// 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
|
||||
|
||||
// Haptic
|
||||
#define hapticOn() PORTG |= (1 << OUT_G_HAPTIC)
|
||||
#define hapticOff() PORTG &= ~(1 << OUT_G_HAPTIC)
|
||||
|
||||
// USB fake driver
|
||||
#define usbPlugged() false
|
||||
|
||||
// Buzzer driver
|
||||
#define buzzerOn() PORTE |= (1 << OUT_E_BUZZER)
|
||||
#define buzzerOff() PORTE &= ~(1 << OUT_E_BUZZER)
|
||||
|
||||
#endif // _BOARD_STOCK_H_
|
||||
|
||||
@@ -1,138 +1,138 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
void lcdSendCtl(uint8_t val)
|
||||
{
|
||||
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
|
||||
#if defined(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);
|
||||
#if defined(LCD_MULTIPLEX)
|
||||
DDRA = 0x00; // Set LCD_DAT pins to input
|
||||
#endif
|
||||
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS1);
|
||||
}
|
||||
|
||||
const static pm_uchar lcdInitSequence[] PROGMEM =
|
||||
{
|
||||
//ST7565 eq. : KS0713, SED1565, S6B1713, SPLC501C, NT7532 /34 /38, TL03245
|
||||
#if defined(LCD_ST7565R)
|
||||
0xE2, //Initialize the internal functions
|
||||
0xAE, //DON = 0: display OFF
|
||||
0xA0, //ADC = 0: normal direction (SEG132->SEG1)
|
||||
0xA6, //REV = 0: non-reverse display
|
||||
0xA4, //EON = 0: normal display. non-entire
|
||||
0xA2, //Select LCD bias
|
||||
0xC8, //SHL = 1: reverse direction (COM64->COM1)
|
||||
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
|
||||
0x60 //Set the display start line to zero
|
||||
#elif defined(LCD_ERC12864FSF)
|
||||
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
|
||||
0xA3, //Select LCD bias
|
||||
0xC0, //SHL = 0: normal direction (COM1->COM64)
|
||||
0x2F, //Control power circuit operation VC=VR=VF=1
|
||||
0x27, //Select int resistance ratio R2 R1 R0
|
||||
0x81, //Set reference voltage Mode
|
||||
0x2D, //24 SV5 SV4 SV3 SV2 SV1 SV0
|
||||
0xAF //DON = 1: display ON
|
||||
#else //ST7565P (default 9x LCD)
|
||||
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
|
||||
#endif
|
||||
};
|
||||
|
||||
void lcdInit()
|
||||
{
|
||||
LCD_LOCK();
|
||||
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES); // LCD reset
|
||||
_delay_us(2);
|
||||
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); // LCD normal operation
|
||||
_delay_us(1500);
|
||||
for (uint8_t i=0; i<DIM(lcdInitSequence); i++) {
|
||||
lcdSendCtl(pgm_read_byte(&lcdInitSequence[i])) ;
|
||||
}
|
||||
#if defined(LCD_ERC12864FSF)
|
||||
g_eeGeneral.contrast = 0x2D;
|
||||
#else
|
||||
g_eeGeneral.contrast = 0x22;
|
||||
#endif
|
||||
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++) {
|
||||
#if defined(LCD_ST7565R)
|
||||
lcdSendCtl(0x01);
|
||||
#else
|
||||
lcdSendCtl(0x04);
|
||||
#endif
|
||||
lcdSendCtl(0x10); // Column addr 0
|
||||
lcdSendCtl( y | 0xB0); //Page addr y
|
||||
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
|
||||
#if defined(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 (coord_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();
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
void lcdSendCtl(uint8_t val)
|
||||
{
|
||||
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
|
||||
#if defined(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);
|
||||
#if defined(LCD_MULTIPLEX)
|
||||
DDRA = 0x00; // Set LCD_DAT pins to input
|
||||
#endif
|
||||
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS1);
|
||||
}
|
||||
|
||||
const static pm_uchar lcdInitSequence[] PROGMEM =
|
||||
{
|
||||
//ST7565 eq. : KS0713, SED1565, S6B1713, SPLC501C, NT7532 /34 /38, TL03245
|
||||
#if defined(LCD_ST7565R)
|
||||
0xE2, //Initialize the internal functions
|
||||
0xAE, //DON = 0: display OFF
|
||||
0xA0, //ADC = 0: normal direction (SEG132->SEG1)
|
||||
0xA6, //REV = 0: non-reverse display
|
||||
0xA4, //EON = 0: normal display. non-entire
|
||||
0xA2, //Select LCD bias
|
||||
0xC8, //SHL = 1: reverse direction (COM64->COM1)
|
||||
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
|
||||
0x60 //Set the display start line to zero
|
||||
#elif defined(LCD_ERC12864FSF)
|
||||
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
|
||||
0xA3, //Select LCD bias
|
||||
0xC0, //SHL = 0: normal direction (COM1->COM64)
|
||||
0x2F, //Control power circuit operation VC=VR=VF=1
|
||||
0x27, //Select int resistance ratio R2 R1 R0
|
||||
0x81, //Set reference voltage Mode
|
||||
0x2D, //24 SV5 SV4 SV3 SV2 SV1 SV0
|
||||
0xAF //DON = 1: display ON
|
||||
#else //ST7565P (default 9x LCD)
|
||||
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
|
||||
#endif
|
||||
};
|
||||
|
||||
void lcdInit()
|
||||
{
|
||||
LCD_LOCK();
|
||||
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES); // LCD reset
|
||||
_delay_us(2);
|
||||
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); // LCD normal operation
|
||||
_delay_us(1500);
|
||||
for (uint8_t i=0; i<DIM(lcdInitSequence); i++) {
|
||||
lcdSendCtl(pgm_read_byte(&lcdInitSequence[i])) ;
|
||||
}
|
||||
#if defined(LCD_ERC12864FSF)
|
||||
g_eeGeneral.contrast = 0x2D;
|
||||
#else
|
||||
g_eeGeneral.contrast = 0x22;
|
||||
#endif
|
||||
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++) {
|
||||
#if defined(LCD_ST7565R)
|
||||
lcdSendCtl(0x01);
|
||||
#else
|
||||
lcdSendCtl(0x04);
|
||||
#endif
|
||||
lcdSendCtl(0x10); // Column addr 0
|
||||
lcdSendCtl( y | 0xB0); //Page addr y
|
||||
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
|
||||
#if defined(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 (coord_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();
|
||||
}
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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(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
|
||||
|
||||
#if defined(LCD_KS108)
|
||||
#include "targets/9x/lcd_ks108_driver.cpp"
|
||||
#elif defined(LCD_ST7920)
|
||||
#include "targets/9x/lcd_st7920_driver.cpp"
|
||||
#else
|
||||
#include "targets/9x/lcd_default_driver.cpp"
|
||||
#endif
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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(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
|
||||
|
||||
#if defined(LCD_KS108)
|
||||
#include "targets/9x/lcd_ks108_driver.cpp"
|
||||
#elif defined(LCD_ST7920)
|
||||
#include "targets/9x/lcd_st7920_driver.cpp"
|
||||
#else
|
||||
#include "targets/9x/lcd_default_driver.cpp"
|
||||
#endif
|
||||
|
||||
@@ -1,92 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 DISPLAY_SET_COLUMN 0x40
|
||||
#define DISPLAY_SET_PAGE 0xB8
|
||||
#define DISPLAY_SET_START 0XC0
|
||||
#define DISPLAY_ON_CMD 0x3F
|
||||
#define CS1_on PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS1)
|
||||
#define CS1_off PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1)
|
||||
#define CS2_on PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS2)
|
||||
#define CS2_off PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS2)
|
||||
#define A0_on PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0)
|
||||
#define A0_off PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_A0)
|
||||
#define E_on PORTC_LCD_CTRL |= (1<<OUT_C_LCD_E)
|
||||
#define E_off PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E)
|
||||
|
||||
void lcdPulseEnable(void)
|
||||
{
|
||||
E_on;
|
||||
_delay_us(4);
|
||||
E_off;
|
||||
}
|
||||
|
||||
void lcdSendCtl(uint8_t val)
|
||||
{
|
||||
PORTA_LCD_DAT = val;
|
||||
A0_off;
|
||||
lcdPulseEnable();
|
||||
A0_on;
|
||||
}
|
||||
|
||||
void lcdInit()
|
||||
{
|
||||
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES); //LCD reset
|
||||
_delay_us(20);
|
||||
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); //LCD normal operation
|
||||
CS1_on;
|
||||
lcdSendCtl(DISPLAY_ON_CMD);
|
||||
lcdSendCtl(DISPLAY_SET_START);
|
||||
CS1_off;
|
||||
CS2_on;
|
||||
lcdSendCtl(DISPLAY_ON_CMD);
|
||||
lcdSendCtl(DISPLAY_SET_START);
|
||||
CS2_off;
|
||||
}
|
||||
|
||||
void lcdSetRefVolt(uint8_t val)
|
||||
{
|
||||
}
|
||||
|
||||
void lcdRefreshSide()
|
||||
{
|
||||
static uint8_t change = 0; // toggle left or right lcd writing
|
||||
uint8_t *p;
|
||||
if (change == 0){ CS2_off; CS1_on; p = displayBuf; change = 1;} // Right
|
||||
else{ CS1_off; CS2_on; p = displayBuf + 64; change = 0;} // Left
|
||||
|
||||
for (uint8_t page=0; page < 8; page++) {
|
||||
lcdSendCtl(DISPLAY_SET_COLUMN); // Column addr 0
|
||||
lcdSendCtl( page | DISPLAY_SET_PAGE); //Page addr
|
||||
A0_on;
|
||||
for (coord_t x=64; x>0; --x) {
|
||||
PORTA_LCD_DAT = *p++;
|
||||
lcdPulseEnable();
|
||||
}
|
||||
p += 64;
|
||||
}
|
||||
A0_off;
|
||||
}
|
||||
|
||||
void lcdRefresh()
|
||||
{
|
||||
lcdRefreshSide();
|
||||
lcdRefreshSide();
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 DISPLAY_SET_COLUMN 0x40
|
||||
#define DISPLAY_SET_PAGE 0xB8
|
||||
#define DISPLAY_SET_START 0XC0
|
||||
#define DISPLAY_ON_CMD 0x3F
|
||||
#define CS1_on PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS1)
|
||||
#define CS1_off PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1)
|
||||
#define CS2_on PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS2)
|
||||
#define CS2_off PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS2)
|
||||
#define A0_on PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0)
|
||||
#define A0_off PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_A0)
|
||||
#define E_on PORTC_LCD_CTRL |= (1<<OUT_C_LCD_E)
|
||||
#define E_off PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E)
|
||||
|
||||
void lcdPulseEnable(void)
|
||||
{
|
||||
E_on;
|
||||
_delay_us(4);
|
||||
E_off;
|
||||
}
|
||||
|
||||
void lcdSendCtl(uint8_t val)
|
||||
{
|
||||
PORTA_LCD_DAT = val;
|
||||
A0_off;
|
||||
lcdPulseEnable();
|
||||
A0_on;
|
||||
}
|
||||
|
||||
void lcdInit()
|
||||
{
|
||||
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES); //LCD reset
|
||||
_delay_us(20);
|
||||
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); //LCD normal operation
|
||||
CS1_on;
|
||||
lcdSendCtl(DISPLAY_ON_CMD);
|
||||
lcdSendCtl(DISPLAY_SET_START);
|
||||
CS1_off;
|
||||
CS2_on;
|
||||
lcdSendCtl(DISPLAY_ON_CMD);
|
||||
lcdSendCtl(DISPLAY_SET_START);
|
||||
CS2_off;
|
||||
}
|
||||
|
||||
void lcdSetRefVolt(uint8_t val)
|
||||
{
|
||||
}
|
||||
|
||||
void lcdRefreshSide()
|
||||
{
|
||||
static uint8_t change = 0; // toggle left or right lcd writing
|
||||
uint8_t *p;
|
||||
if (change == 0){ CS2_off; CS1_on; p = displayBuf; change = 1;} // Right
|
||||
else{ CS1_off; CS2_on; p = displayBuf + 64; change = 0;} // Left
|
||||
|
||||
for (uint8_t page=0; page < 8; page++) {
|
||||
lcdSendCtl(DISPLAY_SET_COLUMN); // Column addr 0
|
||||
lcdSendCtl( page | DISPLAY_SET_PAGE); //Page addr
|
||||
A0_on;
|
||||
for (coord_t x=64; x>0; --x) {
|
||||
PORTA_LCD_DAT = *p++;
|
||||
lcdPulseEnable();
|
||||
}
|
||||
p += 64;
|
||||
}
|
||||
A0_off;
|
||||
}
|
||||
|
||||
void lcdRefresh()
|
||||
{
|
||||
lcdRefreshSide();
|
||||
lcdRefreshSide();
|
||||
}
|
||||
|
||||
@@ -1,137 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
void lcdSendCtl(uint8_t val)
|
||||
{
|
||||
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
|
||||
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);
|
||||
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS1);
|
||||
}
|
||||
|
||||
const static pm_uchar lcdInitSequence[] PROGMEM =
|
||||
{
|
||||
0x30, // Set 8-bit interface
|
||||
0x36, // Repeat with graphics bit set to ON
|
||||
0x0C, // Display ON, cursor and blink OFF
|
||||
0x01, // Clear display, reset address
|
||||
0x06 // Display ON, no cursor
|
||||
};
|
||||
|
||||
void lcdInit()
|
||||
{
|
||||
LCD_LOCK();
|
||||
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES); //LCD reset
|
||||
_delay_us(2);
|
||||
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); //LCD normal operation
|
||||
_delay_ms(40);
|
||||
for (uint8_t i=0; i<DIM(lcdInitSequence); i++) {
|
||||
lcdSendCtl(pgm_read_byte(&lcdInitSequence[i])) ;
|
||||
_delay_us(80);
|
||||
}
|
||||
g_eeGeneral.contrast = 0x22;
|
||||
LCD_UNLOCK();
|
||||
}
|
||||
|
||||
void lcdSetRefVolt(uint8_t val)
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t lcdRefresh_ST7920(uint8_t full)
|
||||
{
|
||||
LCD_LOCK();
|
||||
static uint8_t state;
|
||||
uint8_t yst;
|
||||
uint8_t yend;
|
||||
uint8_t y_table[6]={0,13,26,39,52,64};
|
||||
uint8_t x_addr = 0;
|
||||
uint8_t y_addr = 0;
|
||||
uint16_t line_offset = 0;
|
||||
uint8_t col_offset = 0;
|
||||
uint8_t bit_count = 0;
|
||||
uint8_t result;
|
||||
uint8_t *p;
|
||||
|
||||
if(full!=0){
|
||||
yst=0;
|
||||
yend=64;
|
||||
state=0;
|
||||
}
|
||||
else{ //Since writing to ST7920 is too slow we need to split it to five bands
|
||||
yst=y_table[state];
|
||||
yend=y_table[state+1];
|
||||
if (state==4){
|
||||
state=0;
|
||||
}
|
||||
else{
|
||||
state++;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t y=yst; y<yend; y++) {
|
||||
x_addr = 0;
|
||||
//Convert coordinates to weirdly-arranged 128x64 screen (the ST7920 is mapped for 256x32 displays)
|
||||
if (y > 31) {
|
||||
y_addr = y - 32; //Because there are only 31 addressable lines in the ST7920
|
||||
x_addr += 8; //so we overflow x (7 visible bytes per line) to reach the bottom half
|
||||
}
|
||||
else {
|
||||
y_addr = y;
|
||||
}
|
||||
lcdSendCtl( 0x80 | y_addr ); //Set Vertical Address
|
||||
_delay_us(49);
|
||||
lcdSendCtl( 0x80 | x_addr ); //Set Horizontal Address
|
||||
_delay_us(49);
|
||||
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0); //HIGH RS and LOW RW will put the LCD to
|
||||
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW); //Write data register mode
|
||||
bit_count = y & 0x07; //Count from 0 bis 7 -> 0=0, 1=1..7=7, 8=0, 9=1...
|
||||
col_offset = 1 << bit_count; //Build a value for a AND operation with the vorrect bitposition
|
||||
line_offset = ( y / 8 ) * 128; //On the ST7565 there are 8 lines with each 128 bytes width
|
||||
for (coord_t x=0; x<16; x++) { //Walk through 16 bytes form left to right (128 Pixel)
|
||||
p = displayBuf + line_offset + ( x * 8 ); //Calculate the position of the first byte im array
|
||||
// adressing the bytes sequential and set the bits at the correct position merging them with an OR operation to get all bits in one byte
|
||||
// the position of the LSB is the right-most position of the byte to the ST7920
|
||||
result = ((*p++ & col_offset)!=0?0x80:0);
|
||||
result |= ((*p++ & col_offset)!=0?0x40:0);
|
||||
result |= ((*p++ & col_offset)!=0?0x20:0);
|
||||
result |= ((*p++ & col_offset)!=0?0x10:0);
|
||||
result |= ((*p++ & col_offset)!=0?0x08:0);
|
||||
result |= ((*p++ & col_offset)!=0?0x04:0);
|
||||
result |= ((*p++ & col_offset) !=0?0x02:0);
|
||||
result |= ((*p++ & col_offset)!=0?0x01:0);
|
||||
PORTA_LCD_DAT = result;
|
||||
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_E);
|
||||
_delay_us(8);
|
||||
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
|
||||
_delay_us(49);
|
||||
}
|
||||
}
|
||||
LCD_UNLOCK();
|
||||
return state;
|
||||
}
|
||||
|
||||
void lcdRefresh()
|
||||
{
|
||||
lcdRefresh_ST7920(1);
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
void lcdSendCtl(uint8_t val)
|
||||
{
|
||||
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
|
||||
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);
|
||||
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS1);
|
||||
}
|
||||
|
||||
const static pm_uchar lcdInitSequence[] PROGMEM =
|
||||
{
|
||||
0x30, // Set 8-bit interface
|
||||
0x36, // Repeat with graphics bit set to ON
|
||||
0x0C, // Display ON, cursor and blink OFF
|
||||
0x01, // Clear display, reset address
|
||||
0x06 // Display ON, no cursor
|
||||
};
|
||||
|
||||
void lcdInit()
|
||||
{
|
||||
LCD_LOCK();
|
||||
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES); //LCD reset
|
||||
_delay_us(2);
|
||||
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); //LCD normal operation
|
||||
_delay_ms(40);
|
||||
for (uint8_t i=0; i<DIM(lcdInitSequence); i++) {
|
||||
lcdSendCtl(pgm_read_byte(&lcdInitSequence[i])) ;
|
||||
_delay_us(80);
|
||||
}
|
||||
g_eeGeneral.contrast = 0x22;
|
||||
LCD_UNLOCK();
|
||||
}
|
||||
|
||||
void lcdSetRefVolt(uint8_t val)
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t lcdRefresh_ST7920(uint8_t full)
|
||||
{
|
||||
LCD_LOCK();
|
||||
static uint8_t state;
|
||||
uint8_t yst;
|
||||
uint8_t yend;
|
||||
uint8_t y_table[6]={0,13,26,39,52,64};
|
||||
uint8_t x_addr = 0;
|
||||
uint8_t y_addr = 0;
|
||||
uint16_t line_offset = 0;
|
||||
uint8_t col_offset = 0;
|
||||
uint8_t bit_count = 0;
|
||||
uint8_t result;
|
||||
uint8_t *p;
|
||||
|
||||
if(full!=0){
|
||||
yst=0;
|
||||
yend=64;
|
||||
state=0;
|
||||
}
|
||||
else{ //Since writing to ST7920 is too slow we need to split it to five bands
|
||||
yst=y_table[state];
|
||||
yend=y_table[state+1];
|
||||
if (state==4){
|
||||
state=0;
|
||||
}
|
||||
else{
|
||||
state++;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t y=yst; y<yend; y++) {
|
||||
x_addr = 0;
|
||||
//Convert coordinates to weirdly-arranged 128x64 screen (the ST7920 is mapped for 256x32 displays)
|
||||
if (y > 31) {
|
||||
y_addr = y - 32; //Because there are only 31 addressable lines in the ST7920
|
||||
x_addr += 8; //so we overflow x (7 visible bytes per line) to reach the bottom half
|
||||
}
|
||||
else {
|
||||
y_addr = y;
|
||||
}
|
||||
lcdSendCtl( 0x80 | y_addr ); //Set Vertical Address
|
||||
_delay_us(49);
|
||||
lcdSendCtl( 0x80 | x_addr ); //Set Horizontal Address
|
||||
_delay_us(49);
|
||||
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0); //HIGH RS and LOW RW will put the LCD to
|
||||
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW); //Write data register mode
|
||||
bit_count = y & 0x07; //Count from 0 bis 7 -> 0=0, 1=1..7=7, 8=0, 9=1...
|
||||
col_offset = 1 << bit_count; //Build a value for a AND operation with the vorrect bitposition
|
||||
line_offset = ( y / 8 ) * 128; //On the ST7565 there are 8 lines with each 128 bytes width
|
||||
for (coord_t x=0; x<16; x++) { //Walk through 16 bytes form left to right (128 Pixel)
|
||||
p = displayBuf + line_offset + ( x * 8 ); //Calculate the position of the first byte im array
|
||||
// adressing the bytes sequential and set the bits at the correct position merging them with an OR operation to get all bits in one byte
|
||||
// the position of the LSB is the right-most position of the byte to the ST7920
|
||||
result = ((*p++ & col_offset)!=0?0x80:0);
|
||||
result |= ((*p++ & col_offset)!=0?0x40:0);
|
||||
result |= ((*p++ & col_offset)!=0?0x20:0);
|
||||
result |= ((*p++ & col_offset)!=0?0x10:0);
|
||||
result |= ((*p++ & col_offset)!=0?0x08:0);
|
||||
result |= ((*p++ & col_offset)!=0?0x04:0);
|
||||
result |= ((*p++ & col_offset) !=0?0x02:0);
|
||||
result |= ((*p++ & col_offset)!=0?0x01:0);
|
||||
PORTA_LCD_DAT = result;
|
||||
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_E);
|
||||
_delay_us(8);
|
||||
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
|
||||
_delay_us(49);
|
||||
}
|
||||
}
|
||||
LCD_UNLOCK();
|
||||
return state;
|
||||
}
|
||||
|
||||
void lcdRefresh()
|
||||
{
|
||||
lcdRefresh_ST7920(1);
|
||||
}
|
||||
|
||||
+139
-139
@@ -1,139 +1,139 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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
|
||||
TRACE("playFile(\"%04d.ad4\")", value);
|
||||
#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
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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
|
||||
TRACE("playFile(\"%04d.ad4\")", value);
|
||||
#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
|
||||
}
|
||||
}
|
||||
|
||||
+125
-125
@@ -1,125 +1,125 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 setScaledVolume(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, att) playDuration((d))
|
||||
#define PLAY_DURATION_ATT
|
||||
#define PLAY_TIME
|
||||
#define IS_PLAY_TIME() (0)
|
||||
#define IS_PLAYING(id) (0) /* isPlaying() */
|
||||
#define PLAY_VALUE(v, id) playValue((v))
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 setScaledVolume(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, att) playDuration((d))
|
||||
#define PLAY_DURATION_ATT
|
||||
#define PLAY_TIME
|
||||
#define IS_PLAY_TIME() (0)
|
||||
#define IS_PLAYING(id) (0) /* isPlaying() */
|
||||
#define PLAY_VALUE(v, id) playValue((v))
|
||||
|
||||
@@ -1,56 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 <OsConfig.h>
|
||||
#include "board.h"
|
||||
#if defined(STM32F2)
|
||||
#include "dwt.h" // the old ST library that we use does not define DWT register for STM32F2xx
|
||||
#endif
|
||||
|
||||
#define SYSTEM_TICKS_1US ((CFG_CPU_FREQ + 500000) / 1000000) // number of system ticks in 1us
|
||||
#define SYSTEM_TICKS_01US ((CFG_CPU_FREQ + 5000000) / 10000000) // number of system ticks in 0.1us (rounding needed for sys frequencies that are not multiple of 10MHz)
|
||||
|
||||
void delaysInit(void)
|
||||
{
|
||||
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
|
||||
DWT->CYCCNT = 0;
|
||||
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
|
||||
}
|
||||
|
||||
void delay_01us(uint16_t nb)
|
||||
{
|
||||
volatile uint32_t dwtStart = DWT->CYCCNT;
|
||||
volatile uint32_t dwtTotal = (SYSTEM_TICKS_01US * nb) - 10;
|
||||
while ((DWT->CYCCNT - dwtStart) < dwtTotal);
|
||||
}
|
||||
|
||||
void delay_us(uint16_t nb)
|
||||
{
|
||||
volatile uint32_t dwtStart = DWT->CYCCNT;
|
||||
volatile uint32_t dwtTotal = (SYSTEM_TICKS_1US * nb) - 10;
|
||||
while ((DWT->CYCCNT - dwtStart) < dwtTotal);
|
||||
}
|
||||
|
||||
void delay_ms(uint32_t ms)
|
||||
{
|
||||
while (ms--) {
|
||||
delay_us(1000);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 <OsConfig.h>
|
||||
#include "board.h"
|
||||
#if defined(STM32F2)
|
||||
#include "dwt.h" // the old ST library that we use does not define DWT register for STM32F2xx
|
||||
#endif
|
||||
|
||||
#define SYSTEM_TICKS_1US ((CFG_CPU_FREQ + 500000) / 1000000) // number of system ticks in 1us
|
||||
#define SYSTEM_TICKS_01US ((CFG_CPU_FREQ + 5000000) / 10000000) // number of system ticks in 0.1us (rounding needed for sys frequencies that are not multiple of 10MHz)
|
||||
|
||||
void delaysInit(void)
|
||||
{
|
||||
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
|
||||
DWT->CYCCNT = 0;
|
||||
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
|
||||
}
|
||||
|
||||
void delay_01us(uint16_t nb)
|
||||
{
|
||||
volatile uint32_t dwtStart = DWT->CYCCNT;
|
||||
volatile uint32_t dwtTotal = (SYSTEM_TICKS_01US * nb) - 10;
|
||||
while ((DWT->CYCCNT - dwtStart) < dwtTotal);
|
||||
}
|
||||
|
||||
void delay_us(uint16_t nb)
|
||||
{
|
||||
volatile uint32_t dwtStart = DWT->CYCCNT;
|
||||
volatile uint32_t dwtTotal = (SYSTEM_TICKS_1US * nb) - 10;
|
||||
while ((DWT->CYCCNT - dwtStart) < dwtTotal);
|
||||
}
|
||||
|
||||
void delay_ms(uint32_t ms)
|
||||
{
|
||||
while (ms--) {
|
||||
delay_us(1000);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,86 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 rtcSetTime(const struct gtm * t)
|
||||
{
|
||||
g_ms100 = 0; // start of next second begins now
|
||||
|
||||
RTC_TimeTypeDef RTC_TimeStruct;
|
||||
RTC_DateTypeDef RTC_DateStruct;
|
||||
|
||||
RTC_TimeStructInit(&RTC_TimeStruct);
|
||||
RTC_DateStructInit(&RTC_DateStruct);
|
||||
|
||||
RTC_TimeStruct.RTC_Hours = t->tm_hour;
|
||||
RTC_TimeStruct.RTC_Minutes = t->tm_min;
|
||||
RTC_TimeStruct.RTC_Seconds = t->tm_sec;
|
||||
RTC_DateStruct.RTC_Year = t->tm_year - 100;
|
||||
RTC_DateStruct.RTC_Month = t->tm_mon + 1;
|
||||
RTC_DateStruct.RTC_Date = t->tm_mday;
|
||||
|
||||
RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);
|
||||
RTC_SetDate(RTC_Format_BIN, &RTC_DateStruct);
|
||||
}
|
||||
|
||||
void rtcGetTime(struct gtm * t)
|
||||
{
|
||||
RTC_TimeTypeDef RTC_TimeStruct;
|
||||
RTC_DateTypeDef RTC_DateStruct;
|
||||
|
||||
RTC_GetTime(RTC_Format_BIN, &RTC_TimeStruct);
|
||||
RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct);
|
||||
|
||||
t->tm_hour = RTC_TimeStruct.RTC_Hours;
|
||||
t->tm_min = RTC_TimeStruct.RTC_Minutes;
|
||||
t->tm_sec = RTC_TimeStruct.RTC_Seconds;
|
||||
t->tm_year = RTC_DateStruct.RTC_Year + 100; // STM32 year is two decimals only (so base is currently 2000), gtm is based on number of years since 1900
|
||||
t->tm_mon = RTC_DateStruct.RTC_Month - 1;
|
||||
t->tm_mday = RTC_DateStruct.RTC_Date;
|
||||
}
|
||||
|
||||
void rtcInit()
|
||||
{
|
||||
RTC_InitTypeDef RTC_InitStruct;
|
||||
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
|
||||
PWR_BackupAccessCmd(ENABLE);
|
||||
RCC_LSEConfig(RCC_LSE_ON);
|
||||
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
|
||||
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
|
||||
RCC_RTCCLKCmd(ENABLE);
|
||||
RTC_WaitForSynchro();
|
||||
|
||||
// RTC time base = LSE / ((AsynchPrediv+1) * (SynchPrediv+1)) = 1 Hz*/
|
||||
RTC_InitStruct.RTC_HourFormat = RTC_HourFormat_24;
|
||||
RTC_InitStruct.RTC_AsynchPrediv = 127;
|
||||
RTC_InitStruct.RTC_SynchPrediv = 255;
|
||||
RTC_Init(&RTC_InitStruct);
|
||||
|
||||
struct gtm utm;
|
||||
rtcGetTime(&utm);
|
||||
g_rtcTime = gmktime(&utm);
|
||||
|
||||
#if defined(RAMBACKUP)
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_BKPSRAM, ENABLE);
|
||||
PWR_BackupRegulatorCmd(ENABLE);
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 rtcSetTime(const struct gtm * t)
|
||||
{
|
||||
g_ms100 = 0; // start of next second begins now
|
||||
|
||||
RTC_TimeTypeDef RTC_TimeStruct;
|
||||
RTC_DateTypeDef RTC_DateStruct;
|
||||
|
||||
RTC_TimeStructInit(&RTC_TimeStruct);
|
||||
RTC_DateStructInit(&RTC_DateStruct);
|
||||
|
||||
RTC_TimeStruct.RTC_Hours = t->tm_hour;
|
||||
RTC_TimeStruct.RTC_Minutes = t->tm_min;
|
||||
RTC_TimeStruct.RTC_Seconds = t->tm_sec;
|
||||
RTC_DateStruct.RTC_Year = t->tm_year - 100;
|
||||
RTC_DateStruct.RTC_Month = t->tm_mon + 1;
|
||||
RTC_DateStruct.RTC_Date = t->tm_mday;
|
||||
|
||||
RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);
|
||||
RTC_SetDate(RTC_Format_BIN, &RTC_DateStruct);
|
||||
}
|
||||
|
||||
void rtcGetTime(struct gtm * t)
|
||||
{
|
||||
RTC_TimeTypeDef RTC_TimeStruct;
|
||||
RTC_DateTypeDef RTC_DateStruct;
|
||||
|
||||
RTC_GetTime(RTC_Format_BIN, &RTC_TimeStruct);
|
||||
RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct);
|
||||
|
||||
t->tm_hour = RTC_TimeStruct.RTC_Hours;
|
||||
t->tm_min = RTC_TimeStruct.RTC_Minutes;
|
||||
t->tm_sec = RTC_TimeStruct.RTC_Seconds;
|
||||
t->tm_year = RTC_DateStruct.RTC_Year + 100; // STM32 year is two decimals only (so base is currently 2000), gtm is based on number of years since 1900
|
||||
t->tm_mon = RTC_DateStruct.RTC_Month - 1;
|
||||
t->tm_mday = RTC_DateStruct.RTC_Date;
|
||||
}
|
||||
|
||||
void rtcInit()
|
||||
{
|
||||
RTC_InitTypeDef RTC_InitStruct;
|
||||
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
|
||||
PWR_BackupAccessCmd(ENABLE);
|
||||
RCC_LSEConfig(RCC_LSE_ON);
|
||||
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
|
||||
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
|
||||
RCC_RTCCLKCmd(ENABLE);
|
||||
RTC_WaitForSynchro();
|
||||
|
||||
// RTC time base = LSE / ((AsynchPrediv+1) * (SynchPrediv+1)) = 1 Hz*/
|
||||
RTC_InitStruct.RTC_HourFormat = RTC_HourFormat_24;
|
||||
RTC_InitStruct.RTC_AsynchPrediv = 127;
|
||||
RTC_InitStruct.RTC_SynchPrediv = 255;
|
||||
RTC_Init(&RTC_InitStruct);
|
||||
|
||||
struct gtm utm;
|
||||
rtcGetTime(&utm);
|
||||
g_rtcTime = gmktime(&utm);
|
||||
|
||||
#if defined(RAMBACKUP)
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_BKPSRAM, ENABLE);
|
||||
PWR_BackupRegulatorCmd(ENABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,171 +1,171 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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"
|
||||
|
||||
uint8_t serial2Mode = 0;
|
||||
Fifo<uint8_t, 512> serial2TxFifo;
|
||||
DMAFifo<32> serial2RxFifo __DMA (SERIAL_DMA_Stream_RX);
|
||||
|
||||
void uart3Setup(unsigned int baudrate, bool dma)
|
||||
{
|
||||
USART_InitTypeDef USART_InitStructure;
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
GPIO_PinAFConfig(SERIAL_GPIO, SERIAL_GPIO_PinSource_RX, SERIAL_GPIO_AF);
|
||||
GPIO_PinAFConfig(SERIAL_GPIO, SERIAL_GPIO_PinSource_TX, SERIAL_GPIO_AF);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = SERIAL_GPIO_PIN_TX | SERIAL_GPIO_PIN_RX;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_Init(SERIAL_GPIO, &GPIO_InitStructure);
|
||||
|
||||
USART_InitStructure.USART_BaudRate = baudrate;
|
||||
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
||||
USART_InitStructure.USART_StopBits = USART_StopBits_1;
|
||||
USART_InitStructure.USART_Parity = USART_Parity_No;
|
||||
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
||||
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
|
||||
USART_Init(SERIAL_USART, &USART_InitStructure);
|
||||
|
||||
if (dma) {
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
serial2RxFifo.clear();
|
||||
USART_ITConfig(SERIAL_USART, USART_IT_RXNE, DISABLE);
|
||||
USART_ITConfig(SERIAL_USART, USART_IT_TXE, DISABLE);
|
||||
DMA_InitStructure.DMA_Channel = SERIAL_DMA_Channel_RX;
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&SERIAL_USART->DR);
|
||||
DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(serial2RxFifo.buffer());
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
|
||||
DMA_InitStructure.DMA_BufferSize = serial2RxFifo.size();
|
||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
|
||||
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
|
||||
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
||||
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
|
||||
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
DMA_Init(SERIAL_DMA_Stream_RX, &DMA_InitStructure);
|
||||
USART_DMACmd(SERIAL_USART, USART_DMAReq_Rx, ENABLE);
|
||||
USART_Cmd(SERIAL_USART, ENABLE);
|
||||
DMA_Cmd(SERIAL_DMA_Stream_RX, ENABLE);
|
||||
}
|
||||
else {
|
||||
USART_Cmd(SERIAL_USART, ENABLE);
|
||||
USART_ITConfig(SERIAL_USART, USART_IT_RXNE, ENABLE);
|
||||
USART_ITConfig(SERIAL_USART, USART_IT_TXE, DISABLE);
|
||||
NVIC_SetPriority(SERIAL_USART_IRQn, 7);
|
||||
NVIC_EnableIRQ(SERIAL_USART_IRQn);
|
||||
}
|
||||
}
|
||||
|
||||
void serial2Init(unsigned int mode, unsigned int protocol)
|
||||
{
|
||||
serial2Stop();
|
||||
|
||||
serial2Mode = mode;
|
||||
|
||||
switch (mode) {
|
||||
case UART_MODE_TELEMETRY_MIRROR:
|
||||
uart3Setup(FRSKY_SPORT_BAUDRATE, false);
|
||||
break;
|
||||
#if !defined(USB_SERIAL) && (defined(DEBUG) || defined(CLI))
|
||||
case UART_MODE_DEBUG:
|
||||
uart3Setup(DEBUG_BAUDRATE, false);
|
||||
break;
|
||||
#endif
|
||||
case UART_MODE_TELEMETRY:
|
||||
if (protocol == PROTOCOL_FRSKY_D_SECONDARY) {
|
||||
uart3Setup(FRSKY_D_BAUDRATE, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void serial2Putc(char c)
|
||||
{
|
||||
#if !defined(SIMU)
|
||||
int n = 0;
|
||||
while (serial2TxFifo.isFull()) {
|
||||
delay_ms(1);
|
||||
if (++n > 100) return;
|
||||
}
|
||||
serial2TxFifo.push(c);
|
||||
USART_ITConfig(SERIAL_USART, USART_IT_TXE, ENABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void serial2SbusInit()
|
||||
{
|
||||
uart3Setup(SBUS_BAUDRATE, true);
|
||||
SERIAL_USART->CR1 |= USART_CR1_M | USART_CR1_PCE ;
|
||||
}
|
||||
|
||||
void serial2Stop()
|
||||
{
|
||||
DMA_DeInit(SERIAL_DMA_Stream_RX);
|
||||
USART_DeInit(SERIAL_USART);
|
||||
}
|
||||
|
||||
uint8_t serial2TracesEnabled()
|
||||
{
|
||||
#if defined(DEBUG)
|
||||
return (serial2Mode == UART_MODE_DEBUG);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" void SERIAL_USART_IRQHandler(void)
|
||||
{
|
||||
DEBUG_INTERRUPT(INT_SER2);
|
||||
// Send
|
||||
if (USART_GetITStatus(SERIAL_USART, USART_IT_TXE) != RESET) {
|
||||
uint8_t txchar;
|
||||
if (serial2TxFifo.pop(txchar)) {
|
||||
/* Write one byte to the transmit data register */
|
||||
USART_SendData(SERIAL_USART, txchar);
|
||||
}
|
||||
else {
|
||||
USART_ITConfig(SERIAL_USART, USART_IT_TXE, DISABLE);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(USB_SERIAL) && defined(CLI)
|
||||
// Receive
|
||||
uint32_t status = SERIAL_USART->SR;
|
||||
while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
|
||||
uint8_t data = SERIAL_USART->DR;
|
||||
if (!(status & USART_FLAG_ERRORS)) {
|
||||
switch (serial2Mode) {
|
||||
case UART_MODE_DEBUG:
|
||||
cliRxFifo.push(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
status = SERIAL_USART->SR;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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"
|
||||
|
||||
uint8_t serial2Mode = 0;
|
||||
Fifo<uint8_t, 512> serial2TxFifo;
|
||||
DMAFifo<32> serial2RxFifo __DMA (SERIAL_DMA_Stream_RX);
|
||||
|
||||
void uart3Setup(unsigned int baudrate, bool dma)
|
||||
{
|
||||
USART_InitTypeDef USART_InitStructure;
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
GPIO_PinAFConfig(SERIAL_GPIO, SERIAL_GPIO_PinSource_RX, SERIAL_GPIO_AF);
|
||||
GPIO_PinAFConfig(SERIAL_GPIO, SERIAL_GPIO_PinSource_TX, SERIAL_GPIO_AF);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = SERIAL_GPIO_PIN_TX | SERIAL_GPIO_PIN_RX;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_Init(SERIAL_GPIO, &GPIO_InitStructure);
|
||||
|
||||
USART_InitStructure.USART_BaudRate = baudrate;
|
||||
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
||||
USART_InitStructure.USART_StopBits = USART_StopBits_1;
|
||||
USART_InitStructure.USART_Parity = USART_Parity_No;
|
||||
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
||||
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
|
||||
USART_Init(SERIAL_USART, &USART_InitStructure);
|
||||
|
||||
if (dma) {
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
serial2RxFifo.clear();
|
||||
USART_ITConfig(SERIAL_USART, USART_IT_RXNE, DISABLE);
|
||||
USART_ITConfig(SERIAL_USART, USART_IT_TXE, DISABLE);
|
||||
DMA_InitStructure.DMA_Channel = SERIAL_DMA_Channel_RX;
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&SERIAL_USART->DR);
|
||||
DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(serial2RxFifo.buffer());
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
|
||||
DMA_InitStructure.DMA_BufferSize = serial2RxFifo.size();
|
||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
|
||||
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
|
||||
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
||||
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
|
||||
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
DMA_Init(SERIAL_DMA_Stream_RX, &DMA_InitStructure);
|
||||
USART_DMACmd(SERIAL_USART, USART_DMAReq_Rx, ENABLE);
|
||||
USART_Cmd(SERIAL_USART, ENABLE);
|
||||
DMA_Cmd(SERIAL_DMA_Stream_RX, ENABLE);
|
||||
}
|
||||
else {
|
||||
USART_Cmd(SERIAL_USART, ENABLE);
|
||||
USART_ITConfig(SERIAL_USART, USART_IT_RXNE, ENABLE);
|
||||
USART_ITConfig(SERIAL_USART, USART_IT_TXE, DISABLE);
|
||||
NVIC_SetPriority(SERIAL_USART_IRQn, 7);
|
||||
NVIC_EnableIRQ(SERIAL_USART_IRQn);
|
||||
}
|
||||
}
|
||||
|
||||
void serial2Init(unsigned int mode, unsigned int protocol)
|
||||
{
|
||||
serial2Stop();
|
||||
|
||||
serial2Mode = mode;
|
||||
|
||||
switch (mode) {
|
||||
case UART_MODE_TELEMETRY_MIRROR:
|
||||
uart3Setup(FRSKY_SPORT_BAUDRATE, false);
|
||||
break;
|
||||
#if !defined(USB_SERIAL) && (defined(DEBUG) || defined(CLI))
|
||||
case UART_MODE_DEBUG:
|
||||
uart3Setup(DEBUG_BAUDRATE, false);
|
||||
break;
|
||||
#endif
|
||||
case UART_MODE_TELEMETRY:
|
||||
if (protocol == PROTOCOL_FRSKY_D_SECONDARY) {
|
||||
uart3Setup(FRSKY_D_BAUDRATE, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void serial2Putc(char c)
|
||||
{
|
||||
#if !defined(SIMU)
|
||||
int n = 0;
|
||||
while (serial2TxFifo.isFull()) {
|
||||
delay_ms(1);
|
||||
if (++n > 100) return;
|
||||
}
|
||||
serial2TxFifo.push(c);
|
||||
USART_ITConfig(SERIAL_USART, USART_IT_TXE, ENABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void serial2SbusInit()
|
||||
{
|
||||
uart3Setup(SBUS_BAUDRATE, true);
|
||||
SERIAL_USART->CR1 |= USART_CR1_M | USART_CR1_PCE ;
|
||||
}
|
||||
|
||||
void serial2Stop()
|
||||
{
|
||||
DMA_DeInit(SERIAL_DMA_Stream_RX);
|
||||
USART_DeInit(SERIAL_USART);
|
||||
}
|
||||
|
||||
uint8_t serial2TracesEnabled()
|
||||
{
|
||||
#if defined(DEBUG)
|
||||
return (serial2Mode == UART_MODE_DEBUG);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" void SERIAL_USART_IRQHandler(void)
|
||||
{
|
||||
DEBUG_INTERRUPT(INT_SER2);
|
||||
// Send
|
||||
if (USART_GetITStatus(SERIAL_USART, USART_IT_TXE) != RESET) {
|
||||
uint8_t txchar;
|
||||
if (serial2TxFifo.pop(txchar)) {
|
||||
/* Write one byte to the transmit data register */
|
||||
USART_SendData(SERIAL_USART, txchar);
|
||||
}
|
||||
else {
|
||||
USART_ITConfig(SERIAL_USART, USART_IT_TXE, DISABLE);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(USB_SERIAL) && defined(CLI)
|
||||
// Receive
|
||||
uint32_t status = SERIAL_USART->SR;
|
||||
while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
|
||||
uint8_t data = SERIAL_USART->DR;
|
||||
if (!(status & USART_FLAG_ERRORS)) {
|
||||
switch (serial2Mode) {
|
||||
case UART_MODE_DEBUG:
|
||||
cliRxFifo.push(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
status = SERIAL_USART->SR;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,118 +1,118 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
#include "usb_bsp.h"
|
||||
#include "board.h"
|
||||
#include "usbd_conf.h"
|
||||
|
||||
extern uint32_t SystemCoreClock;
|
||||
|
||||
/**
|
||||
* @brief USB_OTG_BSP_Init
|
||||
* Initilizes BSP configurations
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
|
||||
void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
RCC_AHB1PeriphClockCmd(USB_RCC_AHB1Periph_GPIO, ENABLE);
|
||||
|
||||
/* Configure DM and DP Pins */
|
||||
GPIO_InitStructure.GPIO_Pin = USB_GPIO_PIN_DM | USB_GPIO_PIN_DP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(USB_GPIO, &GPIO_InitStructure);
|
||||
|
||||
GPIO_PinAFConfig(USB_GPIO, USB_GPIO_PinSource_DM, USB_GPIO_AF);
|
||||
GPIO_PinAFConfig(USB_GPIO, USB_GPIO_PinSource_DP, USB_GPIO_AF);
|
||||
|
||||
/* Configure VBUS Pin */
|
||||
GPIO_InitStructure.GPIO_Pin = USB_GPIO_PIN_VBUS;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
|
||||
GPIO_Init(USB_GPIO, &GPIO_InitStructure);
|
||||
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
|
||||
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, ENABLE) ;
|
||||
}
|
||||
|
||||
void USB_OTG_BSP_Deinit(USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
//nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_OTG_BSP_EnableInterrupt
|
||||
* Enable USB Global interrupt
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void USB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
NVIC_SetPriority(OTG_FS_IRQn, 11); // Lower priority interrupt
|
||||
NVIC_EnableIRQ(OTG_FS_IRQn);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_OTG_BSP_DisableInterrupt
|
||||
* Disable USB Global interrupt
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void USB_OTG_BSP_DisableInterrupt(USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
NVIC_DisableIRQ(OTG_FS_IRQn);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USB_OTG_BSP_uDelay
|
||||
* This function provides delay time in micro sec
|
||||
* @param usec : Value of delay required in micro sec
|
||||
* @retval None
|
||||
*/
|
||||
void USB_OTG_BSP_uDelay (const uint32_t usec)
|
||||
{
|
||||
delay_us(usec);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USB_OTG_BSP_mDelay
|
||||
* This function provides delay time in milli sec
|
||||
* @param msec : Value of delay required in milli sec
|
||||
* @retval None
|
||||
*/
|
||||
void USB_OTG_BSP_mDelay (const uint32_t msec)
|
||||
{
|
||||
delay_ms(msec);
|
||||
}
|
||||
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
|
||||
#include "usb_bsp.h"
|
||||
#include "board.h"
|
||||
#include "usbd_conf.h"
|
||||
|
||||
extern uint32_t SystemCoreClock;
|
||||
|
||||
/**
|
||||
* @brief USB_OTG_BSP_Init
|
||||
* Initilizes BSP configurations
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
|
||||
void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
RCC_AHB1PeriphClockCmd(USB_RCC_AHB1Periph_GPIO, ENABLE);
|
||||
|
||||
/* Configure DM and DP Pins */
|
||||
GPIO_InitStructure.GPIO_Pin = USB_GPIO_PIN_DM | USB_GPIO_PIN_DP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(USB_GPIO, &GPIO_InitStructure);
|
||||
|
||||
GPIO_PinAFConfig(USB_GPIO, USB_GPIO_PinSource_DM, USB_GPIO_AF);
|
||||
GPIO_PinAFConfig(USB_GPIO, USB_GPIO_PinSource_DP, USB_GPIO_AF);
|
||||
|
||||
/* Configure VBUS Pin */
|
||||
GPIO_InitStructure.GPIO_Pin = USB_GPIO_PIN_VBUS;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
|
||||
GPIO_Init(USB_GPIO, &GPIO_InitStructure);
|
||||
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
|
||||
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, ENABLE) ;
|
||||
}
|
||||
|
||||
void USB_OTG_BSP_Deinit(USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
//nothing to do
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_OTG_BSP_EnableInterrupt
|
||||
* Enable USB Global interrupt
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void USB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
NVIC_SetPriority(OTG_FS_IRQn, 11); // Lower priority interrupt
|
||||
NVIC_EnableIRQ(OTG_FS_IRQn);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_OTG_BSP_DisableInterrupt
|
||||
* Disable USB Global interrupt
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void USB_OTG_BSP_DisableInterrupt(USB_OTG_CORE_HANDLE *pdev)
|
||||
{
|
||||
NVIC_DisableIRQ(OTG_FS_IRQn);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USB_OTG_BSP_uDelay
|
||||
* This function provides delay time in micro sec
|
||||
* @param usec : Value of delay required in micro sec
|
||||
* @retval None
|
||||
*/
|
||||
void USB_OTG_BSP_uDelay (const uint32_t usec)
|
||||
{
|
||||
delay_us(usec);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USB_OTG_BSP_mDelay
|
||||
* This function provides delay time in milli sec
|
||||
* @param msec : Value of delay required in milli sec
|
||||
* @retval None
|
||||
*/
|
||||
void USB_OTG_BSP_mDelay (const uint32_t msec)
|
||||
{
|
||||
delay_ms(msec);
|
||||
}
|
||||
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
@@ -1,168 +1,168 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef _USB_CONF_H_
|
||||
#define _USB_CONF_H_
|
||||
|
||||
#if defined(STM32F4)
|
||||
#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h"
|
||||
#else
|
||||
#include "STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/CMSIS/Device/ST/STM32F2xx/Include/stm32f2xx.h"
|
||||
#endif
|
||||
|
||||
/* USB Core and PHY interface configuration.
|
||||
Tip: To avoid modifying these defines each time you need to change the USB
|
||||
configuration, you can declare the needed define in your toolchain
|
||||
compiler preprocessor.
|
||||
*/
|
||||
/****************** USB OTG FS PHY CONFIGURATION *******************************
|
||||
* The USB OTG FS Core supports one on-chip Full Speed PHY.
|
||||
*
|
||||
* The USE_EMBEDDED_PHY symbol is defined in the project compiler preprocessor
|
||||
* when FS core is used.
|
||||
*******************************************************************************/
|
||||
#ifndef USE_USB_OTG_FS
|
||||
#define USE_USB_OTG_FS // USB2.0 Full Speed == 12 Mbit
|
||||
#endif /* USE_USB_OTG_FS */
|
||||
|
||||
#ifdef USE_USB_OTG_FS
|
||||
#define USB_OTG_FS_CORE
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* FIFO Size Configuration in Device mode
|
||||
*
|
||||
* (i) Receive data FIFO size = RAM for setup packets +
|
||||
* OUT endpoint control information +
|
||||
* data OUT packets + miscellaneous
|
||||
* Space = ONE 32-bits words
|
||||
* --> RAM for setup packets = 10 spaces
|
||||
* (n is the nbr of CTRL EPs the device core supports)
|
||||
* --> OUT EP CTRL info = 1 space
|
||||
* (one space for status information written to the FIFO along with each
|
||||
* received packet)
|
||||
* --> data OUT packets = (Largest Packet Size / 4) + 1 spaces
|
||||
* (MINIMUM to receive packets)
|
||||
* --> OR data OUT packets = at least 2*(Largest Packet Size / 4) + 1 spaces
|
||||
* (if high-bandwidth EP is enabled or multiple isochronous EPs)
|
||||
* --> miscellaneous = 1 space per OUT EP
|
||||
* (one space for transfer complete status information also pushed to the
|
||||
* FIFO with each endpoint's last packet)
|
||||
*
|
||||
* (ii)MINIMUM RAM space required for each IN EP Tx FIFO = MAX packet size for
|
||||
* that particular IN EP. More space allocated in the IN EP Tx FIFO results
|
||||
* in a better performance on the USB and can hide latencies on the AHB.
|
||||
*
|
||||
* (iii) TXn min size = 16 words. (n : Transmit FIFO index)
|
||||
* (iv) When a TxFIFO is not used, the Configuration should be as follows:
|
||||
* case 1 : n > m and Txn is not used (n,m : Transmit FIFO indexes)
|
||||
* --> Txm can use the space allocated for Txn.
|
||||
* case2 : n < m and Txn is not used (n,m : Transmit FIFO indexes)
|
||||
* --> Txn should be configured with the minimum space of 16 words
|
||||
* (v) The FIFO is used optimally when used TxFIFOs are allocated in the top
|
||||
* of the FIFO.Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones.
|
||||
* (vi) In HS case12 FIFO locations should be reserved for internal DMA registers
|
||||
* so total FIFO size should be 1012 Only instead of 1024
|
||||
*******************************************************************************/
|
||||
|
||||
/****************** USB OTG FS CONFIGURATION **********************************/
|
||||
#ifdef USB_OTG_FS_CORE
|
||||
#define RX_FIFO_FS_SIZE 128
|
||||
#define TX0_FIFO_FS_SIZE 64
|
||||
#define TX1_FIFO_FS_SIZE 128
|
||||
#define TX2_FIFO_FS_SIZE 0
|
||||
#define TX3_FIFO_FS_SIZE 0
|
||||
|
||||
// #define USB_OTG_FS_LOW_PWR_MGMT_SUPPORT
|
||||
// #define USB_OTG_FS_SOF_OUTPUT_ENABLED
|
||||
#endif
|
||||
|
||||
/****************** USB OTG MISC CONFIGURATION ********************************/
|
||||
#define VBUS_SENSING_ENABLED
|
||||
|
||||
/****************** USB OTG MODE CONFIGURATION ********************************/
|
||||
//#define USE_HOST_MODE
|
||||
#define USE_DEVICE_MODE
|
||||
//#define USE_OTG_MODE
|
||||
|
||||
#ifndef USB_OTG_FS_CORE
|
||||
#ifndef USB_OTG_HS_CORE
|
||||
#error "USB_OTG_HS_CORE or USB_OTG_FS_CORE should be defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef USE_DEVICE_MODE
|
||||
#ifndef USE_HOST_MODE
|
||||
#error "USE_DEVICE_MODE or USE_HOST_MODE should be defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef USE_USB_OTG_HS
|
||||
#ifndef USE_USB_OTG_FS
|
||||
#error "USE_USB_OTG_HS or USE_USB_OTG_FS should be defined"
|
||||
#endif
|
||||
#else //USE_USB_OTG_HS
|
||||
#ifndef USE_ULPI_PHY
|
||||
#ifndef USE_EMBEDDED_PHY
|
||||
#error "USE_ULPI_PHY or USE_EMBEDDED_PHY should be defined"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/****************** C Compilers dependant keywords ****************************/
|
||||
/* In HS mode and when the DMA is used, all variables and data structures dealing
|
||||
with the DMA during the transaction process should be 4-bytes aligned */
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined (__GNUC__) /* GNU Compiler */
|
||||
#define __ALIGN_END __attribute__ ((aligned (4)))
|
||||
#define __ALIGN_BEGIN
|
||||
#else
|
||||
#define __ALIGN_END
|
||||
#if defined (__CC_ARM) /* ARM Compiler */
|
||||
#define __ALIGN_BEGIN __align(4)
|
||||
#elif defined (__ICCARM__) /* IAR Compiler */
|
||||
#define __ALIGN_BEGIN
|
||||
#elif defined (__TASKING__) /* TASKING Compiler */
|
||||
#define __ALIGN_BEGIN __align(4)
|
||||
#endif /* __CC_ARM */
|
||||
#endif /* __GNUC__ */
|
||||
#else
|
||||
#define __ALIGN_BEGIN
|
||||
#define __ALIGN_END
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
|
||||
/* __packed keyword used to decrease the data type alignment to 1-byte */
|
||||
#if !defined(__packed)
|
||||
#if defined (__CC_ARM) /* ARM Compiler */
|
||||
#define __packed __packed
|
||||
#elif defined (__ICCARM__) /* IAR Compiler */
|
||||
#define __packed __packed
|
||||
#elif defined ( __GNUC__ ) /* GNU Compiler */
|
||||
#define __packed __attribute__ ((__packed__))
|
||||
#elif defined (__TASKING__) /* TASKING Compiler */
|
||||
#define __packed __unaligned
|
||||
#endif /* __CC_ARM */
|
||||
#endif
|
||||
|
||||
#endif // _USB_CONF_H_
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef _USB_CONF_H_
|
||||
#define _USB_CONF_H_
|
||||
|
||||
#if defined(STM32F4)
|
||||
#include "STM32F4xx_DSP_StdPeriph_Lib_V1.4.0/Libraries/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h"
|
||||
#else
|
||||
#include "STM32F2xx_StdPeriph_Lib_V1.1.0/Libraries/CMSIS/Device/ST/STM32F2xx/Include/stm32f2xx.h"
|
||||
#endif
|
||||
|
||||
/* USB Core and PHY interface configuration.
|
||||
Tip: To avoid modifying these defines each time you need to change the USB
|
||||
configuration, you can declare the needed define in your toolchain
|
||||
compiler preprocessor.
|
||||
*/
|
||||
/****************** USB OTG FS PHY CONFIGURATION *******************************
|
||||
* The USB OTG FS Core supports one on-chip Full Speed PHY.
|
||||
*
|
||||
* The USE_EMBEDDED_PHY symbol is defined in the project compiler preprocessor
|
||||
* when FS core is used.
|
||||
*******************************************************************************/
|
||||
#ifndef USE_USB_OTG_FS
|
||||
#define USE_USB_OTG_FS // USB2.0 Full Speed == 12 Mbit
|
||||
#endif /* USE_USB_OTG_FS */
|
||||
|
||||
#ifdef USE_USB_OTG_FS
|
||||
#define USB_OTG_FS_CORE
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* FIFO Size Configuration in Device mode
|
||||
*
|
||||
* (i) Receive data FIFO size = RAM for setup packets +
|
||||
* OUT endpoint control information +
|
||||
* data OUT packets + miscellaneous
|
||||
* Space = ONE 32-bits words
|
||||
* --> RAM for setup packets = 10 spaces
|
||||
* (n is the nbr of CTRL EPs the device core supports)
|
||||
* --> OUT EP CTRL info = 1 space
|
||||
* (one space for status information written to the FIFO along with each
|
||||
* received packet)
|
||||
* --> data OUT packets = (Largest Packet Size / 4) + 1 spaces
|
||||
* (MINIMUM to receive packets)
|
||||
* --> OR data OUT packets = at least 2*(Largest Packet Size / 4) + 1 spaces
|
||||
* (if high-bandwidth EP is enabled or multiple isochronous EPs)
|
||||
* --> miscellaneous = 1 space per OUT EP
|
||||
* (one space for transfer complete status information also pushed to the
|
||||
* FIFO with each endpoint's last packet)
|
||||
*
|
||||
* (ii)MINIMUM RAM space required for each IN EP Tx FIFO = MAX packet size for
|
||||
* that particular IN EP. More space allocated in the IN EP Tx FIFO results
|
||||
* in a better performance on the USB and can hide latencies on the AHB.
|
||||
*
|
||||
* (iii) TXn min size = 16 words. (n : Transmit FIFO index)
|
||||
* (iv) When a TxFIFO is not used, the Configuration should be as follows:
|
||||
* case 1 : n > m and Txn is not used (n,m : Transmit FIFO indexes)
|
||||
* --> Txm can use the space allocated for Txn.
|
||||
* case2 : n < m and Txn is not used (n,m : Transmit FIFO indexes)
|
||||
* --> Txn should be configured with the minimum space of 16 words
|
||||
* (v) The FIFO is used optimally when used TxFIFOs are allocated in the top
|
||||
* of the FIFO.Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones.
|
||||
* (vi) In HS case12 FIFO locations should be reserved for internal DMA registers
|
||||
* so total FIFO size should be 1012 Only instead of 1024
|
||||
*******************************************************************************/
|
||||
|
||||
/****************** USB OTG FS CONFIGURATION **********************************/
|
||||
#ifdef USB_OTG_FS_CORE
|
||||
#define RX_FIFO_FS_SIZE 128
|
||||
#define TX0_FIFO_FS_SIZE 64
|
||||
#define TX1_FIFO_FS_SIZE 128
|
||||
#define TX2_FIFO_FS_SIZE 0
|
||||
#define TX3_FIFO_FS_SIZE 0
|
||||
|
||||
// #define USB_OTG_FS_LOW_PWR_MGMT_SUPPORT
|
||||
// #define USB_OTG_FS_SOF_OUTPUT_ENABLED
|
||||
#endif
|
||||
|
||||
/****************** USB OTG MISC CONFIGURATION ********************************/
|
||||
#define VBUS_SENSING_ENABLED
|
||||
|
||||
/****************** USB OTG MODE CONFIGURATION ********************************/
|
||||
//#define USE_HOST_MODE
|
||||
#define USE_DEVICE_MODE
|
||||
//#define USE_OTG_MODE
|
||||
|
||||
#ifndef USB_OTG_FS_CORE
|
||||
#ifndef USB_OTG_HS_CORE
|
||||
#error "USB_OTG_HS_CORE or USB_OTG_FS_CORE should be defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef USE_DEVICE_MODE
|
||||
#ifndef USE_HOST_MODE
|
||||
#error "USE_DEVICE_MODE or USE_HOST_MODE should be defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef USE_USB_OTG_HS
|
||||
#ifndef USE_USB_OTG_FS
|
||||
#error "USE_USB_OTG_HS or USE_USB_OTG_FS should be defined"
|
||||
#endif
|
||||
#else //USE_USB_OTG_HS
|
||||
#ifndef USE_ULPI_PHY
|
||||
#ifndef USE_EMBEDDED_PHY
|
||||
#error "USE_ULPI_PHY or USE_EMBEDDED_PHY should be defined"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/****************** C Compilers dependant keywords ****************************/
|
||||
/* In HS mode and when the DMA is used, all variables and data structures dealing
|
||||
with the DMA during the transaction process should be 4-bytes aligned */
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined (__GNUC__) /* GNU Compiler */
|
||||
#define __ALIGN_END __attribute__ ((aligned (4)))
|
||||
#define __ALIGN_BEGIN
|
||||
#else
|
||||
#define __ALIGN_END
|
||||
#if defined (__CC_ARM) /* ARM Compiler */
|
||||
#define __ALIGN_BEGIN __align(4)
|
||||
#elif defined (__ICCARM__) /* IAR Compiler */
|
||||
#define __ALIGN_BEGIN
|
||||
#elif defined (__TASKING__) /* TASKING Compiler */
|
||||
#define __ALIGN_BEGIN __align(4)
|
||||
#endif /* __CC_ARM */
|
||||
#endif /* __GNUC__ */
|
||||
#else
|
||||
#define __ALIGN_BEGIN
|
||||
#define __ALIGN_END
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
|
||||
/* __packed keyword used to decrease the data type alignment to 1-byte */
|
||||
#if !defined(__packed)
|
||||
#if defined (__CC_ARM) /* ARM Compiler */
|
||||
#define __packed __packed
|
||||
#elif defined (__ICCARM__) /* IAR Compiler */
|
||||
#define __packed __packed
|
||||
#elif defined ( __GNUC__ ) /* GNU Compiler */
|
||||
#define __packed __attribute__ ((__packed__))
|
||||
#elif defined (__TASKING__) /* TASKING Compiler */
|
||||
#define __packed __unaligned
|
||||
#endif /* __CC_ARM */
|
||||
#endif
|
||||
|
||||
#endif // _USB_CONF_H_
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
|
||||
@@ -1,232 +1,232 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#pragma data_alignment = 4
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
|
||||
#include "opentx.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_conf.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
|
||||
/* These are external variables imported from CDC core to be used for IN
|
||||
transfer management. */
|
||||
extern uint8_t APP_Rx_Buffer []; /* Write CDC received data in this buffer.
|
||||
These data will be sent over USB IN endpoint
|
||||
in the CDC core functions. */
|
||||
extern volatile uint32_t APP_Rx_ptr_in; /* Increment this pointer or roll it back to
|
||||
start address when writing received data
|
||||
in the buffer APP_Rx_Buffer. */
|
||||
extern volatile uint32_t APP_Rx_ptr_out;
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
static uint16_t VCP_Init (void);
|
||||
static uint16_t VCP_DeInit (void);
|
||||
static uint16_t VCP_Ctrl (uint32_t Cmd, uint8_t* Buf, uint32_t Len);
|
||||
static uint16_t VCP_DataRx (uint8_t* Buf, uint32_t Len);
|
||||
|
||||
extern "C" const CDC_IF_Prop_TypeDef VCP_fops =
|
||||
{
|
||||
VCP_Init,
|
||||
VCP_DeInit,
|
||||
VCP_Ctrl,
|
||||
0,
|
||||
VCP_DataRx
|
||||
};
|
||||
|
||||
} // extern "C"
|
||||
|
||||
bool cdcConnected = false;
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/**
|
||||
* @brief VCP_Init
|
||||
* Initializes the Media on the STM32
|
||||
* @param None
|
||||
* @retval Result of the opeartion (USBD_OK in all cases)
|
||||
*/
|
||||
static uint16_t VCP_Init(void)
|
||||
{
|
||||
cdcConnected = true;
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief VCP_DeInit
|
||||
* DeInitializes the Media on the STM32
|
||||
* @param None
|
||||
* @retval Result of the opeartion (USBD_OK in all cases)
|
||||
*/
|
||||
static uint16_t VCP_DeInit(void)
|
||||
{
|
||||
cdcConnected = false;
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief VCP_Ctrl
|
||||
* Manage the CDC class requests
|
||||
* @param Cmd: Command code
|
||||
* @param Buf: Buffer containing command data (request parameters)
|
||||
* @param Len: Number of data to be sent (in bytes)
|
||||
* @retval Result of the opeartion (USBD_OK in all cases)
|
||||
*/
|
||||
static uint16_t VCP_Ctrl (uint32_t Cmd, uint8_t* Buf, uint32_t Len)
|
||||
{
|
||||
switch (Cmd)
|
||||
{
|
||||
case SEND_ENCAPSULATED_COMMAND:
|
||||
/* Not needed for this driver */
|
||||
break;
|
||||
|
||||
case GET_ENCAPSULATED_RESPONSE:
|
||||
/* Not needed for this driver */
|
||||
break;
|
||||
|
||||
case SET_COMM_FEATURE:
|
||||
/* Not needed for this driver */
|
||||
break;
|
||||
|
||||
case GET_COMM_FEATURE:
|
||||
/* Not needed for this driver */
|
||||
break;
|
||||
|
||||
case CLEAR_COMM_FEATURE:
|
||||
/* Not needed for this driver */
|
||||
break;
|
||||
|
||||
case SET_LINE_CODING:
|
||||
/* Not needed for this driver */
|
||||
break;
|
||||
|
||||
case GET_LINE_CODING:
|
||||
/* Not needed for this driver */
|
||||
break;
|
||||
|
||||
case SET_CONTROL_LINE_STATE:
|
||||
/* Not needed for this driver */
|
||||
break;
|
||||
|
||||
case SEND_BREAK:
|
||||
/* Not needed for this driver */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
// some debug vars
|
||||
uint16_t usbWraps = 0;
|
||||
uint16_t charsWritten = 0;
|
||||
|
||||
void usbSerialPutc(uint8_t c)
|
||||
{
|
||||
|
||||
/*
|
||||
Apparently there is no reliable way to tell if the
|
||||
virtual serial port is opened or not.
|
||||
|
||||
The cdcConnected variable only reports the state
|
||||
of the physical USB connection.
|
||||
*/
|
||||
|
||||
if (!cdcConnected) return;
|
||||
|
||||
uint32_t prim = __get_PRIMASK();
|
||||
__disable_irq();
|
||||
uint32_t txDataLen = APP_RX_DATA_SIZE + APP_Rx_ptr_in - APP_Rx_ptr_out;
|
||||
if (!prim) __enable_irq();
|
||||
|
||||
if (txDataLen >= APP_RX_DATA_SIZE) {
|
||||
txDataLen -= APP_RX_DATA_SIZE;
|
||||
}
|
||||
if (txDataLen > (APP_RX_DATA_SIZE - CDC_DATA_MAX_PACKET_SIZE)) return; // buffer is too full, skip this write
|
||||
|
||||
++charsWritten;
|
||||
|
||||
/*
|
||||
APP_Rx_Buffer and associated variables must be modified
|
||||
atomically, because they are used from the interrupt
|
||||
*/
|
||||
|
||||
/* Read PRIMASK register, check interrupt status before you disable them */
|
||||
/* Returns 0 if they are enabled, or non-zero if disabled */
|
||||
prim = __get_PRIMASK();
|
||||
__disable_irq();
|
||||
APP_Rx_Buffer[APP_Rx_ptr_in++] = c;
|
||||
if(APP_Rx_ptr_in >= APP_RX_DATA_SIZE)
|
||||
{
|
||||
APP_Rx_ptr_in = 0;
|
||||
++usbWraps;
|
||||
}
|
||||
if (!prim) __enable_irq();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief VCP_DataRx
|
||||
* Data received over USB OUT endpoint is available here
|
||||
*
|
||||
* @note
|
||||
* This function will block any OUT packet reception on USB endpoint
|
||||
* until exiting this function. If you exit this function before transfer
|
||||
* is complete on CDC interface (ie. using DMA controller) it will result
|
||||
* in receiving more data while previous ones are still not sent.
|
||||
*
|
||||
* @note
|
||||
* This function is executed inside the USBD_OTG_ISR_Handler() interrupt handler!
|
||||
|
||||
* @param Buf: Buffer of data to be received
|
||||
* @param Len: Number of data received (in bytes)
|
||||
* @retval Result of the opeartion: USBD_OK if all operations are OK else VCP_FAIL
|
||||
*/
|
||||
static uint16_t VCP_DataRx (uint8_t* Buf, uint32_t Len)
|
||||
{
|
||||
// TODO: try implementing inbound flow control:
|
||||
// if the cliRxFifo does not have enough free space to receive all
|
||||
// available characters, return VCP_FAIL. Maybe that will throttle down
|
||||
// the sender and we will receive the same packet at a later time.
|
||||
|
||||
#if defined(CLI)
|
||||
//copy data to the application FIFO
|
||||
for (uint32_t i = 0; i < Len; i++)
|
||||
{
|
||||
cliRxFifo.push(Buf[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#pragma data_alignment = 4
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
|
||||
#include "opentx.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_conf.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
|
||||
/* These are external variables imported from CDC core to be used for IN
|
||||
transfer management. */
|
||||
extern uint8_t APP_Rx_Buffer []; /* Write CDC received data in this buffer.
|
||||
These data will be sent over USB IN endpoint
|
||||
in the CDC core functions. */
|
||||
extern volatile uint32_t APP_Rx_ptr_in; /* Increment this pointer or roll it back to
|
||||
start address when writing received data
|
||||
in the buffer APP_Rx_Buffer. */
|
||||
extern volatile uint32_t APP_Rx_ptr_out;
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
static uint16_t VCP_Init (void);
|
||||
static uint16_t VCP_DeInit (void);
|
||||
static uint16_t VCP_Ctrl (uint32_t Cmd, uint8_t* Buf, uint32_t Len);
|
||||
static uint16_t VCP_DataRx (uint8_t* Buf, uint32_t Len);
|
||||
|
||||
extern "C" const CDC_IF_Prop_TypeDef VCP_fops =
|
||||
{
|
||||
VCP_Init,
|
||||
VCP_DeInit,
|
||||
VCP_Ctrl,
|
||||
0,
|
||||
VCP_DataRx
|
||||
};
|
||||
|
||||
} // extern "C"
|
||||
|
||||
bool cdcConnected = false;
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/**
|
||||
* @brief VCP_Init
|
||||
* Initializes the Media on the STM32
|
||||
* @param None
|
||||
* @retval Result of the opeartion (USBD_OK in all cases)
|
||||
*/
|
||||
static uint16_t VCP_Init(void)
|
||||
{
|
||||
cdcConnected = true;
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief VCP_DeInit
|
||||
* DeInitializes the Media on the STM32
|
||||
* @param None
|
||||
* @retval Result of the opeartion (USBD_OK in all cases)
|
||||
*/
|
||||
static uint16_t VCP_DeInit(void)
|
||||
{
|
||||
cdcConnected = false;
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief VCP_Ctrl
|
||||
* Manage the CDC class requests
|
||||
* @param Cmd: Command code
|
||||
* @param Buf: Buffer containing command data (request parameters)
|
||||
* @param Len: Number of data to be sent (in bytes)
|
||||
* @retval Result of the opeartion (USBD_OK in all cases)
|
||||
*/
|
||||
static uint16_t VCP_Ctrl (uint32_t Cmd, uint8_t* Buf, uint32_t Len)
|
||||
{
|
||||
switch (Cmd)
|
||||
{
|
||||
case SEND_ENCAPSULATED_COMMAND:
|
||||
/* Not needed for this driver */
|
||||
break;
|
||||
|
||||
case GET_ENCAPSULATED_RESPONSE:
|
||||
/* Not needed for this driver */
|
||||
break;
|
||||
|
||||
case SET_COMM_FEATURE:
|
||||
/* Not needed for this driver */
|
||||
break;
|
||||
|
||||
case GET_COMM_FEATURE:
|
||||
/* Not needed for this driver */
|
||||
break;
|
||||
|
||||
case CLEAR_COMM_FEATURE:
|
||||
/* Not needed for this driver */
|
||||
break;
|
||||
|
||||
case SET_LINE_CODING:
|
||||
/* Not needed for this driver */
|
||||
break;
|
||||
|
||||
case GET_LINE_CODING:
|
||||
/* Not needed for this driver */
|
||||
break;
|
||||
|
||||
case SET_CONTROL_LINE_STATE:
|
||||
/* Not needed for this driver */
|
||||
break;
|
||||
|
||||
case SEND_BREAK:
|
||||
/* Not needed for this driver */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
// some debug vars
|
||||
uint16_t usbWraps = 0;
|
||||
uint16_t charsWritten = 0;
|
||||
|
||||
void usbSerialPutc(uint8_t c)
|
||||
{
|
||||
|
||||
/*
|
||||
Apparently there is no reliable way to tell if the
|
||||
virtual serial port is opened or not.
|
||||
|
||||
The cdcConnected variable only reports the state
|
||||
of the physical USB connection.
|
||||
*/
|
||||
|
||||
if (!cdcConnected) return;
|
||||
|
||||
uint32_t prim = __get_PRIMASK();
|
||||
__disable_irq();
|
||||
uint32_t txDataLen = APP_RX_DATA_SIZE + APP_Rx_ptr_in - APP_Rx_ptr_out;
|
||||
if (!prim) __enable_irq();
|
||||
|
||||
if (txDataLen >= APP_RX_DATA_SIZE) {
|
||||
txDataLen -= APP_RX_DATA_SIZE;
|
||||
}
|
||||
if (txDataLen > (APP_RX_DATA_SIZE - CDC_DATA_MAX_PACKET_SIZE)) return; // buffer is too full, skip this write
|
||||
|
||||
++charsWritten;
|
||||
|
||||
/*
|
||||
APP_Rx_Buffer and associated variables must be modified
|
||||
atomically, because they are used from the interrupt
|
||||
*/
|
||||
|
||||
/* Read PRIMASK register, check interrupt status before you disable them */
|
||||
/* Returns 0 if they are enabled, or non-zero if disabled */
|
||||
prim = __get_PRIMASK();
|
||||
__disable_irq();
|
||||
APP_Rx_Buffer[APP_Rx_ptr_in++] = c;
|
||||
if(APP_Rx_ptr_in >= APP_RX_DATA_SIZE)
|
||||
{
|
||||
APP_Rx_ptr_in = 0;
|
||||
++usbWraps;
|
||||
}
|
||||
if (!prim) __enable_irq();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief VCP_DataRx
|
||||
* Data received over USB OUT endpoint is available here
|
||||
*
|
||||
* @note
|
||||
* This function will block any OUT packet reception on USB endpoint
|
||||
* until exiting this function. If you exit this function before transfer
|
||||
* is complete on CDC interface (ie. using DMA controller) it will result
|
||||
* in receiving more data while previous ones are still not sent.
|
||||
*
|
||||
* @note
|
||||
* This function is executed inside the USBD_OTG_ISR_Handler() interrupt handler!
|
||||
|
||||
* @param Buf: Buffer of data to be received
|
||||
* @param Len: Number of data received (in bytes)
|
||||
* @retval Result of the opeartion: USBD_OK if all operations are OK else VCP_FAIL
|
||||
*/
|
||||
static uint16_t VCP_DataRx (uint8_t* Buf, uint32_t Len)
|
||||
{
|
||||
// TODO: try implementing inbound flow control:
|
||||
// if the cliRxFifo does not have enough free space to receive all
|
||||
// available characters, return VCP_FAIL. Maybe that will throttle down
|
||||
// the sender and we will receive the same packet at a later time.
|
||||
|
||||
#if defined(CLI)
|
||||
//copy data to the application FIFO
|
||||
for (uint32_t i = 0; i < Len; i++)
|
||||
{
|
||||
cliRxFifo.push(Buf[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
@@ -18,47 +18,47 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef _USBD_CONF_H_
|
||||
#define _USBD_CONF_H_
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_conf.h"
|
||||
|
||||
#define USBD_CFG_MAX_NUM 1
|
||||
#define USBD_ITF_MAX_NUM 1
|
||||
#define USB_MAX_STR_DESC_SIZ 64
|
||||
|
||||
#define USBD_SELF_POWERED
|
||||
|
||||
/* Class Layer Parameter */
|
||||
|
||||
#define MSC_IN_EP 0x81
|
||||
#define MSC_OUT_EP 0x01
|
||||
#define MSC_MAX_PACKET 64
|
||||
|
||||
#define MSC_MEDIA_PACKET 4096
|
||||
|
||||
#define HID_IN_EP 0x81
|
||||
#define HID_OUT_EP 0x01
|
||||
|
||||
#define HID_IN_PACKET 11
|
||||
#define HID_OUT_PACKET 9
|
||||
|
||||
#define CDC_IN_EP 0x81 /* EP1 for data IN */
|
||||
#define CDC_OUT_EP 0x01 /* EP1 for data OUT */
|
||||
#define CDC_CMD_EP 0x82 /* EP2 for CDC commands */
|
||||
|
||||
/* CDC Endpoints parameters: you can fine tune these values depending on the needed baudrates and performance. */
|
||||
#define CDC_DATA_MAX_PACKET_SIZE 64 /* Endpoint IN & OUT Packet size */
|
||||
#define CDC_CMD_PACKET_SZE 8 /* Control Endpoint Packet size */
|
||||
|
||||
#define CDC_IN_FRAME_INTERVAL 5 /* Number of frames between IN transfers */
|
||||
#define APP_RX_DATA_SIZE 512 // USB serial port output buffer. TODO: tune this buffer size /* Total size of IN buffer: APP_RX_DATA_SIZE*8/MAX_BAUDARATE*1000 should be > CDC_IN_FRAME_INTERVAL */
|
||||
#define APP_FOPS VCP_fops
|
||||
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_conf.h"
|
||||
|
||||
#define USBD_CFG_MAX_NUM 1
|
||||
#define USBD_ITF_MAX_NUM 1
|
||||
#define USB_MAX_STR_DESC_SIZ 64
|
||||
|
||||
#define USBD_SELF_POWERED
|
||||
|
||||
/* Class Layer Parameter */
|
||||
|
||||
#define MSC_IN_EP 0x81
|
||||
#define MSC_OUT_EP 0x01
|
||||
#define MSC_MAX_PACKET 64
|
||||
|
||||
#define MSC_MEDIA_PACKET 4096
|
||||
|
||||
#define HID_IN_EP 0x81
|
||||
#define HID_OUT_EP 0x01
|
||||
|
||||
#define HID_IN_PACKET 11
|
||||
#define HID_OUT_PACKET 9
|
||||
|
||||
#define CDC_IN_EP 0x81 /* EP1 for data IN */
|
||||
#define CDC_OUT_EP 0x01 /* EP1 for data OUT */
|
||||
#define CDC_CMD_EP 0x82 /* EP2 for CDC commands */
|
||||
|
||||
/* CDC Endpoints parameters: you can fine tune these values depending on the needed baudrates and performance. */
|
||||
#define CDC_DATA_MAX_PACKET_SIZE 64 /* Endpoint IN & OUT Packet size */
|
||||
#define CDC_CMD_PACKET_SZE 8 /* Control Endpoint Packet size */
|
||||
|
||||
#define CDC_IN_FRAME_INTERVAL 5 /* Number of frames between IN transfers */
|
||||
#define APP_RX_DATA_SIZE 512 // USB serial port output buffer. TODO: tune this buffer size /* Total size of IN buffer: APP_RX_DATA_SIZE*8/MAX_BAUDARATE*1000 should be > CDC_IN_FRAME_INTERVAL */
|
||||
#define APP_FOPS VCP_fops
|
||||
|
||||
#endif // _USBD_CONF_H_
|
||||
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
|
||||
@@ -1,239 +1,239 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_desc.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "usbd_conf.h"
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_req.h"
|
||||
#include "usb_regs.h"
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_DESC
|
||||
* @brief USBD descriptors module
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_DESC_Private_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_DESC_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define USBD_VID 0x0483
|
||||
|
||||
#define USBD_LANGID_STRING 0x409
|
||||
#define USBD_MANUFACTURER_STRING "FrSky"
|
||||
#define USBD_SERIALNUMBER_FS_STRING "00000000001B"
|
||||
|
||||
|
||||
#if defined(BOOT)
|
||||
#define USBD_PID 0x5720
|
||||
#define USBD_PRODUCT_FS_STRING USB_NAME " Bootloader"
|
||||
#define USBD_CONFIGURATION_FS_STRING "MSC Config"
|
||||
#define USBD_INTERFACE_FS_STRING "MSC Interface"
|
||||
#elif defined(USB_JOYSTICK)
|
||||
#define USBD_PID 0x5710
|
||||
#define USBD_PRODUCT_FS_STRING USB_NAME " Joystick"
|
||||
#define USBD_CONFIGURATION_FS_STRING "HID Config"
|
||||
#define USBD_INTERFACE_FS_STRING "HID Interface"
|
||||
#elif defined(USB_SERIAL)
|
||||
#define USBD_PID 0x5740 // do not change, this ID is used by the ST USB driver for Windows
|
||||
#define USBD_PRODUCT_FS_STRING USB_NAME " Serial Port"
|
||||
#define USBD_CONFIGURATION_FS_STRING "VSP Config"
|
||||
#define USBD_INTERFACE_FS_STRING "VSP Interface"
|
||||
#elif defined(USB_MASS_STORAGE)
|
||||
#define USBD_PID 0x5720
|
||||
#define USBD_PRODUCT_FS_STRING USB_NAME " Mass Storage"
|
||||
#define USBD_CONFIGURATION_FS_STRING "MSC Config"
|
||||
#define USBD_INTERFACE_FS_STRING "MSC Interface"
|
||||
#endif
|
||||
|
||||
const USBD_DEVICE USR_desc =
|
||||
{
|
||||
USBD_USR_DeviceDescriptor,
|
||||
USBD_USR_LangIDStrDescriptor,
|
||||
USBD_USR_ManufacturerStrDescriptor,
|
||||
USBD_USR_ProductStrDescriptor,
|
||||
USBD_USR_SerialStrDescriptor,
|
||||
USBD_USR_ConfigStrDescriptor,
|
||||
USBD_USR_InterfaceStrDescriptor,
|
||||
};
|
||||
|
||||
/* USB Standard Device Descriptor */
|
||||
__ALIGN_BEGIN const uint8_t USBD_DeviceDesc[USB_SIZ_DEVICE_DESC] __ALIGN_END =
|
||||
{
|
||||
USB_SIZ_DEVICE_DESC, /*bLength */
|
||||
USB_DEVICE_DESCRIPTOR_TYPE, /*bDescriptorType*/
|
||||
0x00, /*bcdUSB */
|
||||
0x02,
|
||||
0x00, /*bDeviceClass*/
|
||||
0x00, /*bDeviceSubClass*/
|
||||
0x00, /*bDeviceProtocol*/
|
||||
USB_OTG_MAX_EP0_SIZE, /*bMaxPacketSize*/
|
||||
LOBYTE(USBD_VID), /*idVendor*/
|
||||
HIBYTE(USBD_VID), /*idVendor*/
|
||||
LOBYTE(USBD_PID), /*idVendor*/
|
||||
HIBYTE(USBD_PID), /*idVendor*/
|
||||
0x00, /*bcdDevice rel. 2.00*/
|
||||
0x02,
|
||||
USBD_IDX_MFC_STR, /*Index of manufacturer string*/
|
||||
USBD_IDX_PRODUCT_STR, /*Index of product string*/
|
||||
USBD_IDX_SERIAL_STR, /*Index of serial number string*/
|
||||
USBD_CFG_MAX_NUM /*bNumConfigurations*/
|
||||
}; /* USB_DeviceDescriptor */
|
||||
|
||||
/* USB Standard Device Descriptor */
|
||||
__ALIGN_BEGIN const uint8_t USBD_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
|
||||
{
|
||||
USB_LEN_DEV_QUALIFIER_DESC,
|
||||
USB_DESC_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
};
|
||||
|
||||
/* USB Standard Device Descriptor */
|
||||
__ALIGN_BEGIN const uint8_t USBD_LangIDDesc[USB_SIZ_STRING_LANGID] __ALIGN_END =
|
||||
{
|
||||
USB_SIZ_STRING_LANGID,
|
||||
USB_DESC_TYPE_STRING,
|
||||
LOBYTE(USBD_LANGID_STRING),
|
||||
HIBYTE(USBD_LANGID_STRING),
|
||||
};
|
||||
|
||||
__ALIGN_BEGIN uint8_t USBD_StrDesc[USB_MAX_STR_DESC_SIZ] __ALIGN_END ; // modified by OpenTX
|
||||
|
||||
/*
|
||||
* @brief USBD_USR_DeviceDescriptor
|
||||
* return the device descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer to data length variable
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t * USBD_USR_DeviceDescriptor( uint8_t speed , uint16_t *length)
|
||||
{
|
||||
*length = sizeof(USBD_DeviceDesc);
|
||||
memcpy(USBD_StrDesc, USBD_DeviceDesc, *length);
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_USR_LangIDStrDescriptor
|
||||
* return the LangID string descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer to data length variable
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t * USBD_USR_LangIDStrDescriptor( uint8_t speed , uint16_t *length)
|
||||
{
|
||||
*length = sizeof(USBD_LangIDDesc);
|
||||
memcpy(USBD_StrDesc, USBD_LangIDDesc, *length);
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_USR_ProductStrDescriptor
|
||||
* return the product string descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer to data length variable
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t * USBD_USR_ProductStrDescriptor( uint8_t speed , uint16_t *length)
|
||||
{
|
||||
USBD_GetString ((uint8_t*)USBD_PRODUCT_FS_STRING, USBD_StrDesc, length);
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_USR_ManufacturerStrDescriptor
|
||||
* return the manufacturer string descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer to data length variable
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t * USBD_USR_ManufacturerStrDescriptor( uint8_t speed , uint16_t *length)
|
||||
{
|
||||
USBD_GetString ((uint8_t*)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_USR_SerialStrDescriptor
|
||||
* return the serial number string descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer to data length variable
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t * USBD_USR_SerialStrDescriptor( uint8_t speed , uint16_t *length)
|
||||
{
|
||||
USBD_GetString ((uint8_t*)USBD_SERIALNUMBER_FS_STRING, USBD_StrDesc, length);
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_USR_ConfigStrDescriptor
|
||||
* return the configuration string descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer to data length variable
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t * USBD_USR_ConfigStrDescriptor( uint8_t speed , uint16_t *length)
|
||||
{
|
||||
USBD_GetString ((uint8_t *)USBD_CONFIGURATION_FS_STRING, USBD_StrDesc, length);
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_USR_InterfaceStrDescriptor
|
||||
* return the interface string descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer to data length variable
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t * USBD_USR_InterfaceStrDescriptor( uint8_t speed , uint16_t *length)
|
||||
{
|
||||
USBD_GetString ((uint8_t*)USBD_INTERFACE_FS_STRING, USBD_StrDesc, length);
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_desc.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "usbd_conf.h"
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_req.h"
|
||||
#include "usb_regs.h"
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_DESC
|
||||
* @brief USBD descriptors module
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_DESC_Private_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_DESC_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define USBD_VID 0x0483
|
||||
|
||||
#define USBD_LANGID_STRING 0x409
|
||||
#define USBD_MANUFACTURER_STRING "FrSky"
|
||||
#define USBD_SERIALNUMBER_FS_STRING "00000000001B"
|
||||
|
||||
|
||||
#if defined(BOOT)
|
||||
#define USBD_PID 0x5720
|
||||
#define USBD_PRODUCT_FS_STRING USB_NAME " Bootloader"
|
||||
#define USBD_CONFIGURATION_FS_STRING "MSC Config"
|
||||
#define USBD_INTERFACE_FS_STRING "MSC Interface"
|
||||
#elif defined(USB_JOYSTICK)
|
||||
#define USBD_PID 0x5710
|
||||
#define USBD_PRODUCT_FS_STRING USB_NAME " Joystick"
|
||||
#define USBD_CONFIGURATION_FS_STRING "HID Config"
|
||||
#define USBD_INTERFACE_FS_STRING "HID Interface"
|
||||
#elif defined(USB_SERIAL)
|
||||
#define USBD_PID 0x5740 // do not change, this ID is used by the ST USB driver for Windows
|
||||
#define USBD_PRODUCT_FS_STRING USB_NAME " Serial Port"
|
||||
#define USBD_CONFIGURATION_FS_STRING "VSP Config"
|
||||
#define USBD_INTERFACE_FS_STRING "VSP Interface"
|
||||
#elif defined(USB_MASS_STORAGE)
|
||||
#define USBD_PID 0x5720
|
||||
#define USBD_PRODUCT_FS_STRING USB_NAME " Mass Storage"
|
||||
#define USBD_CONFIGURATION_FS_STRING "MSC Config"
|
||||
#define USBD_INTERFACE_FS_STRING "MSC Interface"
|
||||
#endif
|
||||
|
||||
const USBD_DEVICE USR_desc =
|
||||
{
|
||||
USBD_USR_DeviceDescriptor,
|
||||
USBD_USR_LangIDStrDescriptor,
|
||||
USBD_USR_ManufacturerStrDescriptor,
|
||||
USBD_USR_ProductStrDescriptor,
|
||||
USBD_USR_SerialStrDescriptor,
|
||||
USBD_USR_ConfigStrDescriptor,
|
||||
USBD_USR_InterfaceStrDescriptor,
|
||||
};
|
||||
|
||||
/* USB Standard Device Descriptor */
|
||||
__ALIGN_BEGIN const uint8_t USBD_DeviceDesc[USB_SIZ_DEVICE_DESC] __ALIGN_END =
|
||||
{
|
||||
USB_SIZ_DEVICE_DESC, /*bLength */
|
||||
USB_DEVICE_DESCRIPTOR_TYPE, /*bDescriptorType*/
|
||||
0x00, /*bcdUSB */
|
||||
0x02,
|
||||
0x00, /*bDeviceClass*/
|
||||
0x00, /*bDeviceSubClass*/
|
||||
0x00, /*bDeviceProtocol*/
|
||||
USB_OTG_MAX_EP0_SIZE, /*bMaxPacketSize*/
|
||||
LOBYTE(USBD_VID), /*idVendor*/
|
||||
HIBYTE(USBD_VID), /*idVendor*/
|
||||
LOBYTE(USBD_PID), /*idVendor*/
|
||||
HIBYTE(USBD_PID), /*idVendor*/
|
||||
0x00, /*bcdDevice rel. 2.00*/
|
||||
0x02,
|
||||
USBD_IDX_MFC_STR, /*Index of manufacturer string*/
|
||||
USBD_IDX_PRODUCT_STR, /*Index of product string*/
|
||||
USBD_IDX_SERIAL_STR, /*Index of serial number string*/
|
||||
USBD_CFG_MAX_NUM /*bNumConfigurations*/
|
||||
}; /* USB_DeviceDescriptor */
|
||||
|
||||
/* USB Standard Device Descriptor */
|
||||
__ALIGN_BEGIN const uint8_t USBD_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
|
||||
{
|
||||
USB_LEN_DEV_QUALIFIER_DESC,
|
||||
USB_DESC_TYPE_DEVICE_QUALIFIER,
|
||||
0x00,
|
||||
0x02,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x40,
|
||||
0x01,
|
||||
0x00,
|
||||
};
|
||||
|
||||
/* USB Standard Device Descriptor */
|
||||
__ALIGN_BEGIN const uint8_t USBD_LangIDDesc[USB_SIZ_STRING_LANGID] __ALIGN_END =
|
||||
{
|
||||
USB_SIZ_STRING_LANGID,
|
||||
USB_DESC_TYPE_STRING,
|
||||
LOBYTE(USBD_LANGID_STRING),
|
||||
HIBYTE(USBD_LANGID_STRING),
|
||||
};
|
||||
|
||||
__ALIGN_BEGIN uint8_t USBD_StrDesc[USB_MAX_STR_DESC_SIZ] __ALIGN_END ; // modified by OpenTX
|
||||
|
||||
/*
|
||||
* @brief USBD_USR_DeviceDescriptor
|
||||
* return the device descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer to data length variable
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t * USBD_USR_DeviceDescriptor( uint8_t speed , uint16_t *length)
|
||||
{
|
||||
*length = sizeof(USBD_DeviceDesc);
|
||||
memcpy(USBD_StrDesc, USBD_DeviceDesc, *length);
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_USR_LangIDStrDescriptor
|
||||
* return the LangID string descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer to data length variable
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t * USBD_USR_LangIDStrDescriptor( uint8_t speed , uint16_t *length)
|
||||
{
|
||||
*length = sizeof(USBD_LangIDDesc);
|
||||
memcpy(USBD_StrDesc, USBD_LangIDDesc, *length);
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_USR_ProductStrDescriptor
|
||||
* return the product string descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer to data length variable
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t * USBD_USR_ProductStrDescriptor( uint8_t speed , uint16_t *length)
|
||||
{
|
||||
USBD_GetString ((uint8_t*)USBD_PRODUCT_FS_STRING, USBD_StrDesc, length);
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_USR_ManufacturerStrDescriptor
|
||||
* return the manufacturer string descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer to data length variable
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t * USBD_USR_ManufacturerStrDescriptor( uint8_t speed , uint16_t *length)
|
||||
{
|
||||
USBD_GetString ((uint8_t*)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_USR_SerialStrDescriptor
|
||||
* return the serial number string descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer to data length variable
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t * USBD_USR_SerialStrDescriptor( uint8_t speed , uint16_t *length)
|
||||
{
|
||||
USBD_GetString ((uint8_t*)USBD_SERIALNUMBER_FS_STRING, USBD_StrDesc, length);
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_USR_ConfigStrDescriptor
|
||||
* return the configuration string descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer to data length variable
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t * USBD_USR_ConfigStrDescriptor( uint8_t speed , uint16_t *length)
|
||||
{
|
||||
USBD_GetString ((uint8_t *)USBD_CONFIGURATION_FS_STRING, USBD_StrDesc, length);
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_USR_InterfaceStrDescriptor
|
||||
* return the interface string descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer to data length variable
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
uint8_t * USBD_USR_InterfaceStrDescriptor( uint8_t speed , uint16_t *length)
|
||||
{
|
||||
USBD_GetString ((uint8_t*)USBD_INTERFACE_FS_STRING, USBD_StrDesc, length);
|
||||
return USBD_StrDesc;
|
||||
}
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
|
||||
@@ -18,97 +18,97 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
|
||||
#ifndef _USBD_DESC_H_
|
||||
#define _USBD_DESC_H_
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_core.h"
|
||||
#include "usbd_def.h"
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USB_DESC
|
||||
* @brief general defines for the usb device library file
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USB_DESC_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
#define USB_DEVICE_DESCRIPTOR_TYPE 0x01
|
||||
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 0x02
|
||||
#define USB_STRING_DESCRIPTOR_TYPE 0x03
|
||||
#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04
|
||||
#define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05
|
||||
#define USB_SIZ_DEVICE_DESC 18
|
||||
#define USB_SIZ_STRING_LANGID 4
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_DESC_Exported_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_DESC_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_DESC_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
extern const uint8_t USBD_DeviceDesc [USB_SIZ_DEVICE_DESC];
|
||||
extern uint8_t USBD_StrDesc[USB_MAX_STR_DESC_SIZ];
|
||||
extern const uint8_t USBD_OtherSpeedCfgDesc[USB_LEN_CFG_DESC];
|
||||
extern const uint8_t USBD_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC];
|
||||
extern const uint8_t USBD_LangIDDesc[USB_SIZ_STRING_LANGID];
|
||||
extern const USBD_DEVICE USR_desc;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_DESC_Exported_FunctionsPrototype
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
uint8_t * USBD_USR_DeviceDescriptor( uint8_t speed , uint16_t *length);
|
||||
uint8_t * USBD_USR_LangIDStrDescriptor( uint8_t speed , uint16_t *length);
|
||||
uint8_t * USBD_USR_ManufacturerStrDescriptor ( uint8_t speed , uint16_t *length);
|
||||
uint8_t * USBD_USR_ProductStrDescriptor ( uint8_t speed , uint16_t *length);
|
||||
uint8_t * USBD_USR_SerialStrDescriptor( uint8_t speed , uint16_t *length);
|
||||
uint8_t * USBD_USR_ConfigStrDescriptor( uint8_t speed , uint16_t *length);
|
||||
uint8_t * USBD_USR_InterfaceStrDescriptor( uint8_t speed , uint16_t *length);
|
||||
|
||||
#ifdef USB_SUPPORT_USER_STRING_DESC
|
||||
uint8_t * USBD_USR_USRStringDesc (uint8_t speed, uint8_t idx , uint16_t *length);
|
||||
#endif /* USB_SUPPORT_USER_STRING_DESC */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_core.h"
|
||||
#include "usbd_def.h"
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USB_DESC
|
||||
* @brief general defines for the usb device library file
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USB_DESC_Exported_Defines
|
||||
* @{
|
||||
*/
|
||||
#define USB_DEVICE_DESCRIPTOR_TYPE 0x01
|
||||
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 0x02
|
||||
#define USB_STRING_DESCRIPTOR_TYPE 0x03
|
||||
#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04
|
||||
#define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05
|
||||
#define USB_SIZ_DEVICE_DESC 18
|
||||
#define USB_SIZ_STRING_LANGID 4
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_DESC_Exported_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_DESC_Exported_Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_DESC_Exported_Variables
|
||||
* @{
|
||||
*/
|
||||
extern const uint8_t USBD_DeviceDesc [USB_SIZ_DEVICE_DESC];
|
||||
extern uint8_t USBD_StrDesc[USB_MAX_STR_DESC_SIZ];
|
||||
extern const uint8_t USBD_OtherSpeedCfgDesc[USB_LEN_CFG_DESC];
|
||||
extern const uint8_t USBD_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC];
|
||||
extern const uint8_t USBD_LangIDDesc[USB_SIZ_STRING_LANGID];
|
||||
extern const USBD_DEVICE USR_desc;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_DESC_Exported_FunctionsPrototype
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
uint8_t * USBD_USR_DeviceDescriptor( uint8_t speed , uint16_t *length);
|
||||
uint8_t * USBD_USR_LangIDStrDescriptor( uint8_t speed , uint16_t *length);
|
||||
uint8_t * USBD_USR_ManufacturerStrDescriptor ( uint8_t speed , uint16_t *length);
|
||||
uint8_t * USBD_USR_ProductStrDescriptor ( uint8_t speed , uint16_t *length);
|
||||
uint8_t * USBD_USR_SerialStrDescriptor( uint8_t speed , uint16_t *length);
|
||||
uint8_t * USBD_USR_ConfigStrDescriptor( uint8_t speed , uint16_t *length);
|
||||
uint8_t * USBD_USR_InterfaceStrDescriptor( uint8_t speed , uint16_t *length);
|
||||
|
||||
#ifdef USB_SUPPORT_USER_STRING_DESC
|
||||
uint8_t * USBD_USR_USRStringDesc (uint8_t speed, uint8_t idx , uint16_t *length);
|
||||
#endif /* USB_SUPPORT_USER_STRING_DESC */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif // _USBD_DESC_H_
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
@@ -1,455 +1,455 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_desc.h"
|
||||
#include "usbd_hid_core.h"
|
||||
#include "usbd_req.h"
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_HID
|
||||
* @brief usbd core module
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_HID_Private_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_HID_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_HID_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_HID_Private_FunctionPrototypes
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
static uint8_t USBD_HID_Init (void *pdev,
|
||||
uint8_t cfgidx);
|
||||
|
||||
static uint8_t USBD_HID_DeInit (void *pdev,
|
||||
uint8_t cfgidx);
|
||||
|
||||
static uint8_t USBD_HID_Setup (void *pdev,
|
||||
USB_SETUP_REQ *req);
|
||||
|
||||
static const uint8_t *USBD_HID_GetCfgDesc (uint8_t speed, uint16_t *length);
|
||||
|
||||
static uint8_t USBD_HID_DataIn (void *pdev, uint8_t epnum);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
/*
|
||||
This USB HID endpoint report description defines a device with:
|
||||
* 24 digital buttons
|
||||
* 8 analog axes with 8bit resolution
|
||||
|
||||
Repot packet described as C struct is:
|
||||
|
||||
struct {
|
||||
uint8_t buttons1; //bit 0 - button 1, bit 1 - button 2, ..., mapped to channels 9-16, on if channel > 0
|
||||
uint8_t buttons2; // mapped to channels 17-24, on if channel > 0
|
||||
uint8_t buttons3; // mapped to channels 25-32, on if channel > 0
|
||||
uint8_t X; //analog value, mapped to channel 1
|
||||
uint8_t Y; //analog value, mapped to channel 2
|
||||
uint8_t Z; //analog value, mapped to channel 3
|
||||
uint8_t Rx; //analog value, mapped to channel 4
|
||||
uint8_t Ry //analog value, mapped to channel 5
|
||||
uint8_t Rz; //analog value, mapped to channel 6
|
||||
uint8_t S1; //analog value, mapped to channel 7
|
||||
uint8_t S2; //analog value, mapped to channel 8
|
||||
}
|
||||
*/
|
||||
__ALIGN_BEGIN static const uint8_t HID_JOYSTICK_ReportDesc[] __ALIGN_END =
|
||||
{
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x05, // USAGE (Game Pad)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
0xa1, 0x00, // COLLECTION (Physical)
|
||||
0x05, 0x09, // USAGE_PAGE (Button)
|
||||
0x19, 0x01, // USAGE_MINIMUM (Button 1)
|
||||
0x29, 0x18, // USAGE_MAXIMUM (Button 24)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||
0x95, 0x18, // REPORT_COUNT (24)
|
||||
0x75, 0x01, // REPORT_SIZE (1)
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x30, // USAGE (X)
|
||||
0x09, 0x31, // USAGE (Y)
|
||||
0x09, 0x32, // USAGE (Z)
|
||||
0x09, 0x33, // USAGE (Rx)
|
||||
0x09, 0x34, // USAGE (Ry)
|
||||
0x09, 0x35, // USAGE (Rz)
|
||||
0x09, 0x36, // USAGE (Slider)
|
||||
0x09, 0x36, // USAGE (Slider)
|
||||
0x15, 0x81, // LOGICAL_MINIMUM (-127)
|
||||
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x95, 0x08, // REPORT_COUNT (8)
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
0xc0, // END_COLLECTION
|
||||
0xc0 // END_COLLECTION
|
||||
};
|
||||
|
||||
|
||||
/** @defgroup USBD_HID_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
const USBD_Class_cb_TypeDef USBD_HID_cb =
|
||||
{
|
||||
USBD_HID_Init,
|
||||
USBD_HID_DeInit,
|
||||
USBD_HID_Setup,
|
||||
NULL, /*EP0_TxSent*/
|
||||
NULL, /*EP0_RxReady*/
|
||||
USBD_HID_DataIn, /*DataIn*/
|
||||
NULL, /*DataOut*/
|
||||
NULL, /*SOF */
|
||||
NULL,
|
||||
NULL,
|
||||
USBD_HID_GetCfgDesc,
|
||||
#ifdef USB_OTG_HS_CORE
|
||||
USBD_HID_GetCfgDesc, /* use same config as per FS */
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
__ALIGN_BEGIN static uint32_t USBD_HID_AltSet __ALIGN_END = 0;
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
__ALIGN_BEGIN static uint32_t USBD_HID_Protocol __ALIGN_END = 0;
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
__ALIGN_BEGIN static uint32_t USBD_HID_IdleState __ALIGN_END = 0;
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
/* USB HID device Configuration Descriptor */
|
||||
__ALIGN_BEGIN static const uint8_t USBD_HID_CfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END =
|
||||
{
|
||||
0x09, /* bLength: Configuration Descriptor size */
|
||||
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
|
||||
USB_HID_CONFIG_DESC_SIZ,
|
||||
/* wTotalLength: Bytes returned */
|
||||
0x00,
|
||||
0x01, /*bNumInterfaces: 1 interface*/
|
||||
0x01, /*bConfigurationValue: Configuration value*/
|
||||
0x00, /*iConfiguration: Index of string descriptor describing
|
||||
the configuration*/
|
||||
0xE0, /*bmAttributes: bus powered and Support Remote Wake-up */
|
||||
0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/
|
||||
|
||||
/************** Descriptor of Joystick Mouse interface ****************/
|
||||
/* 09 */
|
||||
0x09, /*bLength: Interface Descriptor size*/
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE,/*bDescriptorType: Interface descriptor type*/
|
||||
0x00, /*bInterfaceNumber: Number of Interface*/
|
||||
0x00, /*bAlternateSetting: Alternate setting*/
|
||||
0x01, /*bNumEndpoints*/
|
||||
0x03, /*bInterfaceClass: HID*/
|
||||
0x00 /*0x01*/, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
|
||||
0x00 /*0x02*/, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
|
||||
0, /*iInterface: Index of string descriptor*/
|
||||
/******************** Descriptor of Joystick Mouse HID ********************/
|
||||
/* 18 */
|
||||
0x09, /*bLength: HID Descriptor size*/
|
||||
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
|
||||
0x11, /*bcdHID: HID Class Spec release number*/
|
||||
0x01,
|
||||
0x00, /*bCountryCode: Hardware target country*/
|
||||
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
|
||||
0x22, /*bDescriptorType*/
|
||||
sizeof(HID_JOYSTICK_ReportDesc),/*wItemLength: Total length of Report descriptor*/
|
||||
0x00,
|
||||
/******************** Descriptor of Mouse endpoint ********************/
|
||||
/* 27 */
|
||||
0x07, /*bLength: Endpoint Descriptor size*/
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/
|
||||
|
||||
HID_IN_EP, /*bEndpointAddress: Endpoint Address (IN)*/
|
||||
0x03, /*bmAttributes: Interrupt endpoint*/
|
||||
HID_IN_PACKET, /*wMaxPacketSize: 4 Byte max */
|
||||
0x00,
|
||||
0x0A, /*bInterval: Polling Interval (10 ms)*/
|
||||
/* 34 */
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
static uint8_t ReportSent;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_HID_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief USBD_HID_Init
|
||||
* Initialize the HID interface
|
||||
* @param pdev: device instance
|
||||
* @param cfgidx: Configuration index
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_HID_Init (void *pdev,
|
||||
uint8_t cfgidx)
|
||||
{
|
||||
|
||||
/* Open EP IN */
|
||||
DCD_EP_Open(pdev,
|
||||
HID_IN_EP,
|
||||
HID_IN_PACKET,
|
||||
USB_OTG_EP_INT);
|
||||
|
||||
/* Open EP OUT */
|
||||
DCD_EP_Open(pdev,
|
||||
HID_OUT_EP,
|
||||
HID_OUT_PACKET,
|
||||
USB_OTG_EP_INT);
|
||||
|
||||
ReportSent = 1;
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_HID_Init
|
||||
* DeInitialize the HID layer
|
||||
* @param pdev: device instance
|
||||
* @param cfgidx: Configuration index
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_HID_DeInit (void *pdev,
|
||||
uint8_t cfgidx)
|
||||
{
|
||||
/* Close HID EPs */
|
||||
DCD_EP_Close (pdev , HID_IN_EP);
|
||||
DCD_EP_Close (pdev , HID_OUT_EP);
|
||||
|
||||
ReportSent = 1;
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_HID_Setup
|
||||
* Handle the HID specific requests
|
||||
* @param pdev: instance
|
||||
* @param req: usb requests
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_HID_Setup (void *pdev,
|
||||
USB_SETUP_REQ *req)
|
||||
{
|
||||
uint16_t len = 0;
|
||||
const uint8_t *pbuf = NULL;
|
||||
|
||||
switch (req->bmRequest & USB_REQ_TYPE_MASK)
|
||||
{
|
||||
case USB_REQ_TYPE_CLASS :
|
||||
switch (req->bRequest)
|
||||
{
|
||||
|
||||
|
||||
case HID_REQ_SET_PROTOCOL:
|
||||
USBD_HID_Protocol = (uint8_t)(req->wValue);
|
||||
break;
|
||||
|
||||
case HID_REQ_GET_PROTOCOL:
|
||||
USBD_CtlSendData (pdev,
|
||||
(uint8_t *)&USBD_HID_Protocol,
|
||||
1);
|
||||
break;
|
||||
|
||||
case HID_REQ_SET_IDLE:
|
||||
USBD_HID_IdleState = (uint8_t)(req->wValue >> 8);
|
||||
break;
|
||||
|
||||
case HID_REQ_GET_IDLE:
|
||||
USBD_CtlSendData (pdev,
|
||||
(uint8_t *)&USBD_HID_IdleState,
|
||||
1);
|
||||
break;
|
||||
|
||||
default:
|
||||
USBD_CtlError (pdev, req);
|
||||
return USBD_FAIL;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQ_TYPE_STANDARD:
|
||||
switch (req->bRequest)
|
||||
{
|
||||
case USB_REQ_GET_DESCRIPTOR:
|
||||
if( req->wValue >> 8 == HID_REPORT_DESC)
|
||||
{
|
||||
len = MIN(sizeof(HID_JOYSTICK_ReportDesc) , req->wLength);
|
||||
pbuf = HID_JOYSTICK_ReportDesc; // wiiccReportDescriptor; //
|
||||
}
|
||||
else if( req->wValue >> 8 == HID_DESCRIPTOR_TYPE)
|
||||
{
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
pbuf = USBD_HID_Desc;
|
||||
#else
|
||||
pbuf = USBD_HID_CfgDesc + 0x12;
|
||||
#endif
|
||||
len = MIN(USB_HID_DESC_SIZ , req->wLength);
|
||||
}
|
||||
|
||||
USBD_CtlSendData (pdev,
|
||||
pbuf,
|
||||
len);
|
||||
|
||||
break;
|
||||
|
||||
case USB_REQ_GET_INTERFACE :
|
||||
USBD_CtlSendData (pdev,
|
||||
(uint8_t *)&USBD_HID_AltSet,
|
||||
1);
|
||||
break;
|
||||
|
||||
case USB_REQ_SET_INTERFACE :
|
||||
USBD_HID_AltSet = (uint8_t)(req->wValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_HID_SendReport
|
||||
* Send HID Report if TX buffer is free and USB device is configured.
|
||||
* @param pdev: device instance
|
||||
* @param buff: pointer to report, if this parameter is NULL then function just test if new buffer can be sent
|
||||
* @retval status
|
||||
*/
|
||||
uint8_t USBD_HID_SendReport(USB_OTG_CORE_HANDLE *pdev, uint8_t * report, uint16_t len)
|
||||
{
|
||||
if (pdev->dev.device_status == USB_OTG_CONFIGURED) {
|
||||
if (ReportSent) {
|
||||
if (report) {
|
||||
ReportSent = 0;
|
||||
DCD_EP_Tx (pdev, HID_IN_EP, report, len);
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
}
|
||||
return USBD_FAIL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_HID_GetCfgDesc
|
||||
* return configuration descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer data length
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
static const uint8_t *USBD_HID_GetCfgDesc (uint8_t speed, uint16_t *length)
|
||||
{
|
||||
*length = sizeof (USBD_HID_CfgDesc);
|
||||
return USBD_HID_CfgDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_HID_DataIn
|
||||
* handle data IN Stage
|
||||
* @param pdev: device instance
|
||||
* @param epnum: endpoint index
|
||||
* @retval status
|
||||
|
||||
This function is called when buffer has been sent over the USB.
|
||||
The TX buffer is now empty and can be filled with new data.
|
||||
*/
|
||||
static uint8_t USBD_HID_DataIn (void *pdev,
|
||||
uint8_t epnum)
|
||||
{
|
||||
ReportSent = 1;
|
||||
/* Ensure that the FIFO is empty before a new transfer, this condition could
|
||||
be caused by a new transfer before the end of the previous transfer */
|
||||
DCD_EP_Flush(pdev, HID_IN_EP);
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usbd_desc.h"
|
||||
#include "usbd_hid_core.h"
|
||||
#include "usbd_req.h"
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_HID
|
||||
* @brief usbd core module
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_HID_Private_TypesDefinitions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_HID_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup USBD_HID_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/** @defgroup USBD_HID_Private_FunctionPrototypes
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
static uint8_t USBD_HID_Init (void *pdev,
|
||||
uint8_t cfgidx);
|
||||
|
||||
static uint8_t USBD_HID_DeInit (void *pdev,
|
||||
uint8_t cfgidx);
|
||||
|
||||
static uint8_t USBD_HID_Setup (void *pdev,
|
||||
USB_SETUP_REQ *req);
|
||||
|
||||
static const uint8_t *USBD_HID_GetCfgDesc (uint8_t speed, uint16_t *length);
|
||||
|
||||
static uint8_t USBD_HID_DataIn (void *pdev, uint8_t epnum);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
/*
|
||||
This USB HID endpoint report description defines a device with:
|
||||
* 24 digital buttons
|
||||
* 8 analog axes with 8bit resolution
|
||||
|
||||
Repot packet described as C struct is:
|
||||
|
||||
struct {
|
||||
uint8_t buttons1; //bit 0 - button 1, bit 1 - button 2, ..., mapped to channels 9-16, on if channel > 0
|
||||
uint8_t buttons2; // mapped to channels 17-24, on if channel > 0
|
||||
uint8_t buttons3; // mapped to channels 25-32, on if channel > 0
|
||||
uint8_t X; //analog value, mapped to channel 1
|
||||
uint8_t Y; //analog value, mapped to channel 2
|
||||
uint8_t Z; //analog value, mapped to channel 3
|
||||
uint8_t Rx; //analog value, mapped to channel 4
|
||||
uint8_t Ry //analog value, mapped to channel 5
|
||||
uint8_t Rz; //analog value, mapped to channel 6
|
||||
uint8_t S1; //analog value, mapped to channel 7
|
||||
uint8_t S2; //analog value, mapped to channel 8
|
||||
}
|
||||
*/
|
||||
__ALIGN_BEGIN static const uint8_t HID_JOYSTICK_ReportDesc[] __ALIGN_END =
|
||||
{
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x05, // USAGE (Game Pad)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
0xa1, 0x00, // COLLECTION (Physical)
|
||||
0x05, 0x09, // USAGE_PAGE (Button)
|
||||
0x19, 0x01, // USAGE_MINIMUM (Button 1)
|
||||
0x29, 0x18, // USAGE_MAXIMUM (Button 24)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||
0x95, 0x18, // REPORT_COUNT (24)
|
||||
0x75, 0x01, // REPORT_SIZE (1)
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x30, // USAGE (X)
|
||||
0x09, 0x31, // USAGE (Y)
|
||||
0x09, 0x32, // USAGE (Z)
|
||||
0x09, 0x33, // USAGE (Rx)
|
||||
0x09, 0x34, // USAGE (Ry)
|
||||
0x09, 0x35, // USAGE (Rz)
|
||||
0x09, 0x36, // USAGE (Slider)
|
||||
0x09, 0x36, // USAGE (Slider)
|
||||
0x15, 0x81, // LOGICAL_MINIMUM (-127)
|
||||
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x95, 0x08, // REPORT_COUNT (8)
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
0xc0, // END_COLLECTION
|
||||
0xc0 // END_COLLECTION
|
||||
};
|
||||
|
||||
|
||||
/** @defgroup USBD_HID_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
const USBD_Class_cb_TypeDef USBD_HID_cb =
|
||||
{
|
||||
USBD_HID_Init,
|
||||
USBD_HID_DeInit,
|
||||
USBD_HID_Setup,
|
||||
NULL, /*EP0_TxSent*/
|
||||
NULL, /*EP0_RxReady*/
|
||||
USBD_HID_DataIn, /*DataIn*/
|
||||
NULL, /*DataOut*/
|
||||
NULL, /*SOF */
|
||||
NULL,
|
||||
NULL,
|
||||
USBD_HID_GetCfgDesc,
|
||||
#ifdef USB_OTG_HS_CORE
|
||||
USBD_HID_GetCfgDesc, /* use same config as per FS */
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
__ALIGN_BEGIN static uint32_t USBD_HID_AltSet __ALIGN_END = 0;
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
__ALIGN_BEGIN static uint32_t USBD_HID_Protocol __ALIGN_END = 0;
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
__ALIGN_BEGIN static uint32_t USBD_HID_IdleState __ALIGN_END = 0;
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
|
||||
#pragma data_alignment=4
|
||||
#endif
|
||||
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
|
||||
/* USB HID device Configuration Descriptor */
|
||||
__ALIGN_BEGIN static const uint8_t USBD_HID_CfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END =
|
||||
{
|
||||
0x09, /* bLength: Configuration Descriptor size */
|
||||
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */
|
||||
USB_HID_CONFIG_DESC_SIZ,
|
||||
/* wTotalLength: Bytes returned */
|
||||
0x00,
|
||||
0x01, /*bNumInterfaces: 1 interface*/
|
||||
0x01, /*bConfigurationValue: Configuration value*/
|
||||
0x00, /*iConfiguration: Index of string descriptor describing
|
||||
the configuration*/
|
||||
0xE0, /*bmAttributes: bus powered and Support Remote Wake-up */
|
||||
0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/
|
||||
|
||||
/************** Descriptor of Joystick Mouse interface ****************/
|
||||
/* 09 */
|
||||
0x09, /*bLength: Interface Descriptor size*/
|
||||
USB_INTERFACE_DESCRIPTOR_TYPE,/*bDescriptorType: Interface descriptor type*/
|
||||
0x00, /*bInterfaceNumber: Number of Interface*/
|
||||
0x00, /*bAlternateSetting: Alternate setting*/
|
||||
0x01, /*bNumEndpoints*/
|
||||
0x03, /*bInterfaceClass: HID*/
|
||||
0x00 /*0x01*/, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
|
||||
0x00 /*0x02*/, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
|
||||
0, /*iInterface: Index of string descriptor*/
|
||||
/******************** Descriptor of Joystick Mouse HID ********************/
|
||||
/* 18 */
|
||||
0x09, /*bLength: HID Descriptor size*/
|
||||
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
|
||||
0x11, /*bcdHID: HID Class Spec release number*/
|
||||
0x01,
|
||||
0x00, /*bCountryCode: Hardware target country*/
|
||||
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
|
||||
0x22, /*bDescriptorType*/
|
||||
sizeof(HID_JOYSTICK_ReportDesc),/*wItemLength: Total length of Report descriptor*/
|
||||
0x00,
|
||||
/******************** Descriptor of Mouse endpoint ********************/
|
||||
/* 27 */
|
||||
0x07, /*bLength: Endpoint Descriptor size*/
|
||||
USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/
|
||||
|
||||
HID_IN_EP, /*bEndpointAddress: Endpoint Address (IN)*/
|
||||
0x03, /*bmAttributes: Interrupt endpoint*/
|
||||
HID_IN_PACKET, /*wMaxPacketSize: 4 Byte max */
|
||||
0x00,
|
||||
0x0A, /*bInterval: Polling Interval (10 ms)*/
|
||||
/* 34 */
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
static uint8_t ReportSent;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_HID_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief USBD_HID_Init
|
||||
* Initialize the HID interface
|
||||
* @param pdev: device instance
|
||||
* @param cfgidx: Configuration index
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_HID_Init (void *pdev,
|
||||
uint8_t cfgidx)
|
||||
{
|
||||
|
||||
/* Open EP IN */
|
||||
DCD_EP_Open(pdev,
|
||||
HID_IN_EP,
|
||||
HID_IN_PACKET,
|
||||
USB_OTG_EP_INT);
|
||||
|
||||
/* Open EP OUT */
|
||||
DCD_EP_Open(pdev,
|
||||
HID_OUT_EP,
|
||||
HID_OUT_PACKET,
|
||||
USB_OTG_EP_INT);
|
||||
|
||||
ReportSent = 1;
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_HID_Init
|
||||
* DeInitialize the HID layer
|
||||
* @param pdev: device instance
|
||||
* @param cfgidx: Configuration index
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_HID_DeInit (void *pdev,
|
||||
uint8_t cfgidx)
|
||||
{
|
||||
/* Close HID EPs */
|
||||
DCD_EP_Close (pdev , HID_IN_EP);
|
||||
DCD_EP_Close (pdev , HID_OUT_EP);
|
||||
|
||||
ReportSent = 1;
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_HID_Setup
|
||||
* Handle the HID specific requests
|
||||
* @param pdev: instance
|
||||
* @param req: usb requests
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_HID_Setup (void *pdev,
|
||||
USB_SETUP_REQ *req)
|
||||
{
|
||||
uint16_t len = 0;
|
||||
const uint8_t *pbuf = NULL;
|
||||
|
||||
switch (req->bmRequest & USB_REQ_TYPE_MASK)
|
||||
{
|
||||
case USB_REQ_TYPE_CLASS :
|
||||
switch (req->bRequest)
|
||||
{
|
||||
|
||||
|
||||
case HID_REQ_SET_PROTOCOL:
|
||||
USBD_HID_Protocol = (uint8_t)(req->wValue);
|
||||
break;
|
||||
|
||||
case HID_REQ_GET_PROTOCOL:
|
||||
USBD_CtlSendData (pdev,
|
||||
(uint8_t *)&USBD_HID_Protocol,
|
||||
1);
|
||||
break;
|
||||
|
||||
case HID_REQ_SET_IDLE:
|
||||
USBD_HID_IdleState = (uint8_t)(req->wValue >> 8);
|
||||
break;
|
||||
|
||||
case HID_REQ_GET_IDLE:
|
||||
USBD_CtlSendData (pdev,
|
||||
(uint8_t *)&USBD_HID_IdleState,
|
||||
1);
|
||||
break;
|
||||
|
||||
default:
|
||||
USBD_CtlError (pdev, req);
|
||||
return USBD_FAIL;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQ_TYPE_STANDARD:
|
||||
switch (req->bRequest)
|
||||
{
|
||||
case USB_REQ_GET_DESCRIPTOR:
|
||||
if( req->wValue >> 8 == HID_REPORT_DESC)
|
||||
{
|
||||
len = MIN(sizeof(HID_JOYSTICK_ReportDesc) , req->wLength);
|
||||
pbuf = HID_JOYSTICK_ReportDesc; // wiiccReportDescriptor; //
|
||||
}
|
||||
else if( req->wValue >> 8 == HID_DESCRIPTOR_TYPE)
|
||||
{
|
||||
|
||||
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
|
||||
pbuf = USBD_HID_Desc;
|
||||
#else
|
||||
pbuf = USBD_HID_CfgDesc + 0x12;
|
||||
#endif
|
||||
len = MIN(USB_HID_DESC_SIZ , req->wLength);
|
||||
}
|
||||
|
||||
USBD_CtlSendData (pdev,
|
||||
pbuf,
|
||||
len);
|
||||
|
||||
break;
|
||||
|
||||
case USB_REQ_GET_INTERFACE :
|
||||
USBD_CtlSendData (pdev,
|
||||
(uint8_t *)&USBD_HID_AltSet,
|
||||
1);
|
||||
break;
|
||||
|
||||
case USB_REQ_SET_INTERFACE :
|
||||
USBD_HID_AltSet = (uint8_t)(req->wValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_HID_SendReport
|
||||
* Send HID Report if TX buffer is free and USB device is configured.
|
||||
* @param pdev: device instance
|
||||
* @param buff: pointer to report, if this parameter is NULL then function just test if new buffer can be sent
|
||||
* @retval status
|
||||
*/
|
||||
uint8_t USBD_HID_SendReport(USB_OTG_CORE_HANDLE *pdev, uint8_t * report, uint16_t len)
|
||||
{
|
||||
if (pdev->dev.device_status == USB_OTG_CONFIGURED) {
|
||||
if (ReportSent) {
|
||||
if (report) {
|
||||
ReportSent = 0;
|
||||
DCD_EP_Tx (pdev, HID_IN_EP, report, len);
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
}
|
||||
return USBD_FAIL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_HID_GetCfgDesc
|
||||
* return configuration descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer data length
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
static const uint8_t *USBD_HID_GetCfgDesc (uint8_t speed, uint16_t *length)
|
||||
{
|
||||
*length = sizeof (USBD_HID_CfgDesc);
|
||||
return USBD_HID_CfgDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_HID_DataIn
|
||||
* handle data IN Stage
|
||||
* @param pdev: device instance
|
||||
* @param epnum: endpoint index
|
||||
* @retval status
|
||||
|
||||
This function is called when buffer has been sent over the USB.
|
||||
The TX buffer is now empty and can be filled with new data.
|
||||
*/
|
||||
static uint8_t USBD_HID_DataIn (void *pdev,
|
||||
uint8_t epnum)
|
||||
{
|
||||
ReportSent = 1;
|
||||
/* Ensure that the FIFO is empty before a new transfer, this condition could
|
||||
be caused by a new transfer before the end of the previous transfer */
|
||||
DCD_EP_Flush(pdev, HID_IN_EP);
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,122 +1,122 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "opentx.h"
|
||||
|
||||
extern "C" {
|
||||
#include "usbd_usr.h"
|
||||
|
||||
/* Points to the DEVICE_PROP structure of current device */
|
||||
/* The purpose of this register is to speed up the execution */
|
||||
|
||||
|
||||
const USBD_Usr_cb_TypeDef USR_cb =
|
||||
{
|
||||
USBD_USR_Init,
|
||||
USBD_USR_DeviceReset,
|
||||
USBD_USR_DeviceConfigured,
|
||||
USBD_USR_DeviceSuspended,
|
||||
USBD_USR_DeviceResumed,
|
||||
|
||||
USBD_USR_DeviceConnected,
|
||||
USBD_USR_DeviceDisconnected,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Whatever the user application needs to do when USB is initialised
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void USBD_USR_Init(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Displays the message on LCD on device reset event
|
||||
* @param speed : device speed
|
||||
* @retval None
|
||||
*/
|
||||
void USBD_USR_DeviceReset (uint8_t speed)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Displays the message on LCD on device config event
|
||||
* @param None
|
||||
* @retval Staus
|
||||
*/
|
||||
void USBD_USR_DeviceConfigured (void)
|
||||
{
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief Displays the message on LCD on device suspend event
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void USBD_USR_DeviceSuspended(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Displays the message on LCD on device resume event
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void USBD_USR_DeviceResumed(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_USR_DeviceConnected
|
||||
* Displays the message on LCD on device connection Event
|
||||
* @param None
|
||||
* @retval Staus
|
||||
*/
|
||||
void USBD_USR_DeviceConnected (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_USR_DeviceDisonnected
|
||||
* Displays the message on LCD on device disconnection Event
|
||||
* @param None
|
||||
* @retval Staus
|
||||
*/
|
||||
void USBD_USR_DeviceDisconnected (void)
|
||||
{
|
||||
#if !defined(BOOT) && defined(USB_MASS_STORAGE) && defined(EEPROM)
|
||||
// TODO is it really needed if we didn't write the EEPROM?
|
||||
NVIC_SystemReset();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "opentx.h"
|
||||
|
||||
extern "C" {
|
||||
#include "usbd_usr.h"
|
||||
|
||||
/* Points to the DEVICE_PROP structure of current device */
|
||||
/* The purpose of this register is to speed up the execution */
|
||||
|
||||
|
||||
const USBD_Usr_cb_TypeDef USR_cb =
|
||||
{
|
||||
USBD_USR_Init,
|
||||
USBD_USR_DeviceReset,
|
||||
USBD_USR_DeviceConfigured,
|
||||
USBD_USR_DeviceSuspended,
|
||||
USBD_USR_DeviceResumed,
|
||||
|
||||
USBD_USR_DeviceConnected,
|
||||
USBD_USR_DeviceDisconnected,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Whatever the user application needs to do when USB is initialised
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void USBD_USR_Init(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Displays the message on LCD on device reset event
|
||||
* @param speed : device speed
|
||||
* @retval None
|
||||
*/
|
||||
void USBD_USR_DeviceReset (uint8_t speed)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Displays the message on LCD on device config event
|
||||
* @param None
|
||||
* @retval Staus
|
||||
*/
|
||||
void USBD_USR_DeviceConfigured (void)
|
||||
{
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief Displays the message on LCD on device suspend event
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void USBD_USR_DeviceSuspended(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Displays the message on LCD on device resume event
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void USBD_USR_DeviceResumed(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_USR_DeviceConnected
|
||||
* Displays the message on LCD on device connection Event
|
||||
* @param None
|
||||
* @retval Staus
|
||||
*/
|
||||
void USBD_USR_DeviceConnected (void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_USR_DeviceDisonnected
|
||||
* Displays the message on LCD on device disconnection Event
|
||||
* @param None
|
||||
* @retval Staus
|
||||
*/
|
||||
void USBD_USR_DeviceDisconnected (void)
|
||||
{
|
||||
#if !defined(BOOT) && defined(USB_MASS_STORAGE) && defined(EEPROM)
|
||||
// TODO is it really needed if we didn't write the EEPROM?
|
||||
NVIC_SystemReset();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
+171
-171
@@ -1,171 +1,171 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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_
|
||||
|
||||
#include "../common/avr/board_avr.h"
|
||||
|
||||
// Board driver
|
||||
void boardInit(void);
|
||||
#define boardOff() pwrOff()
|
||||
|
||||
// Keys
|
||||
#define KEYS_GPIO_REG_MENU pinl
|
||||
#define KEYS_GPIO_PIN_MENU (1<<4)
|
||||
#define KEYS_GPIO_REG_EXIT pinl
|
||||
#define KEYS_GPIO_PIN_EXIT (1<<5)
|
||||
#define KEYS_GPIO_REG_RIGHT pinl
|
||||
#define KEYS_GPIO_PIN_RIGHT (1<<2)
|
||||
#define KEYS_GPIO_REG_LEFT pinl
|
||||
#define KEYS_GPIO_PIN_LEFT (1<<3)
|
||||
#define KEYS_GPIO_REG_UP pinl
|
||||
#define KEYS_GPIO_PIN_UP (1<<1)
|
||||
#define KEYS_GPIO_REG_DOWN pinl
|
||||
#define KEYS_GPIO_PIN_DOWN (1<<0)
|
||||
|
||||
// Trims
|
||||
#define TRIMS_GPIO_REG_LHL pinj
|
||||
#define TRIMS_GPIO_REG_LVD pinj
|
||||
#define TRIMS_GPIO_REG_RVU pinj
|
||||
#define TRIMS_GPIO_REG_RHL pinj
|
||||
#define TRIMS_GPIO_REG_LHR pinj
|
||||
#define TRIMS_GPIO_REG_LVU pinj
|
||||
#define TRIMS_GPIO_REG_RVD pinj
|
||||
#define TRIMS_GPIO_REG_RHR pinj
|
||||
#define TRIMS_GPIO_PIN_LHL (1<<0)
|
||||
#define TRIMS_GPIO_PIN_LVD (1<<2)
|
||||
#define TRIMS_GPIO_PIN_RVU (1<<5)
|
||||
#define TRIMS_GPIO_PIN_RHL (1<<6)
|
||||
#define TRIMS_GPIO_PIN_LHR (1<<1)
|
||||
#define TRIMS_GPIO_PIN_LVU (1<<3)
|
||||
#define TRIMS_GPIO_PIN_RVD (1<<4)
|
||||
#define TRIMS_GPIO_PIN_RHR (1<<7)
|
||||
|
||||
#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
|
||||
#define BLOCK_SIZE 512 /* Block Size in Bytes */
|
||||
#define sdDone()
|
||||
#define SD_IS_HC() (0)
|
||||
#define SD_GET_SPEED() (0)
|
||||
#if !defined(SIMU)
|
||||
bool sdMounted();
|
||||
void sdMountPoll();
|
||||
void sdPoll10ms();
|
||||
#endif
|
||||
|
||||
#define speakerOn() TCCR0A |= (1 << COM0A0)
|
||||
#define speakerOff() TCCR0A &= ~(1 << COM0A0)
|
||||
|
||||
// Backlight driver
|
||||
#define OUT_C_LIGHT 0
|
||||
#define backlightEnable() PORTC |= (1<<OUT_C_LIGHT)
|
||||
#define backlightDisable() PORTC &= ~(1<<OUT_C_LIGHT)
|
||||
#define isBacklightEnabled() (PORTC & (1<<OUT_C_LIGHT))
|
||||
#define BACKLIGHT_ENABLE() backlightEnable()
|
||||
#define BACKLIGHT_DISABLE() backlightDisable()
|
||||
|
||||
#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_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.
|
||||
|
||||
// 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 hapticOn() PORTD &= ~(1 << OUT_D_HAPTIC)
|
||||
#define hapticOff() PORTD |= (1 << OUT_D_HAPTIC)
|
||||
|
||||
// Rotary encoder driver
|
||||
#define REA_DOWN() (~PIND & 0x20)
|
||||
#define REB_DOWN() (~PIND & 0x10)
|
||||
#define ROTENC_DOWN() (REA_DOWN() || REB_DOWN())
|
||||
|
||||
// Buzzer driver
|
||||
#define buzzerOn() PORTE |= (1 << OUT_E_BUZZER)
|
||||
#define buzzerOff() PORTE &= ~(1 << OUT_E_BUZZER)
|
||||
|
||||
#endif // _BOARD_GRUVIN9X_H_
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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_
|
||||
|
||||
#include "../common/avr/board_avr.h"
|
||||
|
||||
// Board driver
|
||||
void boardInit(void);
|
||||
#define boardOff() pwrOff()
|
||||
|
||||
// Keys
|
||||
#define KEYS_GPIO_REG_MENU pinl
|
||||
#define KEYS_GPIO_PIN_MENU (1<<4)
|
||||
#define KEYS_GPIO_REG_EXIT pinl
|
||||
#define KEYS_GPIO_PIN_EXIT (1<<5)
|
||||
#define KEYS_GPIO_REG_RIGHT pinl
|
||||
#define KEYS_GPIO_PIN_RIGHT (1<<2)
|
||||
#define KEYS_GPIO_REG_LEFT pinl
|
||||
#define KEYS_GPIO_PIN_LEFT (1<<3)
|
||||
#define KEYS_GPIO_REG_UP pinl
|
||||
#define KEYS_GPIO_PIN_UP (1<<1)
|
||||
#define KEYS_GPIO_REG_DOWN pinl
|
||||
#define KEYS_GPIO_PIN_DOWN (1<<0)
|
||||
|
||||
// Trims
|
||||
#define TRIMS_GPIO_REG_LHL pinj
|
||||
#define TRIMS_GPIO_REG_LVD pinj
|
||||
#define TRIMS_GPIO_REG_RVU pinj
|
||||
#define TRIMS_GPIO_REG_RHL pinj
|
||||
#define TRIMS_GPIO_REG_LHR pinj
|
||||
#define TRIMS_GPIO_REG_LVU pinj
|
||||
#define TRIMS_GPIO_REG_RVD pinj
|
||||
#define TRIMS_GPIO_REG_RHR pinj
|
||||
#define TRIMS_GPIO_PIN_LHL (1<<0)
|
||||
#define TRIMS_GPIO_PIN_LVD (1<<2)
|
||||
#define TRIMS_GPIO_PIN_RVU (1<<5)
|
||||
#define TRIMS_GPIO_PIN_RHL (1<<6)
|
||||
#define TRIMS_GPIO_PIN_LHR (1<<1)
|
||||
#define TRIMS_GPIO_PIN_LVU (1<<3)
|
||||
#define TRIMS_GPIO_PIN_RVD (1<<4)
|
||||
#define TRIMS_GPIO_PIN_RHR (1<<7)
|
||||
|
||||
#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
|
||||
#define BLOCK_SIZE 512 /* Block Size in Bytes */
|
||||
#define sdDone()
|
||||
#define SD_IS_HC() (0)
|
||||
#define SD_GET_SPEED() (0)
|
||||
#if !defined(SIMU)
|
||||
bool sdMounted();
|
||||
void sdMountPoll();
|
||||
void sdPoll10ms();
|
||||
#endif
|
||||
|
||||
#define speakerOn() TCCR0A |= (1 << COM0A0)
|
||||
#define speakerOff() TCCR0A &= ~(1 << COM0A0)
|
||||
|
||||
// Backlight driver
|
||||
#define OUT_C_LIGHT 0
|
||||
#define backlightEnable() PORTC |= (1<<OUT_C_LIGHT)
|
||||
#define backlightDisable() PORTC &= ~(1<<OUT_C_LIGHT)
|
||||
#define isBacklightEnabled() (PORTC & (1<<OUT_C_LIGHT))
|
||||
#define BACKLIGHT_ENABLE() backlightEnable()
|
||||
#define BACKLIGHT_DISABLE() backlightDisable()
|
||||
|
||||
#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_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.
|
||||
|
||||
// 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 hapticOn() PORTD &= ~(1 << OUT_D_HAPTIC)
|
||||
#define hapticOff() PORTD |= (1 << OUT_D_HAPTIC)
|
||||
|
||||
// Rotary encoder driver
|
||||
#define REA_DOWN() (~PIND & 0x20)
|
||||
#define REB_DOWN() (~PIND & 0x10)
|
||||
#define ROTENC_DOWN() (REA_DOWN() || REB_DOWN())
|
||||
|
||||
// Buzzer driver
|
||||
#define buzzerOn() PORTE |= (1 << OUT_E_BUZZER)
|
||||
#define buzzerOff() PORTE &= ~(1 << OUT_E_BUZZER)
|
||||
|
||||
#endif // _BOARD_GRUVIN9X_H_
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,304 +1,304 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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_rtcGetTime (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 rtcGetTime(struct gtm * utm)
|
||||
{
|
||||
RTC rtc = {0,0,0,0,0,0,0};
|
||||
|
||||
g9x_rtcGetTime(&rtc);
|
||||
|
||||
utm->tm_year = rtc.year - TM_YEAR_BASE;
|
||||
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(const struct gtm * t)
|
||||
{
|
||||
g_ms100 = 0; // start of next second begins now
|
||||
|
||||
RTC rtc;
|
||||
rtc.year = t->tm_year + TM_YEAR_BASE;
|
||||
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;
|
||||
rtcGetTime(&utm);
|
||||
g_rtcTime = gmktime(&utm);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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_rtcGetTime (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 rtcGetTime(struct gtm * utm)
|
||||
{
|
||||
RTC rtc = {0,0,0,0,0,0,0};
|
||||
|
||||
g9x_rtcGetTime(&rtc);
|
||||
|
||||
utm->tm_year = rtc.year - TM_YEAR_BASE;
|
||||
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(const struct gtm * t)
|
||||
{
|
||||
g_ms100 = 0; // start of next second begins now
|
||||
|
||||
RTC rtc;
|
||||
rtc.year = t->tm_year + TM_YEAR_BASE;
|
||||
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;
|
||||
rtcGetTime(&utm);
|
||||
g_rtcTime = gmktime(&utm);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,260 +1,260 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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"
|
||||
|
||||
uint16_t adcValues[NUM_ANALOGS] __DMA;
|
||||
|
||||
#define ADC_CS_HIGH() (ADC_SPI_GPIO->BSRRL = ADC_SPI_PIN_CS)
|
||||
#define ADC_CS_LOW() (ADC_SPI_GPIO->BSRRH = ADC_SPI_PIN_CS)
|
||||
|
||||
#define SPI_STICK1 0
|
||||
#define SPI_STICK2 1
|
||||
#define SPI_STICK3 2
|
||||
#define SPI_STICK4 3
|
||||
#define SPI_S1 4
|
||||
#define SPI_6POS 5
|
||||
#define SPI_S2 6
|
||||
#define SPI_LS 7
|
||||
#define SPI_RS 8
|
||||
#define SPI_TX_VOLTAGE 9
|
||||
#define SPI_L2 10
|
||||
#define SPI_L1 11
|
||||
#define RESETCMD 0x4000
|
||||
#define MANUAL_MODE 0x1000 // manual mode channel 0
|
||||
|
||||
#define SAMPTIME 2 // sample time = 28 cycles
|
||||
|
||||
uint16_t SPIx_ReadWriteByte(uint16_t value)
|
||||
{
|
||||
while (SPI_I2S_GetFlagStatus(ADC_SPI, SPI_I2S_FLAG_TXE) == RESET);
|
||||
SPI_I2S_SendData(ADC_SPI, value);
|
||||
|
||||
while (SPI_I2S_GetFlagStatus(ADC_SPI, SPI_I2S_FLAG_RXNE) == RESET);
|
||||
return SPI_I2S_ReceiveData(ADC_SPI);
|
||||
}
|
||||
|
||||
static void ADS7952_Init()
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
SPI_InitTypeDef SPI_InitStructure;
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = ADC_SPI_PIN_MISO | ADC_SPI_PIN_SCK | ADC_SPI_PIN_MOSI;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(ADC_SPI_GPIO, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = ADC_SPI_PIN_CS;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(ADC_SPI_GPIO, &GPIO_InitStructure);
|
||||
|
||||
GPIO_PinAFConfig(ADC_SPI_GPIO, ADC_SPI_PinSource_SCK, ADC_GPIO_AF);
|
||||
GPIO_PinAFConfig(ADC_SPI_GPIO, ADC_SPI_PinSource_MISO, ADC_GPIO_AF);
|
||||
GPIO_PinAFConfig(ADC_SPI_GPIO, ADC_SPI_PinSource_MOSI, ADC_GPIO_AF);
|
||||
|
||||
SPI_I2S_DeInit(ADC_SPI);
|
||||
|
||||
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
|
||||
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
|
||||
SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
|
||||
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
|
||||
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
|
||||
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
|
||||
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
|
||||
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
|
||||
SPI_InitStructure.SPI_CRCPolynomial = 7;
|
||||
SPI_Init(ADC_SPI, &SPI_InitStructure);
|
||||
SPI_Cmd(ADC_SPI, ENABLE);
|
||||
SPI_I2S_ITConfig(ADC_SPI, SPI_I2S_IT_TXE, DISABLE);
|
||||
SPI_I2S_ITConfig(ADC_SPI, SPI_I2S_IT_RXNE, DISABLE);
|
||||
|
||||
ADC_CS_HIGH();
|
||||
delay_01us(1);
|
||||
ADC_CS_LOW();
|
||||
SPIx_ReadWriteByte(RESETCMD);
|
||||
ADC_CS_HIGH();
|
||||
delay_01us(1);
|
||||
ADC_CS_LOW();
|
||||
SPIx_ReadWriteByte(MANUAL_MODE);
|
||||
ADC_CS_HIGH();
|
||||
}
|
||||
|
||||
void adcInit()
|
||||
{
|
||||
ADS7952_Init();
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = ADC_GPIO_PIN_MOUSE1 | ADC_GPIO_PIN_MOUSE2;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(ADC_GPIO_MOUSE, &GPIO_InitStructure);
|
||||
|
||||
ADC3->CR1 = ADC_CR1_SCAN;
|
||||
ADC3->CR2 = ADC_CR2_ADON | ADC_CR2_DMA | ADC_CR2_DDS;
|
||||
ADC3->SQR1 = (2-1) << 20;
|
||||
ADC3->SQR2 = 0;
|
||||
ADC3->SQR3 = ADC_IN_MOUSE1 + (ADC_IN_MOUSE2<<5);
|
||||
ADC3->SMPR1 = 0;
|
||||
ADC3->SMPR2 = (ADC_SAMPTIME<<(3*ADC_IN_MOUSE1)) + (ADC_SAMPTIME<<(3*ADC_IN_MOUSE2));
|
||||
ADC->CCR = 0;
|
||||
|
||||
// Enable the DMA channel here, DMA2 stream 1, channel 2
|
||||
ADC_DMA_Stream->CR = DMA_SxCR_PL | DMA_SxCR_CHSEL_1 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC;
|
||||
ADC_DMA_Stream->PAR = CONVERT_PTR_UINT(&ADC3->DR);
|
||||
ADC_DMA_Stream->M0AR = CONVERT_PTR_UINT(&adcValues[MOUSE1]);
|
||||
ADC_DMA_Stream->NDTR = 2;
|
||||
ADC_DMA_Stream->FCR = DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0;
|
||||
}
|
||||
|
||||
const uint16_t adcCommands[MOUSE1+2] =
|
||||
{
|
||||
MANUAL_MODE | (SPI_STICK1 << 7),
|
||||
MANUAL_MODE | (SPI_STICK2 << 7),
|
||||
MANUAL_MODE | (SPI_STICK3 << 7),
|
||||
MANUAL_MODE | (SPI_STICK4 << 7),
|
||||
MANUAL_MODE | (SPI_S1 << 7),
|
||||
MANUAL_MODE | (SPI_6POS << 7),
|
||||
MANUAL_MODE | (SPI_S2 << 7),
|
||||
MANUAL_MODE | (SPI_L1 << 7),
|
||||
MANUAL_MODE | (SPI_L2 << 7),
|
||||
MANUAL_MODE | (SPI_LS << 7),
|
||||
MANUAL_MODE | (SPI_RS << 7),
|
||||
MANUAL_MODE | (SPI_TX_VOLTAGE << 7),
|
||||
MANUAL_MODE | (0 << 7), // small joystick left/right
|
||||
MANUAL_MODE | (0 << 7) // small joystick up/down
|
||||
};
|
||||
|
||||
void adcReadSPIDummy()
|
||||
{
|
||||
// A dummy command to get things started
|
||||
// (because the sampled data is lagging behind for two command cycles)
|
||||
ADC_CS_LOW();
|
||||
delay_01us(1);
|
||||
SPIx_ReadWriteByte(adcCommands[0]);
|
||||
ADC_CS_HIGH();
|
||||
delay_01us(1);
|
||||
}
|
||||
|
||||
uint32_t adcReadNextSPIChannel(uint8_t index)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
|
||||
// This delay is to allow charging of ADC input capacitor
|
||||
// after the MUX changes from one channel to the other.
|
||||
// It was determined experimentally. Biggest problem seems to be
|
||||
// the cross-talk between A4:S1 and A5:MULTIPOS. Changing S1 for one extreme
|
||||
// to the other resulted in A5 change of:
|
||||
//
|
||||
// delay value A5 change Time needed for adcRead()
|
||||
// 1 16 0.154ms - 0.156ms
|
||||
// 38 5 0.197ms - 0.199ms
|
||||
// 62 0 0.225ms - 0.243ms
|
||||
delay_01us(40);
|
||||
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
ADC_CS_LOW();
|
||||
delay_01us(1);
|
||||
// command is changed to the next index for the last two readings
|
||||
// (because the sampled data is lagging behind for two command cycles)
|
||||
uint16_t val = (0x0fff & SPIx_ReadWriteByte(adcCommands[(i>1) ? index+1 : index]));
|
||||
#if defined(JITTER_MEASURE)
|
||||
if (JITTER_MEASURE_ACTIVE()) {
|
||||
rawJitter[index].measure(val);
|
||||
}
|
||||
#endif
|
||||
ADC_CS_HIGH();
|
||||
delay_01us(1);
|
||||
result += val;
|
||||
}
|
||||
|
||||
return result >> 2;
|
||||
}
|
||||
|
||||
void adcOnChipReadStart()
|
||||
{
|
||||
ADC_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
|
||||
ADC3->SR &= ~(uint32_t)(ADC_SR_EOC | ADC_SR_STRT | ADC_SR_OVR);
|
||||
ADC_DMA->LIFCR = DMA_LIFCR_CTCIF0 | DMA_LIFCR_CHTIF0 | DMA_LIFCR_CTEIF0 | DMA_LIFCR_CDMEIF0 | DMA_LIFCR_CFEIF0; // Write ones to clear bits
|
||||
ADC_DMA_Stream->M0AR = CONVERT_PTR_UINT(&adcValues[MOUSE1]);
|
||||
ADC_DMA_Stream->NDTR = 2;
|
||||
ADC_DMA_Stream->CR |= DMA_SxCR_EN; // Enable DMA
|
||||
ADC3->CR2 |= (uint32_t)ADC_CR2_SWSTART;
|
||||
}
|
||||
|
||||
bool adcOnChipReadFinished()
|
||||
{
|
||||
return (ADC_DMA->LISR & DMA_LISR_TCIF0);
|
||||
}
|
||||
|
||||
void adcRead()
|
||||
{
|
||||
uint16_t temp[NUM_ANALOGS-MOUSE1] = { 0 };
|
||||
uint8_t noInternalReads = 0;
|
||||
|
||||
adcOnChipReadStart();
|
||||
adcReadSPIDummy();
|
||||
adcReadSPIDummy();
|
||||
for (uint32_t index=0; index<MOUSE1; index++) {
|
||||
adcValues[index] = adcReadNextSPIChannel(index);
|
||||
if (noInternalReads < 4 && adcOnChipReadFinished()) {
|
||||
for (uint8_t x=0; x<NUM_ANALOGS-MOUSE1; x++) {
|
||||
uint16_t val = adcValues[MOUSE1+x];
|
||||
#if defined(JITTER_MEASURE)
|
||||
if (JITTER_MEASURE_ACTIVE()) {
|
||||
rawJitter[MOUSE1+x].measure(val);
|
||||
}
|
||||
#endif
|
||||
temp[x] += val;
|
||||
}
|
||||
if (++noInternalReads < 4) {
|
||||
adcOnChipReadStart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
if (noInternalReads != 4) {
|
||||
TRACE("Internal ADC problem: reads: %d", noInternalReads);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint8_t x=0; x<NUM_ANALOGS-MOUSE1; x++) {
|
||||
adcValues[MOUSE1+x] = temp[x] >> 2;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(SIMU)
|
||||
const int8_t ana_direction[NUM_ANALOGS] = {1,-1,1,-1, -1,1,-1, -1,-1, -1,1, 0,0,0};
|
||||
|
||||
uint16_t getAnalogValue(uint8_t index)
|
||||
{
|
||||
if (ana_direction[index] < 0)
|
||||
return 4095 - adcValues[index];
|
||||
else
|
||||
return adcValues[index];
|
||||
}
|
||||
#endif // #if !defined(SIMU)
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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"
|
||||
|
||||
uint16_t adcValues[NUM_ANALOGS] __DMA;
|
||||
|
||||
#define ADC_CS_HIGH() (ADC_SPI_GPIO->BSRRL = ADC_SPI_PIN_CS)
|
||||
#define ADC_CS_LOW() (ADC_SPI_GPIO->BSRRH = ADC_SPI_PIN_CS)
|
||||
|
||||
#define SPI_STICK1 0
|
||||
#define SPI_STICK2 1
|
||||
#define SPI_STICK3 2
|
||||
#define SPI_STICK4 3
|
||||
#define SPI_S1 4
|
||||
#define SPI_6POS 5
|
||||
#define SPI_S2 6
|
||||
#define SPI_LS 7
|
||||
#define SPI_RS 8
|
||||
#define SPI_TX_VOLTAGE 9
|
||||
#define SPI_L2 10
|
||||
#define SPI_L1 11
|
||||
#define RESETCMD 0x4000
|
||||
#define MANUAL_MODE 0x1000 // manual mode channel 0
|
||||
|
||||
#define SAMPTIME 2 // sample time = 28 cycles
|
||||
|
||||
uint16_t SPIx_ReadWriteByte(uint16_t value)
|
||||
{
|
||||
while (SPI_I2S_GetFlagStatus(ADC_SPI, SPI_I2S_FLAG_TXE) == RESET);
|
||||
SPI_I2S_SendData(ADC_SPI, value);
|
||||
|
||||
while (SPI_I2S_GetFlagStatus(ADC_SPI, SPI_I2S_FLAG_RXNE) == RESET);
|
||||
return SPI_I2S_ReceiveData(ADC_SPI);
|
||||
}
|
||||
|
||||
static void ADS7952_Init()
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
SPI_InitTypeDef SPI_InitStructure;
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = ADC_SPI_PIN_MISO | ADC_SPI_PIN_SCK | ADC_SPI_PIN_MOSI;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(ADC_SPI_GPIO, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = ADC_SPI_PIN_CS;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(ADC_SPI_GPIO, &GPIO_InitStructure);
|
||||
|
||||
GPIO_PinAFConfig(ADC_SPI_GPIO, ADC_SPI_PinSource_SCK, ADC_GPIO_AF);
|
||||
GPIO_PinAFConfig(ADC_SPI_GPIO, ADC_SPI_PinSource_MISO, ADC_GPIO_AF);
|
||||
GPIO_PinAFConfig(ADC_SPI_GPIO, ADC_SPI_PinSource_MOSI, ADC_GPIO_AF);
|
||||
|
||||
SPI_I2S_DeInit(ADC_SPI);
|
||||
|
||||
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
|
||||
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
|
||||
SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
|
||||
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
|
||||
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
|
||||
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
|
||||
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
|
||||
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
|
||||
SPI_InitStructure.SPI_CRCPolynomial = 7;
|
||||
SPI_Init(ADC_SPI, &SPI_InitStructure);
|
||||
SPI_Cmd(ADC_SPI, ENABLE);
|
||||
SPI_I2S_ITConfig(ADC_SPI, SPI_I2S_IT_TXE, DISABLE);
|
||||
SPI_I2S_ITConfig(ADC_SPI, SPI_I2S_IT_RXNE, DISABLE);
|
||||
|
||||
ADC_CS_HIGH();
|
||||
delay_01us(1);
|
||||
ADC_CS_LOW();
|
||||
SPIx_ReadWriteByte(RESETCMD);
|
||||
ADC_CS_HIGH();
|
||||
delay_01us(1);
|
||||
ADC_CS_LOW();
|
||||
SPIx_ReadWriteByte(MANUAL_MODE);
|
||||
ADC_CS_HIGH();
|
||||
}
|
||||
|
||||
void adcInit()
|
||||
{
|
||||
ADS7952_Init();
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = ADC_GPIO_PIN_MOUSE1 | ADC_GPIO_PIN_MOUSE2;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(ADC_GPIO_MOUSE, &GPIO_InitStructure);
|
||||
|
||||
ADC3->CR1 = ADC_CR1_SCAN;
|
||||
ADC3->CR2 = ADC_CR2_ADON | ADC_CR2_DMA | ADC_CR2_DDS;
|
||||
ADC3->SQR1 = (2-1) << 20;
|
||||
ADC3->SQR2 = 0;
|
||||
ADC3->SQR3 = ADC_IN_MOUSE1 + (ADC_IN_MOUSE2<<5);
|
||||
ADC3->SMPR1 = 0;
|
||||
ADC3->SMPR2 = (ADC_SAMPTIME<<(3*ADC_IN_MOUSE1)) + (ADC_SAMPTIME<<(3*ADC_IN_MOUSE2));
|
||||
ADC->CCR = 0;
|
||||
|
||||
// Enable the DMA channel here, DMA2 stream 1, channel 2
|
||||
ADC_DMA_Stream->CR = DMA_SxCR_PL | DMA_SxCR_CHSEL_1 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC;
|
||||
ADC_DMA_Stream->PAR = CONVERT_PTR_UINT(&ADC3->DR);
|
||||
ADC_DMA_Stream->M0AR = CONVERT_PTR_UINT(&adcValues[MOUSE1]);
|
||||
ADC_DMA_Stream->NDTR = 2;
|
||||
ADC_DMA_Stream->FCR = DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0;
|
||||
}
|
||||
|
||||
const uint16_t adcCommands[MOUSE1+2] =
|
||||
{
|
||||
MANUAL_MODE | (SPI_STICK1 << 7),
|
||||
MANUAL_MODE | (SPI_STICK2 << 7),
|
||||
MANUAL_MODE | (SPI_STICK3 << 7),
|
||||
MANUAL_MODE | (SPI_STICK4 << 7),
|
||||
MANUAL_MODE | (SPI_S1 << 7),
|
||||
MANUAL_MODE | (SPI_6POS << 7),
|
||||
MANUAL_MODE | (SPI_S2 << 7),
|
||||
MANUAL_MODE | (SPI_L1 << 7),
|
||||
MANUAL_MODE | (SPI_L2 << 7),
|
||||
MANUAL_MODE | (SPI_LS << 7),
|
||||
MANUAL_MODE | (SPI_RS << 7),
|
||||
MANUAL_MODE | (SPI_TX_VOLTAGE << 7),
|
||||
MANUAL_MODE | (0 << 7), // small joystick left/right
|
||||
MANUAL_MODE | (0 << 7) // small joystick up/down
|
||||
};
|
||||
|
||||
void adcReadSPIDummy()
|
||||
{
|
||||
// A dummy command to get things started
|
||||
// (because the sampled data is lagging behind for two command cycles)
|
||||
ADC_CS_LOW();
|
||||
delay_01us(1);
|
||||
SPIx_ReadWriteByte(adcCommands[0]);
|
||||
ADC_CS_HIGH();
|
||||
delay_01us(1);
|
||||
}
|
||||
|
||||
uint32_t adcReadNextSPIChannel(uint8_t index)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
|
||||
// This delay is to allow charging of ADC input capacitor
|
||||
// after the MUX changes from one channel to the other.
|
||||
// It was determined experimentally. Biggest problem seems to be
|
||||
// the cross-talk between A4:S1 and A5:MULTIPOS. Changing S1 for one extreme
|
||||
// to the other resulted in A5 change of:
|
||||
//
|
||||
// delay value A5 change Time needed for adcRead()
|
||||
// 1 16 0.154ms - 0.156ms
|
||||
// 38 5 0.197ms - 0.199ms
|
||||
// 62 0 0.225ms - 0.243ms
|
||||
delay_01us(40);
|
||||
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
ADC_CS_LOW();
|
||||
delay_01us(1);
|
||||
// command is changed to the next index for the last two readings
|
||||
// (because the sampled data is lagging behind for two command cycles)
|
||||
uint16_t val = (0x0fff & SPIx_ReadWriteByte(adcCommands[(i>1) ? index+1 : index]));
|
||||
#if defined(JITTER_MEASURE)
|
||||
if (JITTER_MEASURE_ACTIVE()) {
|
||||
rawJitter[index].measure(val);
|
||||
}
|
||||
#endif
|
||||
ADC_CS_HIGH();
|
||||
delay_01us(1);
|
||||
result += val;
|
||||
}
|
||||
|
||||
return result >> 2;
|
||||
}
|
||||
|
||||
void adcOnChipReadStart()
|
||||
{
|
||||
ADC_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
|
||||
ADC3->SR &= ~(uint32_t)(ADC_SR_EOC | ADC_SR_STRT | ADC_SR_OVR);
|
||||
ADC_DMA->LIFCR = DMA_LIFCR_CTCIF0 | DMA_LIFCR_CHTIF0 | DMA_LIFCR_CTEIF0 | DMA_LIFCR_CDMEIF0 | DMA_LIFCR_CFEIF0; // Write ones to clear bits
|
||||
ADC_DMA_Stream->M0AR = CONVERT_PTR_UINT(&adcValues[MOUSE1]);
|
||||
ADC_DMA_Stream->NDTR = 2;
|
||||
ADC_DMA_Stream->CR |= DMA_SxCR_EN; // Enable DMA
|
||||
ADC3->CR2 |= (uint32_t)ADC_CR2_SWSTART;
|
||||
}
|
||||
|
||||
bool adcOnChipReadFinished()
|
||||
{
|
||||
return (ADC_DMA->LISR & DMA_LISR_TCIF0);
|
||||
}
|
||||
|
||||
void adcRead()
|
||||
{
|
||||
uint16_t temp[NUM_ANALOGS-MOUSE1] = { 0 };
|
||||
uint8_t noInternalReads = 0;
|
||||
|
||||
adcOnChipReadStart();
|
||||
adcReadSPIDummy();
|
||||
adcReadSPIDummy();
|
||||
for (uint32_t index=0; index<MOUSE1; index++) {
|
||||
adcValues[index] = adcReadNextSPIChannel(index);
|
||||
if (noInternalReads < 4 && adcOnChipReadFinished()) {
|
||||
for (uint8_t x=0; x<NUM_ANALOGS-MOUSE1; x++) {
|
||||
uint16_t val = adcValues[MOUSE1+x];
|
||||
#if defined(JITTER_MEASURE)
|
||||
if (JITTER_MEASURE_ACTIVE()) {
|
||||
rawJitter[MOUSE1+x].measure(val);
|
||||
}
|
||||
#endif
|
||||
temp[x] += val;
|
||||
}
|
||||
if (++noInternalReads < 4) {
|
||||
adcOnChipReadStart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
if (noInternalReads != 4) {
|
||||
TRACE("Internal ADC problem: reads: %d", noInternalReads);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint8_t x=0; x<NUM_ANALOGS-MOUSE1; x++) {
|
||||
adcValues[MOUSE1+x] = temp[x] >> 2;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(SIMU)
|
||||
const int8_t ana_direction[NUM_ANALOGS] = {1,-1,1,-1, -1,1,-1, -1,-1, -1,1, 0,0,0};
|
||||
|
||||
uint16_t getAnalogValue(uint8_t index)
|
||||
{
|
||||
if (ana_direction[index] < 0)
|
||||
return 4095 - adcValues[index];
|
||||
else
|
||||
return adcValues[index];
|
||||
}
|
||||
#endif // #if !defined(SIMU)
|
||||
|
||||
@@ -1,261 +1,261 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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"
|
||||
|
||||
Fifo<uint8_t, 64> btTxFifo;
|
||||
Fifo<uint8_t, 64> btRxFifo;
|
||||
|
||||
enum BluetoothState
|
||||
{
|
||||
BLUETOOTH_INIT,
|
||||
BLUETOOTH_WAIT_TTM,
|
||||
BLUETOOTH_WAIT_BAUDRATE_CHANGE,
|
||||
BLUETOOTH_OK,
|
||||
};
|
||||
|
||||
enum BluetoothWriteState
|
||||
{
|
||||
BLUETOOTH_WRITE_IDLE,
|
||||
BLUETOOTH_WRITE_INIT,
|
||||
BLUETOOTH_WRITING,
|
||||
BLUETOOTH_WRITE_DONE
|
||||
};
|
||||
|
||||
volatile uint8_t bluetoothState = BLUETOOTH_INIT;
|
||||
volatile uint8_t bluetoothWriteState = BLUETOOTH_WRITE_IDLE;
|
||||
|
||||
void bluetoothInit(uint32_t baudrate)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
USART_InitTypeDef USART_InitStructure;
|
||||
|
||||
USART_DeInit(BT_USART);
|
||||
|
||||
RCC_AHB1PeriphClockCmd(BT_RCC_AHB1Periph, ENABLE);
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = BT_EN_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(BT_EN_GPIO, &GPIO_InitStructure);
|
||||
|
||||
#if defined(BT_BRTS_GPIO_PIN)
|
||||
GPIO_InitStructure.GPIO_Pin = BT_BRTS_GPIO_PIN;
|
||||
GPIO_Init(BT_BRTS_GPIO, &GPIO_InitStructure);
|
||||
GPIO_SetBits(BT_BRTS_GPIO, BT_BRTS_GPIO_PIN);
|
||||
#endif
|
||||
|
||||
#if defined(BT_BCTS_GPIO_PIN)
|
||||
GPIO_InitStructure.GPIO_Pin = BT_BCTS_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
|
||||
GPIO_Init(BT_BCTS_GPIO, &GPIO_InitStructure);
|
||||
#endif
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = BT_TX_GPIO_PIN|BT_RX_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_Init(BT_GPIO_TXRX, &GPIO_InitStructure);
|
||||
|
||||
GPIO_PinAFConfig(BT_GPIO_TXRX, BT_TX_GPIO_PinSource, BT_GPIO_AF);
|
||||
GPIO_PinAFConfig(BT_GPIO_TXRX, BT_RX_GPIO_PinSource, BT_GPIO_AF);
|
||||
|
||||
USART_DeInit(BT_USART);
|
||||
USART_InitStructure.USART_BaudRate = baudrate;
|
||||
USART_InitStructure.USART_Parity = USART_Parity_No;
|
||||
USART_InitStructure.USART_StopBits = USART_StopBits_1;
|
||||
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
||||
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
||||
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
|
||||
USART_Init(BT_USART, &USART_InitStructure);
|
||||
|
||||
USART_Cmd(BT_USART, ENABLE);
|
||||
USART_ITConfig(BT_USART, USART_IT_RXNE, ENABLE);
|
||||
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
NVIC_InitStructure.NVIC_IRQChannel = BT_USART_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 8;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
GPIO_ResetBits(BT_EN_GPIO, BT_EN_GPIO_PIN); // open bluetooth
|
||||
}
|
||||
|
||||
void bluetoothDone()
|
||||
{
|
||||
GPIO_SetBits(BT_EN_GPIO, BT_EN_GPIO_PIN); // close bluetooth
|
||||
}
|
||||
|
||||
extern "C" void USART6_IRQHandler(void)
|
||||
{
|
||||
DEBUG_INTERRUPT(INT_BLUETOOTH);
|
||||
if (USART_GetITStatus(BT_USART, USART_IT_RXNE) != RESET) {
|
||||
USART_ClearITPendingBit(BT_USART, USART_IT_RXNE);
|
||||
uint8_t byte = USART_ReceiveData(BT_USART);
|
||||
btRxFifo.push(byte);
|
||||
}
|
||||
|
||||
if (USART_GetITStatus(BT_USART, USART_IT_TXE) != RESET) {
|
||||
uint8_t byte;
|
||||
bool result = btTxFifo.pop(byte);
|
||||
if (result) {
|
||||
USART_SendData(BT_USART, byte);
|
||||
}
|
||||
else {
|
||||
USART_ITConfig(BT_USART, USART_IT_TXE, DISABLE);
|
||||
bluetoothWriteState = BLUETOOTH_WRITE_DONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bluetoothWrite(const void * buffer, int len)
|
||||
{
|
||||
uint8_t * data = (uint8_t *)buffer;
|
||||
for (int i=0; i<len; ++i) {
|
||||
btTxFifo.push(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void bluetoothWriteString(const char * str)
|
||||
{
|
||||
while (*str != 0) {
|
||||
btTxFifo.push(*str++);
|
||||
}
|
||||
}
|
||||
|
||||
void bluetoothWriteWakeup(void)
|
||||
{
|
||||
if (bluetoothWriteState == BLUETOOTH_WRITE_IDLE) {
|
||||
if (!btTxFifo.isEmpty()) {
|
||||
bluetoothWriteState = BLUETOOTH_WRITE_INIT;
|
||||
#if defined(BT_BRTS_GPIO_PIN)
|
||||
GPIO_ResetBits(BT_BRTS_GPIO, BT_BRTS_GPIO_PIN);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (bluetoothWriteState == BLUETOOTH_WRITE_INIT) {
|
||||
bluetoothWriteState = BLUETOOTH_WRITING;
|
||||
USART_ITConfig(BT_USART, USART_IT_TXE, ENABLE);
|
||||
}
|
||||
else if (bluetoothWriteState == BLUETOOTH_WRITE_DONE) {
|
||||
bluetoothWriteState = BLUETOOTH_WRITE_IDLE;
|
||||
#if defined(BT_BRTS_GPIO_PIN)
|
||||
GPIO_SetBits(BT_BRTS_GPIO, BT_BRTS_GPIO_PIN);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void bluetoothWakeup(void)
|
||||
{
|
||||
#if defined(BLUETOOTH_CLI_PASSTHROUGH)
|
||||
bluetoothWriteWakeup();
|
||||
return;
|
||||
|
||||
#else // #if defined(BLUETOOTH_CLI_PASSTHROUGH)
|
||||
|
||||
// NOTICE: code below doesn't work on Horus beta!
|
||||
if (!g_eeGeneral.bluetoothEnable) {
|
||||
if (bluetoothState != BLUETOOTH_INIT) {
|
||||
bluetoothDone();
|
||||
bluetoothState = BLUETOOTH_INIT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (bluetoothState != BLUETOOTH_OK) {
|
||||
static tmr10ms_t waitEnd = 0;
|
||||
|
||||
if (bluetoothState == BLUETOOTH_INIT) {
|
||||
TRACE("BLUETOOTH_INIT");
|
||||
bluetoothInit(BLUETOOTH_DEFAULT_BAUDRATE);
|
||||
const char btMessage[] = "TTM:REN-";
|
||||
bluetoothWriteString(btMessage);
|
||||
uint8_t len = ZLEN(g_eeGeneral.bluetoothName);
|
||||
for (int i=0; i<len; i++) {
|
||||
btTxFifo.push(idx2char(g_eeGeneral.bluetoothName[i]));
|
||||
}
|
||||
bluetoothState = BLUETOOTH_WAIT_TTM;
|
||||
waitEnd = get_tmr10ms() + 25; // 250ms
|
||||
}
|
||||
else if (bluetoothState == BLUETOOTH_WAIT_TTM) {
|
||||
if (get_tmr10ms() > waitEnd) {
|
||||
TRACE("bt rename");
|
||||
char ttm[] = "TTM:REN";
|
||||
int index = 0;
|
||||
uint8_t c;
|
||||
bool found = false;
|
||||
while (btRxFifo.pop(c)) {
|
||||
if (c == ttm[index]) {
|
||||
index++;
|
||||
if (index == sizeof(ttm)-1) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
TRACE("bt OK");
|
||||
bluetoothState = BLUETOOTH_OK;
|
||||
}
|
||||
else {
|
||||
TRACE("bt failure");
|
||||
bluetoothInit(BLUETOOTH_FACTORY_BAUDRATE);
|
||||
const char btMessage[] = "TTM:BPS-115200";
|
||||
bluetoothWriteString(btMessage);
|
||||
bluetoothState = BLUETOOTH_WAIT_BAUDRATE_CHANGE;
|
||||
waitEnd = get_tmr10ms() + 250; // 2.5s
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bluetoothState == BLUETOOTH_WAIT_BAUDRATE_CHANGE) {
|
||||
if (get_tmr10ms() > waitEnd) {
|
||||
bluetoothState = BLUETOOTH_INIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bluetoothWriteWakeup();
|
||||
}
|
||||
#endif // #if defined(BLUETOOTH_CLI_PASSTHROUGH)
|
||||
}
|
||||
|
||||
uint8_t bluetoothReady()
|
||||
{
|
||||
return (bluetoothState == BLUETOOTH_OK);
|
||||
}
|
||||
|
||||
int bluetoothRead(void * buffer, int len)
|
||||
{
|
||||
int result = 0;
|
||||
uint8_t * data = (uint8_t *)buffer;
|
||||
while (result < len) {
|
||||
uint8_t byte;
|
||||
if (!btRxFifo.pop(byte)) {
|
||||
break;
|
||||
}
|
||||
data[result++] = byte;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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"
|
||||
|
||||
Fifo<uint8_t, 64> btTxFifo;
|
||||
Fifo<uint8_t, 64> btRxFifo;
|
||||
|
||||
enum BluetoothState
|
||||
{
|
||||
BLUETOOTH_INIT,
|
||||
BLUETOOTH_WAIT_TTM,
|
||||
BLUETOOTH_WAIT_BAUDRATE_CHANGE,
|
||||
BLUETOOTH_OK,
|
||||
};
|
||||
|
||||
enum BluetoothWriteState
|
||||
{
|
||||
BLUETOOTH_WRITE_IDLE,
|
||||
BLUETOOTH_WRITE_INIT,
|
||||
BLUETOOTH_WRITING,
|
||||
BLUETOOTH_WRITE_DONE
|
||||
};
|
||||
|
||||
volatile uint8_t bluetoothState = BLUETOOTH_INIT;
|
||||
volatile uint8_t bluetoothWriteState = BLUETOOTH_WRITE_IDLE;
|
||||
|
||||
void bluetoothInit(uint32_t baudrate)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
USART_InitTypeDef USART_InitStructure;
|
||||
|
||||
USART_DeInit(BT_USART);
|
||||
|
||||
RCC_AHB1PeriphClockCmd(BT_RCC_AHB1Periph, ENABLE);
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = BT_EN_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(BT_EN_GPIO, &GPIO_InitStructure);
|
||||
|
||||
#if defined(BT_BRTS_GPIO_PIN)
|
||||
GPIO_InitStructure.GPIO_Pin = BT_BRTS_GPIO_PIN;
|
||||
GPIO_Init(BT_BRTS_GPIO, &GPIO_InitStructure);
|
||||
GPIO_SetBits(BT_BRTS_GPIO, BT_BRTS_GPIO_PIN);
|
||||
#endif
|
||||
|
||||
#if defined(BT_BCTS_GPIO_PIN)
|
||||
GPIO_InitStructure.GPIO_Pin = BT_BCTS_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
|
||||
GPIO_Init(BT_BCTS_GPIO, &GPIO_InitStructure);
|
||||
#endif
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = BT_TX_GPIO_PIN|BT_RX_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_Init(BT_GPIO_TXRX, &GPIO_InitStructure);
|
||||
|
||||
GPIO_PinAFConfig(BT_GPIO_TXRX, BT_TX_GPIO_PinSource, BT_GPIO_AF);
|
||||
GPIO_PinAFConfig(BT_GPIO_TXRX, BT_RX_GPIO_PinSource, BT_GPIO_AF);
|
||||
|
||||
USART_DeInit(BT_USART);
|
||||
USART_InitStructure.USART_BaudRate = baudrate;
|
||||
USART_InitStructure.USART_Parity = USART_Parity_No;
|
||||
USART_InitStructure.USART_StopBits = USART_StopBits_1;
|
||||
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
||||
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
||||
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
|
||||
USART_Init(BT_USART, &USART_InitStructure);
|
||||
|
||||
USART_Cmd(BT_USART, ENABLE);
|
||||
USART_ITConfig(BT_USART, USART_IT_RXNE, ENABLE);
|
||||
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
NVIC_InitStructure.NVIC_IRQChannel = BT_USART_IRQn;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 8;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
GPIO_ResetBits(BT_EN_GPIO, BT_EN_GPIO_PIN); // open bluetooth
|
||||
}
|
||||
|
||||
void bluetoothDone()
|
||||
{
|
||||
GPIO_SetBits(BT_EN_GPIO, BT_EN_GPIO_PIN); // close bluetooth
|
||||
}
|
||||
|
||||
extern "C" void USART6_IRQHandler(void)
|
||||
{
|
||||
DEBUG_INTERRUPT(INT_BLUETOOTH);
|
||||
if (USART_GetITStatus(BT_USART, USART_IT_RXNE) != RESET) {
|
||||
USART_ClearITPendingBit(BT_USART, USART_IT_RXNE);
|
||||
uint8_t byte = USART_ReceiveData(BT_USART);
|
||||
btRxFifo.push(byte);
|
||||
}
|
||||
|
||||
if (USART_GetITStatus(BT_USART, USART_IT_TXE) != RESET) {
|
||||
uint8_t byte;
|
||||
bool result = btTxFifo.pop(byte);
|
||||
if (result) {
|
||||
USART_SendData(BT_USART, byte);
|
||||
}
|
||||
else {
|
||||
USART_ITConfig(BT_USART, USART_IT_TXE, DISABLE);
|
||||
bluetoothWriteState = BLUETOOTH_WRITE_DONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bluetoothWrite(const void * buffer, int len)
|
||||
{
|
||||
uint8_t * data = (uint8_t *)buffer;
|
||||
for (int i=0; i<len; ++i) {
|
||||
btTxFifo.push(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void bluetoothWriteString(const char * str)
|
||||
{
|
||||
while (*str != 0) {
|
||||
btTxFifo.push(*str++);
|
||||
}
|
||||
}
|
||||
|
||||
void bluetoothWriteWakeup(void)
|
||||
{
|
||||
if (bluetoothWriteState == BLUETOOTH_WRITE_IDLE) {
|
||||
if (!btTxFifo.isEmpty()) {
|
||||
bluetoothWriteState = BLUETOOTH_WRITE_INIT;
|
||||
#if defined(BT_BRTS_GPIO_PIN)
|
||||
GPIO_ResetBits(BT_BRTS_GPIO, BT_BRTS_GPIO_PIN);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (bluetoothWriteState == BLUETOOTH_WRITE_INIT) {
|
||||
bluetoothWriteState = BLUETOOTH_WRITING;
|
||||
USART_ITConfig(BT_USART, USART_IT_TXE, ENABLE);
|
||||
}
|
||||
else if (bluetoothWriteState == BLUETOOTH_WRITE_DONE) {
|
||||
bluetoothWriteState = BLUETOOTH_WRITE_IDLE;
|
||||
#if defined(BT_BRTS_GPIO_PIN)
|
||||
GPIO_SetBits(BT_BRTS_GPIO, BT_BRTS_GPIO_PIN);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void bluetoothWakeup(void)
|
||||
{
|
||||
#if defined(BLUETOOTH_CLI_PASSTHROUGH)
|
||||
bluetoothWriteWakeup();
|
||||
return;
|
||||
|
||||
#else // #if defined(BLUETOOTH_CLI_PASSTHROUGH)
|
||||
|
||||
// NOTICE: code below doesn't work on Horus beta!
|
||||
if (!g_eeGeneral.bluetoothEnable) {
|
||||
if (bluetoothState != BLUETOOTH_INIT) {
|
||||
bluetoothDone();
|
||||
bluetoothState = BLUETOOTH_INIT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (bluetoothState != BLUETOOTH_OK) {
|
||||
static tmr10ms_t waitEnd = 0;
|
||||
|
||||
if (bluetoothState == BLUETOOTH_INIT) {
|
||||
TRACE("BLUETOOTH_INIT");
|
||||
bluetoothInit(BLUETOOTH_DEFAULT_BAUDRATE);
|
||||
const char btMessage[] = "TTM:REN-";
|
||||
bluetoothWriteString(btMessage);
|
||||
uint8_t len = ZLEN(g_eeGeneral.bluetoothName);
|
||||
for (int i=0; i<len; i++) {
|
||||
btTxFifo.push(idx2char(g_eeGeneral.bluetoothName[i]));
|
||||
}
|
||||
bluetoothState = BLUETOOTH_WAIT_TTM;
|
||||
waitEnd = get_tmr10ms() + 25; // 250ms
|
||||
}
|
||||
else if (bluetoothState == BLUETOOTH_WAIT_TTM) {
|
||||
if (get_tmr10ms() > waitEnd) {
|
||||
TRACE("bt rename");
|
||||
char ttm[] = "TTM:REN";
|
||||
int index = 0;
|
||||
uint8_t c;
|
||||
bool found = false;
|
||||
while (btRxFifo.pop(c)) {
|
||||
if (c == ttm[index]) {
|
||||
index++;
|
||||
if (index == sizeof(ttm)-1) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
TRACE("bt OK");
|
||||
bluetoothState = BLUETOOTH_OK;
|
||||
}
|
||||
else {
|
||||
TRACE("bt failure");
|
||||
bluetoothInit(BLUETOOTH_FACTORY_BAUDRATE);
|
||||
const char btMessage[] = "TTM:BPS-115200";
|
||||
bluetoothWriteString(btMessage);
|
||||
bluetoothState = BLUETOOTH_WAIT_BAUDRATE_CHANGE;
|
||||
waitEnd = get_tmr10ms() + 250; // 2.5s
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bluetoothState == BLUETOOTH_WAIT_BAUDRATE_CHANGE) {
|
||||
if (get_tmr10ms() > waitEnd) {
|
||||
bluetoothState = BLUETOOTH_INIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bluetoothWriteWakeup();
|
||||
}
|
||||
#endif // #if defined(BLUETOOTH_CLI_PASSTHROUGH)
|
||||
}
|
||||
|
||||
uint8_t bluetoothReady()
|
||||
{
|
||||
return (bluetoothState == BLUETOOTH_OK);
|
||||
}
|
||||
|
||||
int bluetoothRead(void * buffer, int len)
|
||||
{
|
||||
int result = 0;
|
||||
uint8_t * data = (uint8_t *)buffer;
|
||||
while (result < len) {
|
||||
uint8_t byte;
|
||||
if (!btRxFifo.pop(byte)) {
|
||||
break;
|
||||
}
|
||||
data[result++] = byte;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+376
-376
@@ -1,376 +1,376 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* This is a stub disk I/O module that acts as front end of the existing */
|
||||
/* disk I/O modules and attach it to FatFs module with common interface. */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
#include "diskio.h"
|
||||
#include <string.h>
|
||||
#include "opentx.h"
|
||||
#include "sdio_sd.h"
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Lock / unlock functions */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
#if !defined(BOOT)
|
||||
static OS_MutexID ioMutex;
|
||||
uint32_t ioMutexReq = 0, ioMutexRel = 0;
|
||||
int ff_cre_syncobj (BYTE vol, _SYNC_t *mutex)
|
||||
{
|
||||
*mutex = ioMutex;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ff_req_grant (_SYNC_t mutex)
|
||||
{
|
||||
ioMutexReq += 1;
|
||||
return CoEnterMutexSection(mutex) == E_OK;
|
||||
}
|
||||
|
||||
void ff_rel_grant (_SYNC_t mutex)
|
||||
{
|
||||
ioMutexRel += 1;
|
||||
CoLeaveMutexSection(mutex);
|
||||
}
|
||||
|
||||
int ff_del_syncobj (_SYNC_t mutex)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Inidialize a Drive */
|
||||
|
||||
DSTATUS disk_initialize (
|
||||
BYTE drv /* Physical drive nmuber (0..) */
|
||||
)
|
||||
{
|
||||
DSTATUS stat = 0;
|
||||
|
||||
/* Supports only single drive */
|
||||
if (drv)
|
||||
{
|
||||
stat |= STA_NOINIT;
|
||||
}
|
||||
|
||||
/*-------------------------- SD Init ----------------------------- */
|
||||
SD_Error res = SD_Init();
|
||||
if (res != SD_OK)
|
||||
{
|
||||
TRACE("SD_Init() failed: %d", res);
|
||||
stat |= STA_NOINIT;
|
||||
}
|
||||
|
||||
TRACE("SD card info:");
|
||||
TRACE("sectors: %u", (uint32_t)(SDCardInfo.CardCapacity / 512));
|
||||
TRACE("type: %u", (uint32_t)(SDCardInfo.CardType));
|
||||
TRACE("EraseGrSize: %u", (uint32_t)(SDCardInfo.SD_csd.EraseGrSize));
|
||||
TRACE("EraseGrMul: %u", (uint32_t)(SDCardInfo.SD_csd.EraseGrMul));
|
||||
TRACE("ManufacturerID: %u", (uint32_t)(SDCardInfo.SD_cid.ManufacturerID));
|
||||
|
||||
return(stat);
|
||||
}
|
||||
|
||||
DWORD scratch[BLOCK_SIZE / 4] __DMA;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Return Disk Status */
|
||||
|
||||
DSTATUS disk_status (
|
||||
BYTE drv /* Physical drive nmuber (0..) */
|
||||
)
|
||||
{
|
||||
DSTATUS stat = 0;
|
||||
|
||||
if (SD_Detect() != SD_PRESENT)
|
||||
stat |= STA_NODISK;
|
||||
|
||||
// STA_NOTINIT - Subsystem not initailized
|
||||
// STA_PROTECTED - Write protected, MMC/SD switch if available
|
||||
|
||||
return(stat);
|
||||
}
|
||||
|
||||
uint32_t sdReadRetries = 0;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Read Sector(s) */
|
||||
|
||||
|
||||
DRESULT disk_read_dma(BYTE drv, BYTE * buff, DWORD sector, UINT count)
|
||||
{
|
||||
// this functions assumes that buff is properly aligned and in the right RAM segment for DMA
|
||||
DRESULT res;
|
||||
SD_Error Status;
|
||||
SDTransferState State;
|
||||
for (int retry=0; retry<3; retry++) {
|
||||
res = RES_OK;
|
||||
if (count == 1) {
|
||||
Status = SD_ReadBlock(buff, sector, BLOCK_SIZE); // 4GB Compliant
|
||||
}
|
||||
else {
|
||||
Status = SD_ReadMultiBlocks(buff, sector, BLOCK_SIZE, count); // 4GB Compliant
|
||||
}
|
||||
if (Status == SD_OK) {
|
||||
Status = SD_WaitReadOperation(200*count); // Check if the Transfer is finished
|
||||
while ((State = SD_GetStatus()) == SD_TRANSFER_BUSY); // BUSY, OK (DONE), ERROR (FAIL)
|
||||
if (State == SD_TRANSFER_ERROR) {
|
||||
TRACE("State=SD_TRANSFER_ERROR, c: %u", sector, (uint32_t)count);
|
||||
res = RES_ERROR;
|
||||
}
|
||||
else if (Status != SD_OK) {
|
||||
TRACE("Status(WaitRead)=%d, s:%u c: %u", Status, sector, (uint32_t)count);
|
||||
res = RES_ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
TRACE("Status(ReadBlock)=%d, s:%u c: %u", Status, sector, (uint32_t)count);
|
||||
res = RES_ERROR;
|
||||
}
|
||||
if (res == RES_OK) break;
|
||||
sdReadRetries += 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
DRESULT __disk_read(BYTE drv, BYTE * buff, DWORD sector, UINT count)
|
||||
{
|
||||
// If unaligned, do the single block reads with a scratch buffer.
|
||||
// If aligned and single sector, do a single block read.
|
||||
// If aligned and multiple sectors, try multi block read.
|
||||
// If multi block read fails, try single block reads without
|
||||
// an intermediate buffer (move trough the provided buffer)
|
||||
|
||||
// TRACE("disk_read %d %p %10d %d", drv, buff, sector, count);
|
||||
if (SD_Detect() != SD_PRESENT) {
|
||||
TRACE("SD_Detect() != SD_PRESENT");
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
|
||||
DRESULT res = RES_OK;
|
||||
if (count == 0) return res;
|
||||
|
||||
if ((DWORD)buff < 0x20000000 || ((DWORD)buff & 3)) {
|
||||
// buffer is not aligned, use scratch buffer that is aligned
|
||||
TRACE("disk_read bad alignment (%p)", buff);
|
||||
while (count--) {
|
||||
res = disk_read_dma(drv, (BYTE *)scratch, sector++, 1);
|
||||
if (res != RES_OK) break;
|
||||
memcpy(buff, scratch, BLOCK_SIZE);
|
||||
buff += BLOCK_SIZE;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
res = disk_read_dma(drv, buff, sector, count);
|
||||
if (res != RES_OK && count > 1) {
|
||||
// multi-read failed, try reading same sectors, one by one
|
||||
TRACE("disk_read() multi-block failed, trying single block reads...");
|
||||
while (count--) {
|
||||
res = disk_read_dma(drv, buff, sector++, 1);
|
||||
if (res != RES_OK) break;
|
||||
buff += BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Write Sector(s) */
|
||||
|
||||
#if _READONLY == 0
|
||||
DRESULT __disk_write(
|
||||
BYTE drv, /* Physical drive nmuber (0..) */
|
||||
const BYTE *buff, /* Data to be written */
|
||||
DWORD sector, /* Sector address (LBA) */
|
||||
UINT count /* Number of sectors to write (1..255) */
|
||||
)
|
||||
{
|
||||
SD_Error Status;
|
||||
DRESULT res = RES_OK;
|
||||
|
||||
// TRACE("disk_write %d %p %10d %d", drv, buff, sector, count);
|
||||
|
||||
if (SD_Detect() != SD_PRESENT)
|
||||
return(RES_NOTRDY);
|
||||
|
||||
if ((DWORD)buff < 0x20000000 || ((DWORD)buff & 3)) {
|
||||
TRACE("disk_write bad alignment (%p)", buff);
|
||||
while(count--) {
|
||||
memcpy(scratch, buff, BLOCK_SIZE);
|
||||
|
||||
res = __disk_write(drv, (BYTE *)scratch, sector++, 1);
|
||||
|
||||
if (res != RES_OK)
|
||||
break;
|
||||
|
||||
buff += BLOCK_SIZE;
|
||||
}
|
||||
return(res);
|
||||
}
|
||||
|
||||
if (count == 1) {
|
||||
Status = SD_WriteBlock((uint8_t *)buff, sector, BLOCK_SIZE); // 4GB Compliant
|
||||
}
|
||||
else {
|
||||
Status = SD_WriteMultiBlocks((uint8_t *)buff, sector, BLOCK_SIZE, count); // 4GB Compliant
|
||||
}
|
||||
|
||||
if (Status == SD_OK) {
|
||||
SDTransferState State;
|
||||
|
||||
Status = SD_WaitWriteOperation(500*count); // Check if the Transfer is finished
|
||||
|
||||
while((State = SD_GetStatus()) == SD_TRANSFER_BUSY); // BUSY, OK (DONE), ERROR (FAIL)
|
||||
|
||||
if ((State == SD_TRANSFER_ERROR) || (Status != SD_OK)) {
|
||||
TRACE("__disk_write() err, st:%d,%d, s:%u c: %u", Status, State, sector, (uint32_t)count);
|
||||
res = RES_ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
res = RES_ERROR;
|
||||
}
|
||||
|
||||
// TRACE("result=%d", res);
|
||||
return res;
|
||||
}
|
||||
#endif /* _READONLY */
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* 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;
|
||||
|
||||
if (drv) return RES_PARERR;
|
||||
|
||||
res = RES_ERROR;
|
||||
|
||||
switch (ctrl) {
|
||||
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
|
||||
// use 512 for sector size, SDCardInfo.CardBlockSize is not sector size and can be 1024 for 2G SD cards!!!!
|
||||
*(DWORD*)buff = SDCardInfo.CardCapacity / BLOCK_SIZE;
|
||||
res = RES_OK;
|
||||
break;
|
||||
|
||||
case GET_SECTOR_SIZE : /* Get R/W sector size (WORD) */
|
||||
*(WORD*)buff = BLOCK_SIZE; // force sector size. SDCardInfo.CardBlockSize is not sector size and can be 1024 for 2G SD cards!!!!
|
||||
res = RES_OK;
|
||||
break;
|
||||
|
||||
case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */
|
||||
// TODO verify that this is the correct value
|
||||
*(DWORD*)buff = (uint32_t)SDCardInfo.SD_csd.EraseGrSize * (uint32_t)SDCardInfo.SD_csd.EraseGrMul;
|
||||
res = RES_OK;
|
||||
break;
|
||||
|
||||
case CTRL_SYNC:
|
||||
while (SD_GetStatus() == SD_TRANSFER_BUSY); /* Complete pending write process (needed at _FS_READONLY == 0) */
|
||||
res = RES_OK;
|
||||
break;
|
||||
|
||||
default:
|
||||
res = RES_OK;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// TODO everything here should not be in the driver layer ...
|
||||
|
||||
FATFS g_FATFS_Obj __DMA; // initialized in boardInit()
|
||||
#if defined(LOG_TELEMETRY)
|
||||
FIL g_telemetryFile = {};
|
||||
#endif
|
||||
|
||||
void sdInit()
|
||||
{
|
||||
TRACE("sdInit");
|
||||
|
||||
ioMutex = CoCreateMutex();
|
||||
if (ioMutex >= CFG_MAX_MUTEX) {
|
||||
// sd error
|
||||
return;
|
||||
}
|
||||
sdMount();
|
||||
}
|
||||
|
||||
void sdMount()
|
||||
{
|
||||
TRACE("sdMount");
|
||||
|
||||
diskCache.clear();
|
||||
|
||||
if (f_mount(&g_FATFS_Obj, "", 1) == FR_OK) {
|
||||
// call sdGetFreeSectors() now because f_getfree() takes a long time first time it's called
|
||||
sdGetFreeSectors();
|
||||
|
||||
#if defined(LOG_TELEMETRY)
|
||||
f_open(&g_telemetryFile, LOGS_PATH "/telemetry.log", FA_OPEN_ALWAYS | FA_WRITE);
|
||||
if (f_size(&g_telemetryFile) > 0) {
|
||||
f_lseek(&g_telemetryFile, f_size(&g_telemetryFile)); // append
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
TRACE("f_mount() failed");
|
||||
}
|
||||
}
|
||||
|
||||
void sdDone()
|
||||
{
|
||||
TRACE("sdDone");
|
||||
|
||||
if (sdMounted()) {
|
||||
audioQueue.stopSD();
|
||||
#if defined(LOG_TELEMETRY)
|
||||
f_close(&g_telemetryFile);
|
||||
#endif
|
||||
f_mount(NULL, "", 0); // unmount SD
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t sdMounted()
|
||||
{
|
||||
return g_FATFS_Obj.fs_type != 0;
|
||||
}
|
||||
|
||||
uint32_t sdIsHC()
|
||||
{
|
||||
return true; // TODO (CardType & CT_BLOCK);
|
||||
}
|
||||
|
||||
uint32_t sdGetSpeed()
|
||||
{
|
||||
return 330000;
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* This is a stub disk I/O module that acts as front end of the existing */
|
||||
/* disk I/O modules and attach it to FatFs module with common interface. */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
#include "diskio.h"
|
||||
#include <string.h>
|
||||
#include "opentx.h"
|
||||
#include "sdio_sd.h"
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Lock / unlock functions */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
#if !defined(BOOT)
|
||||
static OS_MutexID ioMutex;
|
||||
uint32_t ioMutexReq = 0, ioMutexRel = 0;
|
||||
int ff_cre_syncobj (BYTE vol, _SYNC_t *mutex)
|
||||
{
|
||||
*mutex = ioMutex;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ff_req_grant (_SYNC_t mutex)
|
||||
{
|
||||
ioMutexReq += 1;
|
||||
return CoEnterMutexSection(mutex) == E_OK;
|
||||
}
|
||||
|
||||
void ff_rel_grant (_SYNC_t mutex)
|
||||
{
|
||||
ioMutexRel += 1;
|
||||
CoLeaveMutexSection(mutex);
|
||||
}
|
||||
|
||||
int ff_del_syncobj (_SYNC_t mutex)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Inidialize a Drive */
|
||||
|
||||
DSTATUS disk_initialize (
|
||||
BYTE drv /* Physical drive nmuber (0..) */
|
||||
)
|
||||
{
|
||||
DSTATUS stat = 0;
|
||||
|
||||
/* Supports only single drive */
|
||||
if (drv)
|
||||
{
|
||||
stat |= STA_NOINIT;
|
||||
}
|
||||
|
||||
/*-------------------------- SD Init ----------------------------- */
|
||||
SD_Error res = SD_Init();
|
||||
if (res != SD_OK)
|
||||
{
|
||||
TRACE("SD_Init() failed: %d", res);
|
||||
stat |= STA_NOINIT;
|
||||
}
|
||||
|
||||
TRACE("SD card info:");
|
||||
TRACE("sectors: %u", (uint32_t)(SDCardInfo.CardCapacity / 512));
|
||||
TRACE("type: %u", (uint32_t)(SDCardInfo.CardType));
|
||||
TRACE("EraseGrSize: %u", (uint32_t)(SDCardInfo.SD_csd.EraseGrSize));
|
||||
TRACE("EraseGrMul: %u", (uint32_t)(SDCardInfo.SD_csd.EraseGrMul));
|
||||
TRACE("ManufacturerID: %u", (uint32_t)(SDCardInfo.SD_cid.ManufacturerID));
|
||||
|
||||
return(stat);
|
||||
}
|
||||
|
||||
DWORD scratch[BLOCK_SIZE / 4] __DMA;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Return Disk Status */
|
||||
|
||||
DSTATUS disk_status (
|
||||
BYTE drv /* Physical drive nmuber (0..) */
|
||||
)
|
||||
{
|
||||
DSTATUS stat = 0;
|
||||
|
||||
if (SD_Detect() != SD_PRESENT)
|
||||
stat |= STA_NODISK;
|
||||
|
||||
// STA_NOTINIT - Subsystem not initailized
|
||||
// STA_PROTECTED - Write protected, MMC/SD switch if available
|
||||
|
||||
return(stat);
|
||||
}
|
||||
|
||||
uint32_t sdReadRetries = 0;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Read Sector(s) */
|
||||
|
||||
|
||||
DRESULT disk_read_dma(BYTE drv, BYTE * buff, DWORD sector, UINT count)
|
||||
{
|
||||
// this functions assumes that buff is properly aligned and in the right RAM segment for DMA
|
||||
DRESULT res;
|
||||
SD_Error Status;
|
||||
SDTransferState State;
|
||||
for (int retry=0; retry<3; retry++) {
|
||||
res = RES_OK;
|
||||
if (count == 1) {
|
||||
Status = SD_ReadBlock(buff, sector, BLOCK_SIZE); // 4GB Compliant
|
||||
}
|
||||
else {
|
||||
Status = SD_ReadMultiBlocks(buff, sector, BLOCK_SIZE, count); // 4GB Compliant
|
||||
}
|
||||
if (Status == SD_OK) {
|
||||
Status = SD_WaitReadOperation(200*count); // Check if the Transfer is finished
|
||||
while ((State = SD_GetStatus()) == SD_TRANSFER_BUSY); // BUSY, OK (DONE), ERROR (FAIL)
|
||||
if (State == SD_TRANSFER_ERROR) {
|
||||
TRACE("State=SD_TRANSFER_ERROR, c: %u", sector, (uint32_t)count);
|
||||
res = RES_ERROR;
|
||||
}
|
||||
else if (Status != SD_OK) {
|
||||
TRACE("Status(WaitRead)=%d, s:%u c: %u", Status, sector, (uint32_t)count);
|
||||
res = RES_ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
TRACE("Status(ReadBlock)=%d, s:%u c: %u", Status, sector, (uint32_t)count);
|
||||
res = RES_ERROR;
|
||||
}
|
||||
if (res == RES_OK) break;
|
||||
sdReadRetries += 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
DRESULT __disk_read(BYTE drv, BYTE * buff, DWORD sector, UINT count)
|
||||
{
|
||||
// If unaligned, do the single block reads with a scratch buffer.
|
||||
// If aligned and single sector, do a single block read.
|
||||
// If aligned and multiple sectors, try multi block read.
|
||||
// If multi block read fails, try single block reads without
|
||||
// an intermediate buffer (move trough the provided buffer)
|
||||
|
||||
// TRACE("disk_read %d %p %10d %d", drv, buff, sector, count);
|
||||
if (SD_Detect() != SD_PRESENT) {
|
||||
TRACE("SD_Detect() != SD_PRESENT");
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
|
||||
DRESULT res = RES_OK;
|
||||
if (count == 0) return res;
|
||||
|
||||
if ((DWORD)buff < 0x20000000 || ((DWORD)buff & 3)) {
|
||||
// buffer is not aligned, use scratch buffer that is aligned
|
||||
TRACE("disk_read bad alignment (%p)", buff);
|
||||
while (count--) {
|
||||
res = disk_read_dma(drv, (BYTE *)scratch, sector++, 1);
|
||||
if (res != RES_OK) break;
|
||||
memcpy(buff, scratch, BLOCK_SIZE);
|
||||
buff += BLOCK_SIZE;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
res = disk_read_dma(drv, buff, sector, count);
|
||||
if (res != RES_OK && count > 1) {
|
||||
// multi-read failed, try reading same sectors, one by one
|
||||
TRACE("disk_read() multi-block failed, trying single block reads...");
|
||||
while (count--) {
|
||||
res = disk_read_dma(drv, buff, sector++, 1);
|
||||
if (res != RES_OK) break;
|
||||
buff += BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Write Sector(s) */
|
||||
|
||||
#if _READONLY == 0
|
||||
DRESULT __disk_write(
|
||||
BYTE drv, /* Physical drive nmuber (0..) */
|
||||
const BYTE *buff, /* Data to be written */
|
||||
DWORD sector, /* Sector address (LBA) */
|
||||
UINT count /* Number of sectors to write (1..255) */
|
||||
)
|
||||
{
|
||||
SD_Error Status;
|
||||
DRESULT res = RES_OK;
|
||||
|
||||
// TRACE("disk_write %d %p %10d %d", drv, buff, sector, count);
|
||||
|
||||
if (SD_Detect() != SD_PRESENT)
|
||||
return(RES_NOTRDY);
|
||||
|
||||
if ((DWORD)buff < 0x20000000 || ((DWORD)buff & 3)) {
|
||||
TRACE("disk_write bad alignment (%p)", buff);
|
||||
while(count--) {
|
||||
memcpy(scratch, buff, BLOCK_SIZE);
|
||||
|
||||
res = __disk_write(drv, (BYTE *)scratch, sector++, 1);
|
||||
|
||||
if (res != RES_OK)
|
||||
break;
|
||||
|
||||
buff += BLOCK_SIZE;
|
||||
}
|
||||
return(res);
|
||||
}
|
||||
|
||||
if (count == 1) {
|
||||
Status = SD_WriteBlock((uint8_t *)buff, sector, BLOCK_SIZE); // 4GB Compliant
|
||||
}
|
||||
else {
|
||||
Status = SD_WriteMultiBlocks((uint8_t *)buff, sector, BLOCK_SIZE, count); // 4GB Compliant
|
||||
}
|
||||
|
||||
if (Status == SD_OK) {
|
||||
SDTransferState State;
|
||||
|
||||
Status = SD_WaitWriteOperation(500*count); // Check if the Transfer is finished
|
||||
|
||||
while((State = SD_GetStatus()) == SD_TRANSFER_BUSY); // BUSY, OK (DONE), ERROR (FAIL)
|
||||
|
||||
if ((State == SD_TRANSFER_ERROR) || (Status != SD_OK)) {
|
||||
TRACE("__disk_write() err, st:%d,%d, s:%u c: %u", Status, State, sector, (uint32_t)count);
|
||||
res = RES_ERROR;
|
||||
}
|
||||
}
|
||||
else {
|
||||
res = RES_ERROR;
|
||||
}
|
||||
|
||||
// TRACE("result=%d", res);
|
||||
return res;
|
||||
}
|
||||
#endif /* _READONLY */
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* 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;
|
||||
|
||||
if (drv) return RES_PARERR;
|
||||
|
||||
res = RES_ERROR;
|
||||
|
||||
switch (ctrl) {
|
||||
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
|
||||
// use 512 for sector size, SDCardInfo.CardBlockSize is not sector size and can be 1024 for 2G SD cards!!!!
|
||||
*(DWORD*)buff = SDCardInfo.CardCapacity / BLOCK_SIZE;
|
||||
res = RES_OK;
|
||||
break;
|
||||
|
||||
case GET_SECTOR_SIZE : /* Get R/W sector size (WORD) */
|
||||
*(WORD*)buff = BLOCK_SIZE; // force sector size. SDCardInfo.CardBlockSize is not sector size and can be 1024 for 2G SD cards!!!!
|
||||
res = RES_OK;
|
||||
break;
|
||||
|
||||
case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */
|
||||
// TODO verify that this is the correct value
|
||||
*(DWORD*)buff = (uint32_t)SDCardInfo.SD_csd.EraseGrSize * (uint32_t)SDCardInfo.SD_csd.EraseGrMul;
|
||||
res = RES_OK;
|
||||
break;
|
||||
|
||||
case CTRL_SYNC:
|
||||
while (SD_GetStatus() == SD_TRANSFER_BUSY); /* Complete pending write process (needed at _FS_READONLY == 0) */
|
||||
res = RES_OK;
|
||||
break;
|
||||
|
||||
default:
|
||||
res = RES_OK;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// TODO everything here should not be in the driver layer ...
|
||||
|
||||
FATFS g_FATFS_Obj __DMA; // initialized in boardInit()
|
||||
#if defined(LOG_TELEMETRY)
|
||||
FIL g_telemetryFile = {};
|
||||
#endif
|
||||
|
||||
void sdInit()
|
||||
{
|
||||
TRACE("sdInit");
|
||||
|
||||
ioMutex = CoCreateMutex();
|
||||
if (ioMutex >= CFG_MAX_MUTEX) {
|
||||
// sd error
|
||||
return;
|
||||
}
|
||||
sdMount();
|
||||
}
|
||||
|
||||
void sdMount()
|
||||
{
|
||||
TRACE("sdMount");
|
||||
|
||||
diskCache.clear();
|
||||
|
||||
if (f_mount(&g_FATFS_Obj, "", 1) == FR_OK) {
|
||||
// call sdGetFreeSectors() now because f_getfree() takes a long time first time it's called
|
||||
sdGetFreeSectors();
|
||||
|
||||
#if defined(LOG_TELEMETRY)
|
||||
f_open(&g_telemetryFile, LOGS_PATH "/telemetry.log", FA_OPEN_ALWAYS | FA_WRITE);
|
||||
if (f_size(&g_telemetryFile) > 0) {
|
||||
f_lseek(&g_telemetryFile, f_size(&g_telemetryFile)); // append
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
TRACE("f_mount() failed");
|
||||
}
|
||||
}
|
||||
|
||||
void sdDone()
|
||||
{
|
||||
TRACE("sdDone");
|
||||
|
||||
if (sdMounted()) {
|
||||
audioQueue.stopSD();
|
||||
#if defined(LOG_TELEMETRY)
|
||||
f_close(&g_telemetryFile);
|
||||
#endif
|
||||
f_mount(NULL, "", 0); // unmount SD
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t sdMounted()
|
||||
{
|
||||
return g_FATFS_Obj.fs_type != 0;
|
||||
}
|
||||
|
||||
uint32_t sdIsHC()
|
||||
{
|
||||
return true; // TODO (CardType & CT_BLOCK);
|
||||
}
|
||||
|
||||
uint32_t sdGetSpeed()
|
||||
{
|
||||
return 330000;
|
||||
}
|
||||
|
||||
@@ -1,309 +1,309 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 extmoduleSendNextFrame();
|
||||
|
||||
void extmoduleStop()
|
||||
{
|
||||
EXTERNAL_MODULE_OFF();
|
||||
|
||||
NVIC_DisableIRQ(EXTMODULE_DMA_IRQn);
|
||||
NVIC_DisableIRQ(EXTMODULE_TIMER_IRQn);
|
||||
|
||||
EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
|
||||
EXTMODULE_TIMER->DIER &= ~(TIM_DIER_CC2IE | TIM_DIER_UDE);
|
||||
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
|
||||
}
|
||||
|
||||
void extmoduleNoneStart()
|
||||
{
|
||||
EXTERNAL_MODULE_OFF();
|
||||
|
||||
GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, 0);
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure);
|
||||
GPIO_SetBits(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PIN); // Set high
|
||||
|
||||
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
|
||||
EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
|
||||
EXTMODULE_TIMER->ARR = 36000; // 18mS
|
||||
EXTMODULE_TIMER->CCR2 = 32000; // Update time
|
||||
EXTMODULE_TIMER->EGR = 1; // Restart
|
||||
EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF;
|
||||
EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
|
||||
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
|
||||
NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn);
|
||||
NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7);
|
||||
}
|
||||
|
||||
void extmodulePpmStart()
|
||||
{
|
||||
EXTERNAL_MODULE_ON();
|
||||
|
||||
GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, EXTMODULE_PPM_GPIO_AF);
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure);
|
||||
|
||||
// PPM generation principle:
|
||||
//
|
||||
// Hardware timer in PWM mode is used for PPM generation
|
||||
// Output is OFF if CNT<CCR1(delay) and ON if bigger
|
||||
// CCR1 register defines duration of pulse length and is constant
|
||||
// AAR register defines duration of each pulse, it is
|
||||
// updated after every pulse in Update interrupt handler.
|
||||
// CCR2 register defines duration of no pulses (time between two pulse trains)
|
||||
// it is calculated every round to have PPM period constant.
|
||||
// CC2 interrupt is then used to setup new PPM values for the
|
||||
// next PPM pulses train.
|
||||
|
||||
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop timer
|
||||
EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
|
||||
EXTMODULE_TIMER->ARR = 45000;
|
||||
#if PCBREV >= 13
|
||||
EXTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2; // PWM mode 1
|
||||
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE;
|
||||
EXTMODULE_TIMER->EGR = 1; // Reloads register values now
|
||||
EXTMODULE_TIMER->DIER = TIM_DIER_UDE; // Update DMA request
|
||||
EXTMODULE_TIMER->CR1 = TIM_CR1_CEN; // Start timer
|
||||
#else
|
||||
EXTMODULE_TIMER->CCR1 = GET_PPM_DELAY(EXTERNAL_MODULE)*2;
|
||||
EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | (GET_PPM_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC1P : 0);
|
||||
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0; // Force O/P high
|
||||
EXTMODULE_TIMER->EGR = 1; // Reloads register values now
|
||||
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Update DMA request
|
||||
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC2PE; // PWM mode 1
|
||||
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; // Start timer
|
||||
#endif
|
||||
|
||||
extmoduleSendNextFrame();
|
||||
|
||||
NVIC_EnableIRQ(EXTMODULE_DMA_IRQn);
|
||||
NVIC_SetPriority(EXTMODULE_DMA_IRQn, 7);
|
||||
NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn);
|
||||
NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7);
|
||||
}
|
||||
|
||||
void extmodulePxxStart()
|
||||
{
|
||||
EXTERNAL_MODULE_ON();
|
||||
|
||||
GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, EXTMODULE_PPM_GPIO_AF);
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure);
|
||||
|
||||
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
|
||||
EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
|
||||
EXTMODULE_TIMER->ARR = 18000;
|
||||
|
||||
#if PCBREV >= 13
|
||||
EXTMODULE_TIMER->CCER = TIM_CCER_CC3E | TIM_CCER_CC3NE;
|
||||
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs
|
||||
EXTMODULE_TIMER->CCR3 = 18;
|
||||
EXTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_0; // Force O/P high
|
||||
EXTMODULE_TIMER->EGR = 1; // Restart
|
||||
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update
|
||||
EXTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2;
|
||||
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
#else
|
||||
EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P | TIM_CCER_CC1NE | TIM_CCER_CC1NP; // TIM_CCER_CC1E | TIM_CCER_CC1P;
|
||||
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs
|
||||
EXTMODULE_TIMER->CCR1 = 18;
|
||||
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0; // Force O/P high
|
||||
EXTMODULE_TIMER->EGR = 1; // Restart
|
||||
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update
|
||||
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2;
|
||||
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
#endif
|
||||
|
||||
extmoduleSendNextFrame();
|
||||
|
||||
NVIC_EnableIRQ(EXTMODULE_DMA_IRQn);
|
||||
NVIC_SetPriority(EXTMODULE_DMA_IRQn, 7);
|
||||
NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn);
|
||||
NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7);
|
||||
}
|
||||
|
||||
#if defined(DSM2)
|
||||
void extmoduleDsm2Start()
|
||||
{
|
||||
EXTERNAL_MODULE_ON();
|
||||
|
||||
GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, EXTMODULE_PPM_GPIO_AF);
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure);
|
||||
|
||||
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
|
||||
EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
|
||||
EXTMODULE_TIMER->ARR = 44000; // 22mS
|
||||
|
||||
#if PCBREV >= 13
|
||||
EXTMODULE_TIMER->CCER = TIM_CCER_CC3E | TIM_CCER_CC3P;
|
||||
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs
|
||||
EXTMODULE_TIMER->CCR3 = 0;
|
||||
EXTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_0; // Force O/P high
|
||||
EXTMODULE_TIMER->EGR = 1; // Restart
|
||||
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update
|
||||
EXTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0;
|
||||
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
#else
|
||||
EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P;
|
||||
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs
|
||||
EXTMODULE_TIMER->CCR1 = 0;
|
||||
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0; // Force O/P high
|
||||
EXTMODULE_TIMER->EGR = 1; // Restart
|
||||
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update
|
||||
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0;
|
||||
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
#endif
|
||||
|
||||
extmoduleSendNextFrame();
|
||||
|
||||
NVIC_EnableIRQ(EXTMODULE_DMA_IRQn);
|
||||
NVIC_SetPriority(EXTMODULE_DMA_IRQn, 7);
|
||||
NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn);
|
||||
NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7);
|
||||
}
|
||||
#endif
|
||||
|
||||
void extmoduleCrossfireStart()
|
||||
{
|
||||
EXTERNAL_MODULE_ON();
|
||||
|
||||
GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, 0);
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure);
|
||||
GPIO_SetBits(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PIN); // Set high
|
||||
|
||||
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
|
||||
EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
|
||||
EXTMODULE_TIMER->ARR = (2000 * CROSSFIRE_FRAME_PERIOD);
|
||||
EXTMODULE_TIMER->CCR2 = (2000 * CROSSFIRE_FRAME_PERIOD) - 1000;
|
||||
EXTMODULE_TIMER->EGR = 1; // Restart
|
||||
EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF;
|
||||
EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
|
||||
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
|
||||
NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn);
|
||||
NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7);
|
||||
}
|
||||
|
||||
void extmoduleSendNextFrame()
|
||||
{
|
||||
if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PPM) {
|
||||
#if PCBREV >= 13
|
||||
EXTMODULE_TIMER->CCR3 = GET_PPM_DELAY(EXTERNAL_MODULE)*2;
|
||||
EXTMODULE_TIMER->CCER = TIM_CCER_CC3E | (GET_PPM_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC3P : 0);
|
||||
EXTMODULE_TIMER->CCR2 = *(modulePulsesData[EXTERNAL_MODULE].ppm.ptr - 1) - 4000; // 2mS in advance
|
||||
EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
|
||||
EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
|
||||
#else
|
||||
EXTMODULE_TIMER->CCR1 = GET_PPM_DELAY(EXTERNAL_MODULE)*2;
|
||||
EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | (GET_PPM_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC1P : 0);
|
||||
EXTMODULE_TIMER->CCR2 = *(modulePulsesData[EXTERNAL_MODULE].ppm.ptr - 1) - 4000; // 2mS in advance
|
||||
EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
|
||||
EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_1 | DMA_SxCR_MSIZE_1 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
|
||||
#endif
|
||||
EXTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
|
||||
EXTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].ppm.pulses);
|
||||
EXTMODULE_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].ppm.ptr - modulePulsesData[EXTERNAL_MODULE].ppm.pulses;
|
||||
EXTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
|
||||
}
|
||||
else if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PXX) {
|
||||
EXTMODULE_TIMER->CCR2 = *(modulePulsesData[EXTERNAL_MODULE].pxx.ptr - 1) - 4000; // 2mS in advance
|
||||
EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
|
||||
#if PCBREV >= 13
|
||||
EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
|
||||
#else
|
||||
EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_1 | DMA_SxCR_MSIZE_1 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
|
||||
#endif
|
||||
EXTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
|
||||
EXTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].pxx.pulses);
|
||||
EXTMODULE_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].pxx.ptr - modulePulsesData[EXTERNAL_MODULE].pxx.pulses;
|
||||
EXTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
|
||||
}
|
||||
else if (IS_DSM2_PROTOCOL(s_current_protocol[EXTERNAL_MODULE]) || IS_MULTIMODULE_PROTOCOL(s_current_protocol[EXTERNAL_MODULE])) {
|
||||
EXTMODULE_TIMER->CCR2 = *(modulePulsesData[EXTERNAL_MODULE].dsm2.ptr - 1) - 4000; // 2mS in advance
|
||||
EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
|
||||
#if PCBREV >= 13
|
||||
EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
|
||||
#else
|
||||
EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_1 | DMA_SxCR_MSIZE_1 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
|
||||
#endif
|
||||
EXTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
|
||||
EXTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].dsm2.pulses);
|
||||
EXTMODULE_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].dsm2.ptr - modulePulsesData[EXTERNAL_MODULE].dsm2.pulses;
|
||||
EXTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
|
||||
}
|
||||
else {
|
||||
EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void EXTMODULE_DMA_IRQHandler()
|
||||
{
|
||||
if (!DMA_GetITStatus(EXTMODULE_DMA_STREAM, EXTMODULE_DMA_FLAG_TC))
|
||||
return;
|
||||
|
||||
DMA_ClearITPendingBit(EXTMODULE_DMA_STREAM, EXTMODULE_DMA_FLAG_TC);
|
||||
|
||||
EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag
|
||||
EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
|
||||
}
|
||||
|
||||
extern "C" void EXTMODULE_TIMER_IRQHandler()
|
||||
{
|
||||
EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; // Stop this interrupt
|
||||
EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF;
|
||||
setupPulses(EXTERNAL_MODULE);
|
||||
extmoduleSendNextFrame();
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 extmoduleSendNextFrame();
|
||||
|
||||
void extmoduleStop()
|
||||
{
|
||||
EXTERNAL_MODULE_OFF();
|
||||
|
||||
NVIC_DisableIRQ(EXTMODULE_DMA_IRQn);
|
||||
NVIC_DisableIRQ(EXTMODULE_TIMER_IRQn);
|
||||
|
||||
EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
|
||||
EXTMODULE_TIMER->DIER &= ~(TIM_DIER_CC2IE | TIM_DIER_UDE);
|
||||
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
|
||||
}
|
||||
|
||||
void extmoduleNoneStart()
|
||||
{
|
||||
EXTERNAL_MODULE_OFF();
|
||||
|
||||
GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, 0);
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure);
|
||||
GPIO_SetBits(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PIN); // Set high
|
||||
|
||||
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
|
||||
EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
|
||||
EXTMODULE_TIMER->ARR = 36000; // 18mS
|
||||
EXTMODULE_TIMER->CCR2 = 32000; // Update time
|
||||
EXTMODULE_TIMER->EGR = 1; // Restart
|
||||
EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF;
|
||||
EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
|
||||
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
|
||||
NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn);
|
||||
NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7);
|
||||
}
|
||||
|
||||
void extmodulePpmStart()
|
||||
{
|
||||
EXTERNAL_MODULE_ON();
|
||||
|
||||
GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, EXTMODULE_PPM_GPIO_AF);
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure);
|
||||
|
||||
// PPM generation principle:
|
||||
//
|
||||
// Hardware timer in PWM mode is used for PPM generation
|
||||
// Output is OFF if CNT<CCR1(delay) and ON if bigger
|
||||
// CCR1 register defines duration of pulse length and is constant
|
||||
// AAR register defines duration of each pulse, it is
|
||||
// updated after every pulse in Update interrupt handler.
|
||||
// CCR2 register defines duration of no pulses (time between two pulse trains)
|
||||
// it is calculated every round to have PPM period constant.
|
||||
// CC2 interrupt is then used to setup new PPM values for the
|
||||
// next PPM pulses train.
|
||||
|
||||
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop timer
|
||||
EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
|
||||
EXTMODULE_TIMER->ARR = 45000;
|
||||
#if PCBREV >= 13
|
||||
EXTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2; // PWM mode 1
|
||||
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE;
|
||||
EXTMODULE_TIMER->EGR = 1; // Reloads register values now
|
||||
EXTMODULE_TIMER->DIER = TIM_DIER_UDE; // Update DMA request
|
||||
EXTMODULE_TIMER->CR1 = TIM_CR1_CEN; // Start timer
|
||||
#else
|
||||
EXTMODULE_TIMER->CCR1 = GET_PPM_DELAY(EXTERNAL_MODULE)*2;
|
||||
EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | (GET_PPM_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC1P : 0);
|
||||
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0; // Force O/P high
|
||||
EXTMODULE_TIMER->EGR = 1; // Reloads register values now
|
||||
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Update DMA request
|
||||
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC2PE; // PWM mode 1
|
||||
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; // Start timer
|
||||
#endif
|
||||
|
||||
extmoduleSendNextFrame();
|
||||
|
||||
NVIC_EnableIRQ(EXTMODULE_DMA_IRQn);
|
||||
NVIC_SetPriority(EXTMODULE_DMA_IRQn, 7);
|
||||
NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn);
|
||||
NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7);
|
||||
}
|
||||
|
||||
void extmodulePxxStart()
|
||||
{
|
||||
EXTERNAL_MODULE_ON();
|
||||
|
||||
GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, EXTMODULE_PPM_GPIO_AF);
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure);
|
||||
|
||||
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
|
||||
EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
|
||||
EXTMODULE_TIMER->ARR = 18000;
|
||||
|
||||
#if PCBREV >= 13
|
||||
EXTMODULE_TIMER->CCER = TIM_CCER_CC3E | TIM_CCER_CC3NE;
|
||||
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs
|
||||
EXTMODULE_TIMER->CCR3 = 18;
|
||||
EXTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_0; // Force O/P high
|
||||
EXTMODULE_TIMER->EGR = 1; // Restart
|
||||
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update
|
||||
EXTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2;
|
||||
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
#else
|
||||
EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P | TIM_CCER_CC1NE | TIM_CCER_CC1NP; // TIM_CCER_CC1E | TIM_CCER_CC1P;
|
||||
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs
|
||||
EXTMODULE_TIMER->CCR1 = 18;
|
||||
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0; // Force O/P high
|
||||
EXTMODULE_TIMER->EGR = 1; // Restart
|
||||
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update
|
||||
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2;
|
||||
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
#endif
|
||||
|
||||
extmoduleSendNextFrame();
|
||||
|
||||
NVIC_EnableIRQ(EXTMODULE_DMA_IRQn);
|
||||
NVIC_SetPriority(EXTMODULE_DMA_IRQn, 7);
|
||||
NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn);
|
||||
NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7);
|
||||
}
|
||||
|
||||
#if defined(DSM2)
|
||||
void extmoduleDsm2Start()
|
||||
{
|
||||
EXTERNAL_MODULE_ON();
|
||||
|
||||
GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, EXTMODULE_PPM_GPIO_AF);
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure);
|
||||
|
||||
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
|
||||
EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
|
||||
EXTMODULE_TIMER->ARR = 44000; // 22mS
|
||||
|
||||
#if PCBREV >= 13
|
||||
EXTMODULE_TIMER->CCER = TIM_CCER_CC3E | TIM_CCER_CC3P;
|
||||
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs
|
||||
EXTMODULE_TIMER->CCR3 = 0;
|
||||
EXTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_0; // Force O/P high
|
||||
EXTMODULE_TIMER->EGR = 1; // Restart
|
||||
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update
|
||||
EXTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0;
|
||||
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
#else
|
||||
EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P;
|
||||
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs
|
||||
EXTMODULE_TIMER->CCR1 = 0;
|
||||
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0; // Force O/P high
|
||||
EXTMODULE_TIMER->EGR = 1; // Restart
|
||||
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update
|
||||
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0;
|
||||
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
#endif
|
||||
|
||||
extmoduleSendNextFrame();
|
||||
|
||||
NVIC_EnableIRQ(EXTMODULE_DMA_IRQn);
|
||||
NVIC_SetPriority(EXTMODULE_DMA_IRQn, 7);
|
||||
NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn);
|
||||
NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7);
|
||||
}
|
||||
#endif
|
||||
|
||||
void extmoduleCrossfireStart()
|
||||
{
|
||||
EXTERNAL_MODULE_ON();
|
||||
|
||||
GPIO_PinAFConfig(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PinSource, 0);
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = EXTMODULE_PPM_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(EXTMODULE_PPM_GPIO, &GPIO_InitStructure);
|
||||
GPIO_SetBits(EXTMODULE_PPM_GPIO, EXTMODULE_PPM_GPIO_PIN); // Set high
|
||||
|
||||
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
|
||||
EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
|
||||
EXTMODULE_TIMER->ARR = (2000 * CROSSFIRE_FRAME_PERIOD);
|
||||
EXTMODULE_TIMER->CCR2 = (2000 * CROSSFIRE_FRAME_PERIOD) - 1000;
|
||||
EXTMODULE_TIMER->EGR = 1; // Restart
|
||||
EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF;
|
||||
EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
|
||||
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
|
||||
NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn);
|
||||
NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7);
|
||||
}
|
||||
|
||||
void extmoduleSendNextFrame()
|
||||
{
|
||||
if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PPM) {
|
||||
#if PCBREV >= 13
|
||||
EXTMODULE_TIMER->CCR3 = GET_PPM_DELAY(EXTERNAL_MODULE)*2;
|
||||
EXTMODULE_TIMER->CCER = TIM_CCER_CC3E | (GET_PPM_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC3P : 0);
|
||||
EXTMODULE_TIMER->CCR2 = *(modulePulsesData[EXTERNAL_MODULE].ppm.ptr - 1) - 4000; // 2mS in advance
|
||||
EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
|
||||
EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
|
||||
#else
|
||||
EXTMODULE_TIMER->CCR1 = GET_PPM_DELAY(EXTERNAL_MODULE)*2;
|
||||
EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | (GET_PPM_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC1P : 0);
|
||||
EXTMODULE_TIMER->CCR2 = *(modulePulsesData[EXTERNAL_MODULE].ppm.ptr - 1) - 4000; // 2mS in advance
|
||||
EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
|
||||
EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_1 | DMA_SxCR_MSIZE_1 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
|
||||
#endif
|
||||
EXTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
|
||||
EXTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].ppm.pulses);
|
||||
EXTMODULE_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].ppm.ptr - modulePulsesData[EXTERNAL_MODULE].ppm.pulses;
|
||||
EXTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
|
||||
}
|
||||
else if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PXX) {
|
||||
EXTMODULE_TIMER->CCR2 = *(modulePulsesData[EXTERNAL_MODULE].pxx.ptr - 1) - 4000; // 2mS in advance
|
||||
EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
|
||||
#if PCBREV >= 13
|
||||
EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
|
||||
#else
|
||||
EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_1 | DMA_SxCR_MSIZE_1 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
|
||||
#endif
|
||||
EXTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
|
||||
EXTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].pxx.pulses);
|
||||
EXTMODULE_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].pxx.ptr - modulePulsesData[EXTERNAL_MODULE].pxx.pulses;
|
||||
EXTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
|
||||
}
|
||||
else if (IS_DSM2_PROTOCOL(s_current_protocol[EXTERNAL_MODULE]) || IS_MULTIMODULE_PROTOCOL(s_current_protocol[EXTERNAL_MODULE])) {
|
||||
EXTMODULE_TIMER->CCR2 = *(modulePulsesData[EXTERNAL_MODULE].dsm2.ptr - 1) - 4000; // 2mS in advance
|
||||
EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
|
||||
#if PCBREV >= 13
|
||||
EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
|
||||
#else
|
||||
EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_1 | DMA_SxCR_MSIZE_1 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
|
||||
#endif
|
||||
EXTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
|
||||
EXTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].dsm2.pulses);
|
||||
EXTMODULE_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].dsm2.ptr - modulePulsesData[EXTERNAL_MODULE].dsm2.pulses;
|
||||
EXTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
|
||||
}
|
||||
else {
|
||||
EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void EXTMODULE_DMA_IRQHandler()
|
||||
{
|
||||
if (!DMA_GetITStatus(EXTMODULE_DMA_STREAM, EXTMODULE_DMA_FLAG_TC))
|
||||
return;
|
||||
|
||||
DMA_ClearITPendingBit(EXTMODULE_DMA_STREAM, EXTMODULE_DMA_FLAG_TC);
|
||||
|
||||
EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag
|
||||
EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
|
||||
}
|
||||
|
||||
extern "C" void EXTMODULE_TIMER_IRQHandler()
|
||||
{
|
||||
EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; // Stop this interrupt
|
||||
EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF;
|
||||
setupPulses(EXTERNAL_MODULE);
|
||||
extmoduleSendNextFrame();
|
||||
}
|
||||
|
||||
+627
-627
File diff suppressed because it is too large
Load Diff
@@ -1,217 +1,217 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 rotencPosition;
|
||||
|
||||
uint32_t readKeys()
|
||||
{
|
||||
uint32_t result = 0;
|
||||
|
||||
#if defined(PCBX12S)
|
||||
if (~KEYS_GPIO_REG_PGUP & KEYS_GPIO_PIN_PGUP)
|
||||
result |= 1 << KEY_PGUP;
|
||||
#endif
|
||||
if (~KEYS_GPIO_REG_PGDN & KEYS_GPIO_PIN_PGDN)
|
||||
result |= 1 << KEY_PGDN;
|
||||
if (~KEYS_GPIO_REG_ENTER & KEYS_GPIO_PIN_ENTER)
|
||||
result |= 1 << KEY_ENTER;
|
||||
if (~KEYS_GPIO_REG_UP & KEYS_GPIO_PIN_UP)
|
||||
result |= 1 << KEY_MODEL;
|
||||
if (~KEYS_GPIO_REG_DOWN & KEYS_GPIO_PIN_DOWN)
|
||||
result |= 1 << KEY_EXIT;
|
||||
if (~KEYS_GPIO_REG_RIGHT & KEYS_GPIO_PIN_RIGHT)
|
||||
result |= 1 << KEY_TELEM;
|
||||
if (~KEYS_GPIO_REG_LEFT & KEYS_GPIO_PIN_LEFT)
|
||||
result |= 1 << KEY_RADIO;
|
||||
|
||||
// TRACE("readKeys(): %x", result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t readTrims()
|
||||
{
|
||||
uint32_t result = 0;
|
||||
|
||||
if (~TRIMS_GPIO_REG_LHL & TRIMS_GPIO_PIN_LHL)
|
||||
result |= 0x01;
|
||||
if (~TRIMS_GPIO_REG_LHR & TRIMS_GPIO_PIN_LHR)
|
||||
result |= 0x02;
|
||||
if (~TRIMS_GPIO_REG_LVD & TRIMS_GPIO_PIN_LVD)
|
||||
result |= 0x04;
|
||||
if (~TRIMS_GPIO_REG_LVU & TRIMS_GPIO_PIN_LVU)
|
||||
result |= 0x08;
|
||||
if (~TRIMS_GPIO_REG_RVD & TRIMS_GPIO_PIN_RVD)
|
||||
result |= 0x10;
|
||||
if (~TRIMS_GPIO_REG_RVU & TRIMS_GPIO_PIN_RVU)
|
||||
result |= 0x20;
|
||||
if (~TRIMS_GPIO_REG_RHL & TRIMS_GPIO_PIN_RHL)
|
||||
result |= 0x40;
|
||||
if (~TRIMS_GPIO_REG_RHR & TRIMS_GPIO_PIN_RHR)
|
||||
result |= 0x80;
|
||||
if (~TRIMS_GPIO_REG_LSD & TRIMS_GPIO_PIN_LSD)
|
||||
result |= 0x100;
|
||||
if (~TRIMS_GPIO_REG_LSU & TRIMS_GPIO_PIN_LSU)
|
||||
result |= 0x200;
|
||||
if (~TRIMS_GPIO_REG_RSD & TRIMS_GPIO_PIN_RSD)
|
||||
result |= 0x400;
|
||||
if (~TRIMS_GPIO_REG_RSU & TRIMS_GPIO_PIN_RSU)
|
||||
result |= 0x800;
|
||||
// TRACE("readTrims(): result=0x%04x", result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t trimDown(uint16_t idx)
|
||||
{
|
||||
return readTrims() & (1 << idx);
|
||||
}
|
||||
|
||||
uint8_t keyDown()
|
||||
{
|
||||
return readKeys();
|
||||
}
|
||||
|
||||
void checkRotaryEncoder()
|
||||
{
|
||||
uint32_t newpos = ROTARY_ENCODER_POSITION();
|
||||
if (newpos != rotencPosition && !keyState(KEY_ENTER)) {
|
||||
if ((rotencPosition & 0x01) ^ ((newpos & 0x02) >> 1)) {
|
||||
--rotencValue[0];
|
||||
}
|
||||
else {
|
||||
++rotencValue[0];
|
||||
}
|
||||
rotencPosition = newpos;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO common to ARM */
|
||||
void readKeysAndTrims()
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
uint8_t index = 0;
|
||||
uint32_t in = readKeys();
|
||||
for (i = 0; i < TRM_BASE; i++) {
|
||||
keys[index++].input(in & (1 << i));
|
||||
}
|
||||
|
||||
in = readTrims();
|
||||
for (i = 1; i <= 1 << (TRM_LAST-TRM_BASE); i <<= 1) {
|
||||
keys[index++].input(in & i);
|
||||
}
|
||||
}
|
||||
|
||||
#define ADD_2POS_CASE(x) \
|
||||
case SW_S ## x ## 0: \
|
||||
xxx = SWITCHES_GPIO_REG_ ## x & SWITCHES_GPIO_PIN_ ## x ; \
|
||||
break; \
|
||||
case SW_S ## x ## 2: \
|
||||
xxx = ~SWITCHES_GPIO_REG_ ## x & SWITCHES_GPIO_PIN_ ## x ; \
|
||||
break
|
||||
#define ADD_NEG_2POS_CASE(x) \
|
||||
case SW_S ## x ## 2: \
|
||||
xxx = SWITCHES_GPIO_REG_ ## x & SWITCHES_GPIO_PIN_ ## x ; \
|
||||
break; \
|
||||
case SW_S ## x ## 0: \
|
||||
xxx = ~SWITCHES_GPIO_REG_ ## x & SWITCHES_GPIO_PIN_ ## x ; \
|
||||
break
|
||||
#define ADD_3POS_CASE(x, i) \
|
||||
case SW_S ## x ## 0: \
|
||||
xxx = (SWITCHES_GPIO_REG_ ## x ## _H & SWITCHES_GPIO_PIN_ ## x ## _H); \
|
||||
if (IS_3POS(i)) { \
|
||||
xxx = xxx && (~SWITCHES_GPIO_REG_ ## x ## _L & SWITCHES_GPIO_PIN_ ## x ## _L); \
|
||||
} \
|
||||
break; \
|
||||
case SW_S ## x ## 1: \
|
||||
xxx = (SWITCHES_GPIO_REG_ ## x ## _H & SWITCHES_GPIO_PIN_ ## x ## _H) && (SWITCHES_GPIO_REG_ ## x ## _L & SWITCHES_GPIO_PIN_ ## x ## _L); \
|
||||
break; \
|
||||
case SW_S ## x ## 2: \
|
||||
xxx = (~SWITCHES_GPIO_REG_ ## x ## _H & SWITCHES_GPIO_PIN_ ## x ## _H); \
|
||||
if (IS_3POS(i)) { \
|
||||
xxx = xxx && (SWITCHES_GPIO_REG_ ## x ## _L & SWITCHES_GPIO_PIN_ ## x ## _L); \
|
||||
} \
|
||||
break
|
||||
|
||||
#if !defined(BOOT)
|
||||
uint8_t keyState(uint8_t index)
|
||||
{
|
||||
return keys[index].state();
|
||||
}
|
||||
|
||||
uint32_t switchState(uint8_t index)
|
||||
{
|
||||
uint32_t xxx = 0;
|
||||
|
||||
switch (index) {
|
||||
ADD_3POS_CASE(A, 0);
|
||||
ADD_3POS_CASE(B, 1);
|
||||
ADD_3POS_CASE(C, 2);
|
||||
ADD_3POS_CASE(D, 3);
|
||||
ADD_3POS_CASE(E, 4);
|
||||
ADD_NEG_2POS_CASE(F);
|
||||
ADD_3POS_CASE(G, 6);
|
||||
ADD_2POS_CASE(H);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// TRACE("switch %d => %d", index, xxx);
|
||||
return xxx;
|
||||
}
|
||||
#endif
|
||||
|
||||
void keysInit()
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = KEYS_GPIOB_PINS;
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = KEYS_GPIOC_PINS;
|
||||
GPIO_Init(GPIOC, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = KEYS_GPIOD_PINS;
|
||||
GPIO_Init(GPIOD, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = KEYS_GPIOE_PINS;
|
||||
GPIO_Init(GPIOE, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = KEYS_GPIOG_PINS;
|
||||
GPIO_Init(GPIOG, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = KEYS_GPIOH_PINS;
|
||||
GPIO_Init(GPIOH, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = KEYS_GPIOI_PINS;
|
||||
GPIO_Init(GPIOI, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = KEYS_GPIOJ_PINS;
|
||||
GPIO_Init(GPIOJ, &GPIO_InitStructure);
|
||||
|
||||
rotencPosition = ROTARY_ENCODER_POSITION();
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 rotencPosition;
|
||||
|
||||
uint32_t readKeys()
|
||||
{
|
||||
uint32_t result = 0;
|
||||
|
||||
#if defined(PCBX12S)
|
||||
if (~KEYS_GPIO_REG_PGUP & KEYS_GPIO_PIN_PGUP)
|
||||
result |= 1 << KEY_PGUP;
|
||||
#endif
|
||||
if (~KEYS_GPIO_REG_PGDN & KEYS_GPIO_PIN_PGDN)
|
||||
result |= 1 << KEY_PGDN;
|
||||
if (~KEYS_GPIO_REG_ENTER & KEYS_GPIO_PIN_ENTER)
|
||||
result |= 1 << KEY_ENTER;
|
||||
if (~KEYS_GPIO_REG_UP & KEYS_GPIO_PIN_UP)
|
||||
result |= 1 << KEY_MODEL;
|
||||
if (~KEYS_GPIO_REG_DOWN & KEYS_GPIO_PIN_DOWN)
|
||||
result |= 1 << KEY_EXIT;
|
||||
if (~KEYS_GPIO_REG_RIGHT & KEYS_GPIO_PIN_RIGHT)
|
||||
result |= 1 << KEY_TELEM;
|
||||
if (~KEYS_GPIO_REG_LEFT & KEYS_GPIO_PIN_LEFT)
|
||||
result |= 1 << KEY_RADIO;
|
||||
|
||||
// TRACE("readKeys(): %x", result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t readTrims()
|
||||
{
|
||||
uint32_t result = 0;
|
||||
|
||||
if (~TRIMS_GPIO_REG_LHL & TRIMS_GPIO_PIN_LHL)
|
||||
result |= 0x01;
|
||||
if (~TRIMS_GPIO_REG_LHR & TRIMS_GPIO_PIN_LHR)
|
||||
result |= 0x02;
|
||||
if (~TRIMS_GPIO_REG_LVD & TRIMS_GPIO_PIN_LVD)
|
||||
result |= 0x04;
|
||||
if (~TRIMS_GPIO_REG_LVU & TRIMS_GPIO_PIN_LVU)
|
||||
result |= 0x08;
|
||||
if (~TRIMS_GPIO_REG_RVD & TRIMS_GPIO_PIN_RVD)
|
||||
result |= 0x10;
|
||||
if (~TRIMS_GPIO_REG_RVU & TRIMS_GPIO_PIN_RVU)
|
||||
result |= 0x20;
|
||||
if (~TRIMS_GPIO_REG_RHL & TRIMS_GPIO_PIN_RHL)
|
||||
result |= 0x40;
|
||||
if (~TRIMS_GPIO_REG_RHR & TRIMS_GPIO_PIN_RHR)
|
||||
result |= 0x80;
|
||||
if (~TRIMS_GPIO_REG_LSD & TRIMS_GPIO_PIN_LSD)
|
||||
result |= 0x100;
|
||||
if (~TRIMS_GPIO_REG_LSU & TRIMS_GPIO_PIN_LSU)
|
||||
result |= 0x200;
|
||||
if (~TRIMS_GPIO_REG_RSD & TRIMS_GPIO_PIN_RSD)
|
||||
result |= 0x400;
|
||||
if (~TRIMS_GPIO_REG_RSU & TRIMS_GPIO_PIN_RSU)
|
||||
result |= 0x800;
|
||||
// TRACE("readTrims(): result=0x%04x", result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t trimDown(uint16_t idx)
|
||||
{
|
||||
return readTrims() & (1 << idx);
|
||||
}
|
||||
|
||||
uint8_t keyDown()
|
||||
{
|
||||
return readKeys();
|
||||
}
|
||||
|
||||
void checkRotaryEncoder()
|
||||
{
|
||||
uint32_t newpos = ROTARY_ENCODER_POSITION();
|
||||
if (newpos != rotencPosition && !keyState(KEY_ENTER)) {
|
||||
if ((rotencPosition & 0x01) ^ ((newpos & 0x02) >> 1)) {
|
||||
--rotencValue[0];
|
||||
}
|
||||
else {
|
||||
++rotencValue[0];
|
||||
}
|
||||
rotencPosition = newpos;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO common to ARM */
|
||||
void readKeysAndTrims()
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
uint8_t index = 0;
|
||||
uint32_t in = readKeys();
|
||||
for (i = 0; i < TRM_BASE; i++) {
|
||||
keys[index++].input(in & (1 << i));
|
||||
}
|
||||
|
||||
in = readTrims();
|
||||
for (i = 1; i <= 1 << (TRM_LAST-TRM_BASE); i <<= 1) {
|
||||
keys[index++].input(in & i);
|
||||
}
|
||||
}
|
||||
|
||||
#define ADD_2POS_CASE(x) \
|
||||
case SW_S ## x ## 0: \
|
||||
xxx = SWITCHES_GPIO_REG_ ## x & SWITCHES_GPIO_PIN_ ## x ; \
|
||||
break; \
|
||||
case SW_S ## x ## 2: \
|
||||
xxx = ~SWITCHES_GPIO_REG_ ## x & SWITCHES_GPIO_PIN_ ## x ; \
|
||||
break
|
||||
#define ADD_NEG_2POS_CASE(x) \
|
||||
case SW_S ## x ## 2: \
|
||||
xxx = SWITCHES_GPIO_REG_ ## x & SWITCHES_GPIO_PIN_ ## x ; \
|
||||
break; \
|
||||
case SW_S ## x ## 0: \
|
||||
xxx = ~SWITCHES_GPIO_REG_ ## x & SWITCHES_GPIO_PIN_ ## x ; \
|
||||
break
|
||||
#define ADD_3POS_CASE(x, i) \
|
||||
case SW_S ## x ## 0: \
|
||||
xxx = (SWITCHES_GPIO_REG_ ## x ## _H & SWITCHES_GPIO_PIN_ ## x ## _H); \
|
||||
if (IS_3POS(i)) { \
|
||||
xxx = xxx && (~SWITCHES_GPIO_REG_ ## x ## _L & SWITCHES_GPIO_PIN_ ## x ## _L); \
|
||||
} \
|
||||
break; \
|
||||
case SW_S ## x ## 1: \
|
||||
xxx = (SWITCHES_GPIO_REG_ ## x ## _H & SWITCHES_GPIO_PIN_ ## x ## _H) && (SWITCHES_GPIO_REG_ ## x ## _L & SWITCHES_GPIO_PIN_ ## x ## _L); \
|
||||
break; \
|
||||
case SW_S ## x ## 2: \
|
||||
xxx = (~SWITCHES_GPIO_REG_ ## x ## _H & SWITCHES_GPIO_PIN_ ## x ## _H); \
|
||||
if (IS_3POS(i)) { \
|
||||
xxx = xxx && (SWITCHES_GPIO_REG_ ## x ## _L & SWITCHES_GPIO_PIN_ ## x ## _L); \
|
||||
} \
|
||||
break
|
||||
|
||||
#if !defined(BOOT)
|
||||
uint8_t keyState(uint8_t index)
|
||||
{
|
||||
return keys[index].state();
|
||||
}
|
||||
|
||||
uint32_t switchState(uint8_t index)
|
||||
{
|
||||
uint32_t xxx = 0;
|
||||
|
||||
switch (index) {
|
||||
ADD_3POS_CASE(A, 0);
|
||||
ADD_3POS_CASE(B, 1);
|
||||
ADD_3POS_CASE(C, 2);
|
||||
ADD_3POS_CASE(D, 3);
|
||||
ADD_3POS_CASE(E, 4);
|
||||
ADD_NEG_2POS_CASE(F);
|
||||
ADD_3POS_CASE(G, 6);
|
||||
ADD_2POS_CASE(H);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// TRACE("switch %d => %d", index, xxx);
|
||||
return xxx;
|
||||
}
|
||||
#endif
|
||||
|
||||
void keysInit()
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = KEYS_GPIOB_PINS;
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = KEYS_GPIOC_PINS;
|
||||
GPIO_Init(GPIOC, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = KEYS_GPIOD_PINS;
|
||||
GPIO_Init(GPIOD, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = KEYS_GPIOE_PINS;
|
||||
GPIO_Init(GPIOE, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = KEYS_GPIOG_PINS;
|
||||
GPIO_Init(GPIOG, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = KEYS_GPIOH_PINS;
|
||||
GPIO_Init(GPIOH, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = KEYS_GPIOI_PINS;
|
||||
GPIO_Init(GPIOI, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = KEYS_GPIOJ_PINS;
|
||||
GPIO_Init(GPIOJ, &GPIO_InitStructure);
|
||||
|
||||
rotencPosition = ROTARY_ENCODER_POSITION();
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,270 +1,270 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 intmoduleStop(void);
|
||||
void extmoduleStop(void);
|
||||
|
||||
void intmoduleNoneStart(void);
|
||||
void intmodulePxxStart(void);
|
||||
|
||||
void extmoduleNoneStart(void);
|
||||
void extmodulePpmStart(void);
|
||||
void extmodulePxxStart(void);
|
||||
#if defined(DSM2)
|
||||
void extmoduleDsm2Start(void);
|
||||
#endif
|
||||
void extmoduleCrossfireStart(void);
|
||||
|
||||
void init_no_pulses(uint32_t port)
|
||||
{
|
||||
if (port == INTERNAL_MODULE)
|
||||
intmoduleNoneStart();
|
||||
else
|
||||
extmoduleNoneStart();
|
||||
}
|
||||
|
||||
void disable_no_pulses(uint32_t port)
|
||||
{
|
||||
if (port == INTERNAL_MODULE)
|
||||
intmoduleStop();
|
||||
else
|
||||
extmoduleStop();
|
||||
}
|
||||
|
||||
void init_ppm(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
extmodulePpmStart();
|
||||
}
|
||||
}
|
||||
|
||||
void disable_ppm(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
extmoduleStop();
|
||||
}
|
||||
}
|
||||
|
||||
void init_pxx(uint32_t port)
|
||||
{
|
||||
if (port == INTERNAL_MODULE)
|
||||
intmodulePxxStart();
|
||||
else
|
||||
extmodulePxxStart();
|
||||
}
|
||||
|
||||
void disable_pxx(uint32_t port)
|
||||
{
|
||||
if (port == INTERNAL_MODULE)
|
||||
intmoduleStop();
|
||||
else
|
||||
extmoduleStop();
|
||||
}
|
||||
|
||||
#if defined(DSM2)
|
||||
void init_dsm2(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
extmoduleDsm2Start();
|
||||
}
|
||||
}
|
||||
|
||||
void disable_dsm2(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
extmoduleStop();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MULTIMODULE)
|
||||
void init_multimodule(uint32_t port)
|
||||
{
|
||||
init_dsm2(port);
|
||||
}
|
||||
|
||||
void disable_multimodule(uint32_t port)
|
||||
{
|
||||
disable_dsm2(port);
|
||||
}
|
||||
#endif
|
||||
|
||||
void init_crossfire(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
extmoduleCrossfireStart();
|
||||
}
|
||||
}
|
||||
|
||||
void disable_crossfire(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
extmoduleStop();
|
||||
}
|
||||
}
|
||||
|
||||
void intmoduleStop()
|
||||
{
|
||||
INTERNAL_MODULE_OFF();
|
||||
|
||||
NVIC_DisableIRQ(INTMODULE_TIMER_IRQn);
|
||||
|
||||
INTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE;
|
||||
INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
|
||||
}
|
||||
|
||||
void intmoduleNoneStart()
|
||||
{
|
||||
INTERNAL_MODULE_OFF();
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = INTMODULE_TX_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(INTMODULE_TX_GPIO, &GPIO_InitStructure);
|
||||
GPIO_SetBits(INTMODULE_TX_GPIO, INTMODULE_TX_GPIO_PIN); // Set high
|
||||
|
||||
INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
|
||||
INTMODULE_TIMER->ARR = 36000; // 18mS
|
||||
INTMODULE_TIMER->CCR2 = 32000; // Update time
|
||||
INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
|
||||
|
||||
INTMODULE_TIMER->CCER = TIM_CCER_CC3E;
|
||||
|
||||
INTMODULE_TIMER->CCMR2 = 0;
|
||||
INTMODULE_TIMER->EGR = 1; // Restart
|
||||
|
||||
INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0; // Toggle CC1 o/p
|
||||
INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag
|
||||
INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
|
||||
INTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
NVIC_EnableIRQ(INTMODULE_TIMER_IRQn);
|
||||
NVIC_SetPriority(INTMODULE_TIMER_IRQn, 7);
|
||||
}
|
||||
|
||||
void intmodulePxxStart()
|
||||
{
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
INTERNAL_MODULE_ON();
|
||||
|
||||
NVIC_InitStructure.NVIC_IRQChannel = INTMODULE_DMA_STREAM_IRQ;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /* Not used as 4 bits are used for the pre-emption priority. */;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
// TX Pin
|
||||
GPIO_PinAFConfig(INTMODULE_TX_GPIO, INTMODULE_TX_GPIO_PinSource, INTMODULE_GPIO_AF);
|
||||
GPIO_InitStructure.GPIO_Pin = INTMODULE_TX_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_Init(INTMODULE_TX_GPIO, &GPIO_InitStructure);
|
||||
|
||||
// RX Pin
|
||||
GPIO_PinAFConfig(INTMODULE_RX_GPIO, INTMODULE_RX_GPIO_PinSource, INTMODULE_GPIO_AF);
|
||||
GPIO_InitStructure.GPIO_Pin = INTMODULE_RX_GPIO_PIN;
|
||||
GPIO_Init(INTMODULE_RX_GPIO, &GPIO_InitStructure);
|
||||
|
||||
// UART config
|
||||
USART_DeInit(INTMODULE_USART);
|
||||
USART_InitTypeDef USART_InitStructure;
|
||||
USART_InitStructure.USART_BaudRate = 115200;
|
||||
USART_InitStructure.USART_Parity = USART_Parity_No;
|
||||
USART_InitStructure.USART_StopBits = USART_StopBits_1;
|
||||
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
||||
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
||||
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
|
||||
USART_Init(INTMODULE_USART, &USART_InitStructure);
|
||||
USART_Cmd(INTMODULE_USART, ENABLE);
|
||||
|
||||
// Timer
|
||||
INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
|
||||
INTMODULE_TIMER->ARR = 18000; // 9mS
|
||||
INTMODULE_TIMER->CCR2 = 15000; // Update time
|
||||
INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
|
||||
INTMODULE_TIMER->CCER = TIM_CCER_CC3E;
|
||||
INTMODULE_TIMER->CCMR2 = 0;
|
||||
INTMODULE_TIMER->EGR = 1; // Restart
|
||||
|
||||
INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0; // Toggle CC1 o/p
|
||||
INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag
|
||||
INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
|
||||
INTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
|
||||
NVIC_EnableIRQ(INTMODULE_TIMER_IRQn);
|
||||
NVIC_SetPriority(INTMODULE_TIMER_IRQn, 7);
|
||||
}
|
||||
|
||||
extern "C" void INTMODULE_DMA_STREAM_IRQHandler(void)
|
||||
{
|
||||
DEBUG_INTERRUPT(INT_DMA2S7);
|
||||
if (DMA_GetITStatus(INTMODULE_DMA_STREAM, INTMODULE_DMA_FLAG_TC)) {
|
||||
// TODO we could send the 8 next channels here (when needed)
|
||||
DMA_ClearITPendingBit(INTMODULE_DMA_STREAM, INTMODULE_DMA_FLAG_TC);
|
||||
}
|
||||
}
|
||||
|
||||
void intmoduleSendNextFrame()
|
||||
{
|
||||
if (s_current_protocol[INTERNAL_MODULE] == PROTO_PXX) {
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
DMA_DeInit(INTMODULE_DMA_STREAM);
|
||||
DMA_InitStructure.DMA_Channel = INTMODULE_DMA_CHANNEL;
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&INTMODULE_USART->DR);
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
|
||||
DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(modulePulsesData[INTERNAL_MODULE].pxx_uart.pulses);
|
||||
DMA_InitStructure.DMA_BufferSize = modulePulsesData[INTERNAL_MODULE].pxx_uart.ptr - modulePulsesData[INTERNAL_MODULE].pxx_uart.pulses;
|
||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
||||
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
|
||||
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
||||
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
|
||||
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
DMA_Init(INTMODULE_DMA_STREAM, &DMA_InitStructure);
|
||||
|
||||
DMA_Cmd(INTMODULE_DMA_STREAM, ENABLE);
|
||||
USART_DMACmd(INTMODULE_USART, USART_DMAReq_Tx, ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void INTMODULE_TIMER_IRQHandler()
|
||||
{
|
||||
DEBUG_INTERRUPT(INT_TIM1CC);
|
||||
DEBUG_TIMER_SAMPLE(debugTimerIntPulses);
|
||||
DEBUG_TIMER_START(debugTimerIntPulsesDuration);
|
||||
|
||||
INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // clear flag
|
||||
setupPulses(INTERNAL_MODULE);
|
||||
intmoduleSendNextFrame();
|
||||
|
||||
DEBUG_TIMER_STOP(debugTimerIntPulsesDuration);
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 intmoduleStop(void);
|
||||
void extmoduleStop(void);
|
||||
|
||||
void intmoduleNoneStart(void);
|
||||
void intmodulePxxStart(void);
|
||||
|
||||
void extmoduleNoneStart(void);
|
||||
void extmodulePpmStart(void);
|
||||
void extmodulePxxStart(void);
|
||||
#if defined(DSM2)
|
||||
void extmoduleDsm2Start(void);
|
||||
#endif
|
||||
void extmoduleCrossfireStart(void);
|
||||
|
||||
void init_no_pulses(uint32_t port)
|
||||
{
|
||||
if (port == INTERNAL_MODULE)
|
||||
intmoduleNoneStart();
|
||||
else
|
||||
extmoduleNoneStart();
|
||||
}
|
||||
|
||||
void disable_no_pulses(uint32_t port)
|
||||
{
|
||||
if (port == INTERNAL_MODULE)
|
||||
intmoduleStop();
|
||||
else
|
||||
extmoduleStop();
|
||||
}
|
||||
|
||||
void init_ppm(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
extmodulePpmStart();
|
||||
}
|
||||
}
|
||||
|
||||
void disable_ppm(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
extmoduleStop();
|
||||
}
|
||||
}
|
||||
|
||||
void init_pxx(uint32_t port)
|
||||
{
|
||||
if (port == INTERNAL_MODULE)
|
||||
intmodulePxxStart();
|
||||
else
|
||||
extmodulePxxStart();
|
||||
}
|
||||
|
||||
void disable_pxx(uint32_t port)
|
||||
{
|
||||
if (port == INTERNAL_MODULE)
|
||||
intmoduleStop();
|
||||
else
|
||||
extmoduleStop();
|
||||
}
|
||||
|
||||
#if defined(DSM2)
|
||||
void init_dsm2(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
extmoduleDsm2Start();
|
||||
}
|
||||
}
|
||||
|
||||
void disable_dsm2(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
extmoduleStop();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MULTIMODULE)
|
||||
void init_multimodule(uint32_t port)
|
||||
{
|
||||
init_dsm2(port);
|
||||
}
|
||||
|
||||
void disable_multimodule(uint32_t port)
|
||||
{
|
||||
disable_dsm2(port);
|
||||
}
|
||||
#endif
|
||||
|
||||
void init_crossfire(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
extmoduleCrossfireStart();
|
||||
}
|
||||
}
|
||||
|
||||
void disable_crossfire(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
extmoduleStop();
|
||||
}
|
||||
}
|
||||
|
||||
void intmoduleStop()
|
||||
{
|
||||
INTERNAL_MODULE_OFF();
|
||||
|
||||
NVIC_DisableIRQ(INTMODULE_TIMER_IRQn);
|
||||
|
||||
INTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE;
|
||||
INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
|
||||
}
|
||||
|
||||
void intmoduleNoneStart()
|
||||
{
|
||||
INTERNAL_MODULE_OFF();
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = INTMODULE_TX_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(INTMODULE_TX_GPIO, &GPIO_InitStructure);
|
||||
GPIO_SetBits(INTMODULE_TX_GPIO, INTMODULE_TX_GPIO_PIN); // Set high
|
||||
|
||||
INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
|
||||
INTMODULE_TIMER->ARR = 36000; // 18mS
|
||||
INTMODULE_TIMER->CCR2 = 32000; // Update time
|
||||
INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
|
||||
|
||||
INTMODULE_TIMER->CCER = TIM_CCER_CC3E;
|
||||
|
||||
INTMODULE_TIMER->CCMR2 = 0;
|
||||
INTMODULE_TIMER->EGR = 1; // Restart
|
||||
|
||||
INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0; // Toggle CC1 o/p
|
||||
INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag
|
||||
INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
|
||||
INTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
NVIC_EnableIRQ(INTMODULE_TIMER_IRQn);
|
||||
NVIC_SetPriority(INTMODULE_TIMER_IRQn, 7);
|
||||
}
|
||||
|
||||
void intmodulePxxStart()
|
||||
{
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
INTERNAL_MODULE_ON();
|
||||
|
||||
NVIC_InitStructure.NVIC_IRQChannel = INTMODULE_DMA_STREAM_IRQ;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /* Not used as 4 bits are used for the pre-emption priority. */;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
// TX Pin
|
||||
GPIO_PinAFConfig(INTMODULE_TX_GPIO, INTMODULE_TX_GPIO_PinSource, INTMODULE_GPIO_AF);
|
||||
GPIO_InitStructure.GPIO_Pin = INTMODULE_TX_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_Init(INTMODULE_TX_GPIO, &GPIO_InitStructure);
|
||||
|
||||
// RX Pin
|
||||
GPIO_PinAFConfig(INTMODULE_RX_GPIO, INTMODULE_RX_GPIO_PinSource, INTMODULE_GPIO_AF);
|
||||
GPIO_InitStructure.GPIO_Pin = INTMODULE_RX_GPIO_PIN;
|
||||
GPIO_Init(INTMODULE_RX_GPIO, &GPIO_InitStructure);
|
||||
|
||||
// UART config
|
||||
USART_DeInit(INTMODULE_USART);
|
||||
USART_InitTypeDef USART_InitStructure;
|
||||
USART_InitStructure.USART_BaudRate = 115200;
|
||||
USART_InitStructure.USART_Parity = USART_Parity_No;
|
||||
USART_InitStructure.USART_StopBits = USART_StopBits_1;
|
||||
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
||||
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
||||
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
|
||||
USART_Init(INTMODULE_USART, &USART_InitStructure);
|
||||
USART_Cmd(INTMODULE_USART, ENABLE);
|
||||
|
||||
// Timer
|
||||
INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
|
||||
INTMODULE_TIMER->ARR = 18000; // 9mS
|
||||
INTMODULE_TIMER->CCR2 = 15000; // Update time
|
||||
INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
|
||||
INTMODULE_TIMER->CCER = TIM_CCER_CC3E;
|
||||
INTMODULE_TIMER->CCMR2 = 0;
|
||||
INTMODULE_TIMER->EGR = 1; // Restart
|
||||
|
||||
INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0; // Toggle CC1 o/p
|
||||
INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag
|
||||
INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
|
||||
INTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
|
||||
NVIC_EnableIRQ(INTMODULE_TIMER_IRQn);
|
||||
NVIC_SetPriority(INTMODULE_TIMER_IRQn, 7);
|
||||
}
|
||||
|
||||
extern "C" void INTMODULE_DMA_STREAM_IRQHandler(void)
|
||||
{
|
||||
DEBUG_INTERRUPT(INT_DMA2S7);
|
||||
if (DMA_GetITStatus(INTMODULE_DMA_STREAM, INTMODULE_DMA_FLAG_TC)) {
|
||||
// TODO we could send the 8 next channels here (when needed)
|
||||
DMA_ClearITPendingBit(INTMODULE_DMA_STREAM, INTMODULE_DMA_FLAG_TC);
|
||||
}
|
||||
}
|
||||
|
||||
void intmoduleSendNextFrame()
|
||||
{
|
||||
if (s_current_protocol[INTERNAL_MODULE] == PROTO_PXX) {
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
DMA_DeInit(INTMODULE_DMA_STREAM);
|
||||
DMA_InitStructure.DMA_Channel = INTMODULE_DMA_CHANNEL;
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&INTMODULE_USART->DR);
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
|
||||
DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(modulePulsesData[INTERNAL_MODULE].pxx_uart.pulses);
|
||||
DMA_InitStructure.DMA_BufferSize = modulePulsesData[INTERNAL_MODULE].pxx_uart.ptr - modulePulsesData[INTERNAL_MODULE].pxx_uart.pulses;
|
||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
||||
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
|
||||
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
||||
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
|
||||
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
DMA_Init(INTMODULE_DMA_STREAM, &DMA_InitStructure);
|
||||
|
||||
DMA_Cmd(INTMODULE_DMA_STREAM, ENABLE);
|
||||
USART_DMACmd(INTMODULE_USART, USART_DMAReq_Tx, ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void INTMODULE_TIMER_IRQHandler()
|
||||
{
|
||||
DEBUG_INTERRUPT(INT_TIM1CC);
|
||||
DEBUG_TIMER_SAMPLE(debugTimerIntPulses);
|
||||
DEBUG_TIMER_START(debugTimerIntPulsesDuration);
|
||||
|
||||
INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // clear flag
|
||||
setupPulses(INTERNAL_MODULE);
|
||||
intmoduleSendNextFrame();
|
||||
|
||||
DEBUG_TIMER_STOP(debugTimerIntPulsesDuration);
|
||||
}
|
||||
|
||||
@@ -1,150 +1,150 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 "pwr.h"
|
||||
#include "board.h"
|
||||
|
||||
uint32_t shutdownRequest; // Stores intentional shutdown to avoid reboot loop
|
||||
uint32_t shutdownReason; // Used for detecting unexpected reboots regardless of reason
|
||||
uint32_t powerupReason __NOINIT; // Stores power up reason beyond initialization for emergency mode activation
|
||||
|
||||
void pwrInit()
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = PWR_ON_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_Init(PWR_GPIO, &GPIO_InitStructure);
|
||||
|
||||
// Init Module PWR
|
||||
GPIO_ResetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN);
|
||||
GPIO_InitStructure.GPIO_Pin = INTMODULE_PWR_GPIO_PIN;
|
||||
GPIO_Init(INTMODULE_PWR_GPIO, &GPIO_InitStructure);
|
||||
|
||||
GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN);
|
||||
GPIO_InitStructure.GPIO_Pin = EXTMODULE_PWR_GPIO_PIN;
|
||||
GPIO_Init(EXTMODULE_PWR_GPIO, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
|
||||
|
||||
// Init PWR SWITCH PIN
|
||||
GPIO_InitStructure.GPIO_Pin = PWR_SWITCH_GPIO_PIN;
|
||||
GPIO_Init(PWR_GPIO, &GPIO_InitStructure);
|
||||
|
||||
// Init PCBREV PIN
|
||||
// TODO to be removed on X10?
|
||||
GPIO_ResetBits(PCBREV_GPIO, PCBREV_GPIO_PIN);
|
||||
GPIO_InitStructure.GPIO_Pin = PCBREV_GPIO_PIN;
|
||||
GPIO_Init(PCBREV_GPIO, &GPIO_InitStructure);
|
||||
|
||||
// Init SD-DETECT PIN
|
||||
GPIO_ResetBits(SD_PRESENT_GPIO, SD_PRESENT_GPIO_PIN);
|
||||
GPIO_InitStructure.GPIO_Pin = SD_PRESENT_GPIO_PIN;
|
||||
GPIO_Init(SD_PRESENT_GPIO, &GPIO_InitStructure);
|
||||
|
||||
// Init TRAINER DETECT PIN
|
||||
GPIO_InitStructure.GPIO_Pin = TRAINER_DETECT_GPIO_PIN;
|
||||
GPIO_Init(TRAINER_DETECT_GPIO, &GPIO_InitStructure);
|
||||
|
||||
pwrOn();
|
||||
}
|
||||
|
||||
void pwrOn()
|
||||
{
|
||||
GPIO_SetBits(PWR_GPIO, PWR_ON_GPIO_PIN);
|
||||
shutdownRequest = NO_SHUTDOWN_REQUEST;
|
||||
shutdownReason = DIRTY_SHUTDOWN;
|
||||
}
|
||||
|
||||
void pwrOff()
|
||||
{
|
||||
#if defined(PCBX12S)
|
||||
// Shutdown the Audio amp
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = AUDIO_SHUTDOWN_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_Init(AUDIO_SHUTDOWN_GPIO, &GPIO_InitStructure);
|
||||
GPIO_ResetBits(AUDIO_SHUTDOWN_GPIO, AUDIO_SHUTDOWN_GPIO_PIN);
|
||||
#endif
|
||||
|
||||
// Shutdown the Haptic
|
||||
hapticDone();
|
||||
|
||||
shutdownRequest = SHUTDOWN_REQUEST;
|
||||
shutdownReason = NORMAL_POWER_OFF;
|
||||
GPIO_ResetBits(PWR_GPIO, PWR_ON_GPIO_PIN);
|
||||
}
|
||||
|
||||
uint32_t pwrPressed()
|
||||
{
|
||||
return GPIO_ReadInputDataBit(PWR_GPIO, PWR_SWITCH_GPIO_PIN) == Bit_RESET;
|
||||
}
|
||||
|
||||
void pwrResetHandler()
|
||||
{
|
||||
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOJEN;
|
||||
|
||||
// these two NOPs are needed (see STM32F errata sheet) before the peripheral
|
||||
// register can be written after the peripheral clock was enabled
|
||||
__ASM volatile ("nop");
|
||||
__ASM volatile ("nop");
|
||||
|
||||
// We get here whether we are powering up normally, we had an unexpected reboot or we have just powered down normally.
|
||||
// We want:
|
||||
// - In the 2nd case, to power ON as soon as possible if an unexpected reboot happened
|
||||
// (we get there running on remaining capacitor charge, soft power having been cut by the RESET).
|
||||
// - In the 3rd case, NOT power on as that would prevent from turning the system off.
|
||||
// - The 1st case does not need to be handled here, but will be as a result of the handling for the 3rd case, see below.
|
||||
//
|
||||
// shutdownRequest is used to handle the 3rd case. If we really powered down on purpose this will still be set to SHUTDOWN_REQUEST
|
||||
// as we left it in pwrOff(). If however we had an unexpected reboot, it would be set to NO_SHUTDOWN_REQUEST as we set it in pwrOn().
|
||||
// Any other value (e.g. resulting from data corruption) would also keep power on for safety, so this variable can NOT be used
|
||||
// to detect an unexpected reboot (on a normal power on the contents of the variable are random).
|
||||
//
|
||||
// shutdownReason is used to differentiate between an unexpected reboot and a normal power on. We set it to DIRTY_SHUTDOWN in pwrOn()
|
||||
// in anticipation of a potential reboot. Should there be one the value should be preserved and signal below that we rebooted unexpectedly.
|
||||
// If it is NOT set to DIRTY_SHUTDOWN we likely had a normal boot and its contents are random. Due to the need to initialize it to detect a
|
||||
// potential failure ASAP we cannot use it to determine in the firmware why we got there, it has to be buffered.
|
||||
//
|
||||
// powerupReason is there to cater for that, and is what is used in the firmware to decide whether we have to enter emergency mode.
|
||||
// This variable needs to be in a RAM section that is not initialized or zeroed, since once we exit this pwrResetHandler() function the
|
||||
// C runtime would otherwise overwrite it during program init.
|
||||
|
||||
if (shutdownRequest != SHUTDOWN_REQUEST) {
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = PWR_ON_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_Init(PWR_GPIO, &GPIO_InitStructure);
|
||||
|
||||
if (shutdownReason == DIRTY_SHUTDOWN) {
|
||||
powerupReason = DIRTY_SHUTDOWN;
|
||||
}
|
||||
|
||||
pwrOn();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 "pwr.h"
|
||||
#include "board.h"
|
||||
|
||||
uint32_t shutdownRequest; // Stores intentional shutdown to avoid reboot loop
|
||||
uint32_t shutdownReason; // Used for detecting unexpected reboots regardless of reason
|
||||
uint32_t powerupReason __NOINIT; // Stores power up reason beyond initialization for emergency mode activation
|
||||
|
||||
void pwrInit()
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = PWR_ON_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_Init(PWR_GPIO, &GPIO_InitStructure);
|
||||
|
||||
// Init Module PWR
|
||||
GPIO_ResetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN);
|
||||
GPIO_InitStructure.GPIO_Pin = INTMODULE_PWR_GPIO_PIN;
|
||||
GPIO_Init(INTMODULE_PWR_GPIO, &GPIO_InitStructure);
|
||||
|
||||
GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN);
|
||||
GPIO_InitStructure.GPIO_Pin = EXTMODULE_PWR_GPIO_PIN;
|
||||
GPIO_Init(EXTMODULE_PWR_GPIO, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
|
||||
|
||||
// Init PWR SWITCH PIN
|
||||
GPIO_InitStructure.GPIO_Pin = PWR_SWITCH_GPIO_PIN;
|
||||
GPIO_Init(PWR_GPIO, &GPIO_InitStructure);
|
||||
|
||||
// Init PCBREV PIN
|
||||
// TODO to be removed on X10?
|
||||
GPIO_ResetBits(PCBREV_GPIO, PCBREV_GPIO_PIN);
|
||||
GPIO_InitStructure.GPIO_Pin = PCBREV_GPIO_PIN;
|
||||
GPIO_Init(PCBREV_GPIO, &GPIO_InitStructure);
|
||||
|
||||
// Init SD-DETECT PIN
|
||||
GPIO_ResetBits(SD_PRESENT_GPIO, SD_PRESENT_GPIO_PIN);
|
||||
GPIO_InitStructure.GPIO_Pin = SD_PRESENT_GPIO_PIN;
|
||||
GPIO_Init(SD_PRESENT_GPIO, &GPIO_InitStructure);
|
||||
|
||||
// Init TRAINER DETECT PIN
|
||||
GPIO_InitStructure.GPIO_Pin = TRAINER_DETECT_GPIO_PIN;
|
||||
GPIO_Init(TRAINER_DETECT_GPIO, &GPIO_InitStructure);
|
||||
|
||||
pwrOn();
|
||||
}
|
||||
|
||||
void pwrOn()
|
||||
{
|
||||
GPIO_SetBits(PWR_GPIO, PWR_ON_GPIO_PIN);
|
||||
shutdownRequest = NO_SHUTDOWN_REQUEST;
|
||||
shutdownReason = DIRTY_SHUTDOWN;
|
||||
}
|
||||
|
||||
void pwrOff()
|
||||
{
|
||||
#if defined(PCBX12S)
|
||||
// Shutdown the Audio amp
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = AUDIO_SHUTDOWN_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_Init(AUDIO_SHUTDOWN_GPIO, &GPIO_InitStructure);
|
||||
GPIO_ResetBits(AUDIO_SHUTDOWN_GPIO, AUDIO_SHUTDOWN_GPIO_PIN);
|
||||
#endif
|
||||
|
||||
// Shutdown the Haptic
|
||||
hapticDone();
|
||||
|
||||
shutdownRequest = SHUTDOWN_REQUEST;
|
||||
shutdownReason = NORMAL_POWER_OFF;
|
||||
GPIO_ResetBits(PWR_GPIO, PWR_ON_GPIO_PIN);
|
||||
}
|
||||
|
||||
uint32_t pwrPressed()
|
||||
{
|
||||
return GPIO_ReadInputDataBit(PWR_GPIO, PWR_SWITCH_GPIO_PIN) == Bit_RESET;
|
||||
}
|
||||
|
||||
void pwrResetHandler()
|
||||
{
|
||||
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOJEN;
|
||||
|
||||
// these two NOPs are needed (see STM32F errata sheet) before the peripheral
|
||||
// register can be written after the peripheral clock was enabled
|
||||
__ASM volatile ("nop");
|
||||
__ASM volatile ("nop");
|
||||
|
||||
// We get here whether we are powering up normally, we had an unexpected reboot or we have just powered down normally.
|
||||
// We want:
|
||||
// - In the 2nd case, to power ON as soon as possible if an unexpected reboot happened
|
||||
// (we get there running on remaining capacitor charge, soft power having been cut by the RESET).
|
||||
// - In the 3rd case, NOT power on as that would prevent from turning the system off.
|
||||
// - The 1st case does not need to be handled here, but will be as a result of the handling for the 3rd case, see below.
|
||||
//
|
||||
// shutdownRequest is used to handle the 3rd case. If we really powered down on purpose this will still be set to SHUTDOWN_REQUEST
|
||||
// as we left it in pwrOff(). If however we had an unexpected reboot, it would be set to NO_SHUTDOWN_REQUEST as we set it in pwrOn().
|
||||
// Any other value (e.g. resulting from data corruption) would also keep power on for safety, so this variable can NOT be used
|
||||
// to detect an unexpected reboot (on a normal power on the contents of the variable are random).
|
||||
//
|
||||
// shutdownReason is used to differentiate between an unexpected reboot and a normal power on. We set it to DIRTY_SHUTDOWN in pwrOn()
|
||||
// in anticipation of a potential reboot. Should there be one the value should be preserved and signal below that we rebooted unexpectedly.
|
||||
// If it is NOT set to DIRTY_SHUTDOWN we likely had a normal boot and its contents are random. Due to the need to initialize it to detect a
|
||||
// potential failure ASAP we cannot use it to determine in the firmware why we got there, it has to be buffered.
|
||||
//
|
||||
// powerupReason is there to cater for that, and is what is used in the firmware to decide whether we have to enter emergency mode.
|
||||
// This variable needs to be in a RAM section that is not initialized or zeroed, since once we exit this pwrResetHandler() function the
|
||||
// C runtime would otherwise overwrite it during program init.
|
||||
|
||||
if (shutdownRequest != SHUTDOWN_REQUEST) {
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = PWR_ON_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_Init(PWR_GPIO, &GPIO_InitStructure);
|
||||
|
||||
if (shutdownReason == DIRTY_SHUTDOWN) {
|
||||
powerupReason = DIRTY_SHUTDOWN;
|
||||
}
|
||||
|
||||
pwrOn();
|
||||
}
|
||||
}
|
||||
|
||||
+2767
-2767
File diff suppressed because it is too large
Load Diff
+220
-220
@@ -1,220 +1,220 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef _SDIO_SD_H_
|
||||
#define _SDIO_SD_H_
|
||||
|
||||
#include "board.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
typedef enum
|
||||
{
|
||||
/**
|
||||
* @brief SDIO specific error defines
|
||||
*/
|
||||
SD_CMD_CRC_FAIL = (1), /*!< Command response received (but CRC check failed) */
|
||||
SD_DATA_CRC_FAIL = (2), /*!< Data bock sent/received (CRC check Failed) */
|
||||
SD_CMD_RSP_TIMEOUT = (3), /*!< Command response timeout */
|
||||
SD_DATA_TIMEOUT = (4), /*!< Data time out */
|
||||
SD_TX_UNDERRUN = (5), /*!< Transmit FIFO under-run */
|
||||
SD_RX_OVERRUN = (6), /*!< Receive FIFO over-run */
|
||||
SD_START_BIT_ERR = (7), /*!< Start bit not detected on all data signals in widE bus mode */
|
||||
SD_CMD_OUT_OF_RANGE = (8), /*!< CMD's argument was out of range.*/
|
||||
SD_ADDR_MISALIGNED = (9), /*!< Misaligned address */
|
||||
SD_BLOCK_LEN_ERR = (10), /*!< Transferred block length is not allowed for the card or the number of transferred bytes does not match the block length */
|
||||
SD_ERASE_SEQ_ERR = (11), /*!< An error in the sequence of erase command occurs.*/
|
||||
SD_BAD_ERASE_PARAM = (12), /*!< An Invalid selection for erase groups */
|
||||
SD_WRITE_PROT_VIOLATION = (13), /*!< Attempt to program a write protect block */
|
||||
SD_LOCK_UNLOCK_FAILED = (14), /*!< Sequence or password error has been detected in unlock command or if there was an attempt to access a locked card */
|
||||
SD_COM_CRC_FAILED = (15), /*!< CRC check of the previous command failed */
|
||||
SD_ILLEGAL_CMD = (16), /*!< Command is not legal for the card state */
|
||||
SD_CARD_ECC_FAILED = (17), /*!< Card internal ECC was applied but failed to correct the data */
|
||||
SD_CC_ERROR = (18), /*!< Internal card controller error */
|
||||
SD_GENERAL_UNKNOWN_ERROR = (19), /*!< General or Unknown error */
|
||||
SD_STREAM_READ_UNDERRUN = (20), /*!< The card could not sustain data transfer in stream read operation. */
|
||||
SD_STREAM_WRITE_OVERRUN = (21), /*!< The card could not sustain data programming in stream mode */
|
||||
SD_CID_CSD_OVERWRITE = (22), /*!< CID/CSD overwrite error */
|
||||
SD_WP_ERASE_SKIP = (23), /*!< only partial address space was erased */
|
||||
SD_CARD_ECC_DISABLED = (24), /*!< Command has been executed without using internal ECC */
|
||||
SD_ERASE_RESET = (25), /*!< Erase sequence was cleared before executing because an out of erase sequence command was received */
|
||||
SD_AKE_SEQ_ERROR = (26), /*!< Error in sequence of authentication. */
|
||||
SD_INVALID_VOLTRANGE = (27),
|
||||
SD_ADDR_OUT_OF_RANGE = (28),
|
||||
SD_SWITCH_ERROR = (29),
|
||||
SD_SDIO_DISABLED = (30),
|
||||
SD_SDIO_FUNCTION_BUSY = (31),
|
||||
SD_SDIO_FUNCTION_FAILED = (32),
|
||||
SD_SDIO_UNKNOWN_FUNCTION = (33),
|
||||
|
||||
/**
|
||||
* @brief Standard error defines
|
||||
*/
|
||||
SD_INTERNAL_ERROR,
|
||||
SD_NOT_CONFIGURED,
|
||||
SD_REQUEST_PENDING,
|
||||
SD_REQUEST_NOT_APPLICABLE,
|
||||
SD_INVALID_PARAMETER,
|
||||
SD_UNSUPPORTED_FEATURE,
|
||||
SD_UNSUPPORTED_HW,
|
||||
SD_ERROR,
|
||||
SD_OK = 0
|
||||
} SD_Error;
|
||||
|
||||
/**
|
||||
* @brief SDIO Transfer state
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SD_TRANSFER_OK = 0,
|
||||
SD_TRANSFER_BUSY = 1,
|
||||
SD_TRANSFER_ERROR
|
||||
} SDTransferState;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Card Specific Data: CSD Register
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint8_t CSDStruct; /*!< CSD structure */
|
||||
__IO uint8_t SysSpecVersion; /*!< System specification version */
|
||||
__IO uint8_t Reserved1; /*!< Reserved */
|
||||
__IO uint8_t TAAC; /*!< Data read access-time 1 */
|
||||
__IO uint8_t NSAC; /*!< Data read access-time 2 in CLK cycles */
|
||||
__IO uint8_t MaxBusClkFrec; /*!< Max. bus clock frequency */
|
||||
__IO uint16_t CardComdClasses; /*!< Card command classes */
|
||||
__IO uint8_t RdBlockLen; /*!< Max. read data block length */
|
||||
__IO uint8_t PartBlockRead; /*!< Partial blocks for read allowed */
|
||||
__IO uint8_t WrBlockMisalign; /*!< Write block misalignment */
|
||||
__IO uint8_t RdBlockMisalign; /*!< Read block misalignment */
|
||||
__IO uint8_t DSRImpl; /*!< DSR implemented */
|
||||
__IO uint8_t Reserved2; /*!< Reserved */
|
||||
__IO uint32_t DeviceSize; /*!< Device Size */
|
||||
__IO uint8_t MaxRdCurrentVDDMin; /*!< Max. read current @ VDD min */
|
||||
__IO uint8_t MaxRdCurrentVDDMax; /*!< Max. read current @ VDD max */
|
||||
__IO uint8_t MaxWrCurrentVDDMin; /*!< Max. write current @ VDD min */
|
||||
__IO uint8_t MaxWrCurrentVDDMax; /*!< Max. write current @ VDD max */
|
||||
__IO uint8_t DeviceSizeMul; /*!< Device size multiplier */
|
||||
__IO uint8_t EraseGrSize; /*!< Erase group size */
|
||||
__IO uint8_t EraseGrMul; /*!< Erase group size multiplier */
|
||||
__IO uint8_t WrProtectGrSize; /*!< Write protect group size */
|
||||
__IO uint8_t WrProtectGrEnable; /*!< Write protect group enable */
|
||||
__IO uint8_t ManDeflECC; /*!< Manufacturer default ECC */
|
||||
__IO uint8_t WrSpeedFact; /*!< Write speed factor */
|
||||
__IO uint8_t MaxWrBlockLen; /*!< Max. write data block length */
|
||||
__IO uint8_t WriteBlockPaPartial; /*!< Partial blocks for write allowed */
|
||||
__IO uint8_t Reserved3; /*!< Reserded */
|
||||
__IO uint8_t ContentProtectAppli; /*!< Content protection application */
|
||||
__IO uint8_t FileFormatGrouop; /*!< File format group */
|
||||
__IO uint8_t CopyFlag; /*!< Copy flag (OTP) */
|
||||
__IO uint8_t PermWrProtect; /*!< Permanent write protection */
|
||||
__IO uint8_t TempWrProtect; /*!< Temporary write protection */
|
||||
__IO uint8_t FileFormat; /*!< File Format */
|
||||
__IO uint8_t ECC; /*!< ECC code */
|
||||
__IO uint8_t CSD_CRC; /*!< CSD CRC */
|
||||
__IO uint8_t Reserved4; /*!< always 1*/
|
||||
} SD_CSD;
|
||||
|
||||
/**
|
||||
* @brief Card Identification Data: CID Register
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint8_t ManufacturerID; /*!< ManufacturerID */
|
||||
__IO uint16_t OEM_AppliID; /*!< OEM/Application ID */
|
||||
__IO uint32_t ProdName1; /*!< Product Name part1 */
|
||||
__IO uint8_t ProdName2; /*!< Product Name part2*/
|
||||
__IO uint8_t ProdRev; /*!< Product Revision */
|
||||
__IO uint32_t ProdSN; /*!< Product Serial Number */
|
||||
__IO uint8_t Reserved1; /*!< Reserved1 */
|
||||
__IO uint16_t ManufactDate; /*!< Manufacturing Date */
|
||||
__IO uint8_t CID_CRC; /*!< CID CRC */
|
||||
__IO uint8_t Reserved2; /*!< always 1 */
|
||||
} SD_CID;
|
||||
|
||||
/**
|
||||
* @brief SD Card Status
|
||||
*/
|
||||
// typedef struct
|
||||
// {
|
||||
// __IO uint8_t DAT_BUS_WIDTH;
|
||||
// __IO uint8_t SECURED_MODE;
|
||||
// __IO uint16_t SD_CARD_TYPE;
|
||||
// __IO uint32_t SIZE_OF_PROTECTED_AREA;
|
||||
// __IO uint8_t SPEED_CLASS;
|
||||
// __IO uint8_t PERFORMANCE_MOVE;
|
||||
// __IO uint8_t AU_SIZE;
|
||||
// __IO uint16_t ERASE_SIZE;
|
||||
// __IO uint8_t ERASE_TIMEOUT;
|
||||
// __IO uint8_t ERASE_OFFSET;
|
||||
// } SD_CardStatus;
|
||||
|
||||
|
||||
/**
|
||||
* @brief SD Card information
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
SD_CSD SD_csd;
|
||||
SD_CID SD_cid;
|
||||
uint64_t CardCapacity; /*!< Card Capacity */
|
||||
uint32_t CardBlockSize; /*!< Card Block Size */
|
||||
uint16_t RCA;
|
||||
uint8_t CardType;
|
||||
} SD_CardInfo;
|
||||
|
||||
/**
|
||||
* @brief SD detection on its memory slot
|
||||
*/
|
||||
#define SD_PRESENT ((uint8_t)0x01)
|
||||
#define SD_NOT_PRESENT ((uint8_t)0x00)
|
||||
|
||||
// void SD_DeInit(void);
|
||||
SD_Error SD_Init(void);
|
||||
SDTransferState SD_GetStatus(void);
|
||||
uint8_t SD_Detect(void);
|
||||
SD_Error SD_PowerOFF(void);
|
||||
// SD_Error SD_GetCardStatus(SD_CardStatus *cardstatus);
|
||||
SD_Error SD_ReadBlock(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize);
|
||||
SD_Error SD_ReadMultiBlocks(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks);
|
||||
// SD_Error SD_ReadMultiBlocksFIXED(uint8_t *readbuff, uint32_t ReadAddr, uint32_t BlockSize, uint32_t NumberOfBlocks);
|
||||
SD_Error SD_WriteBlock(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize);
|
||||
SD_Error SD_WriteMultiBlocks(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize, uint32_t NumberOfBlocks);
|
||||
// SD_Error SD_WriteMultiBlocksFIXED(uint8_t *writebuff, uint32_t WriteAddr, uint32_t BlockSize, uint32_t NumberOfBlocks);
|
||||
SDTransferState SD_GetTransferState(void);
|
||||
// SD_Error SD_Erase(uint32_t startaddr, uint32_t endaddr);
|
||||
// SD_Error SD_SendSDStatus(uint32_t *psdstatus);
|
||||
SD_Error SD_WaitReadOperation(uint32_t timeout);
|
||||
SD_Error SD_WaitWriteOperation(uint32_t timeout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
extern SD_CardInfo SDCardInfo;
|
||||
|
||||
#endif // _SDIO_SD_H_
|
||||
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef _SDIO_SD_H_
|
||||
#define _SDIO_SD_H_
|
||||
|
||||
#include "board.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
typedef enum
|
||||
{
|
||||
/**
|
||||
* @brief SDIO specific error defines
|
||||
*/
|
||||
SD_CMD_CRC_FAIL = (1), /*!< Command response received (but CRC check failed) */
|
||||
SD_DATA_CRC_FAIL = (2), /*!< Data bock sent/received (CRC check Failed) */
|
||||
SD_CMD_RSP_TIMEOUT = (3), /*!< Command response timeout */
|
||||
SD_DATA_TIMEOUT = (4), /*!< Data time out */
|
||||
SD_TX_UNDERRUN = (5), /*!< Transmit FIFO under-run */
|
||||
SD_RX_OVERRUN = (6), /*!< Receive FIFO over-run */
|
||||
SD_START_BIT_ERR = (7), /*!< Start bit not detected on all data signals in widE bus mode */
|
||||
SD_CMD_OUT_OF_RANGE = (8), /*!< CMD's argument was out of range.*/
|
||||
SD_ADDR_MISALIGNED = (9), /*!< Misaligned address */
|
||||
SD_BLOCK_LEN_ERR = (10), /*!< Transferred block length is not allowed for the card or the number of transferred bytes does not match the block length */
|
||||
SD_ERASE_SEQ_ERR = (11), /*!< An error in the sequence of erase command occurs.*/
|
||||
SD_BAD_ERASE_PARAM = (12), /*!< An Invalid selection for erase groups */
|
||||
SD_WRITE_PROT_VIOLATION = (13), /*!< Attempt to program a write protect block */
|
||||
SD_LOCK_UNLOCK_FAILED = (14), /*!< Sequence or password error has been detected in unlock command or if there was an attempt to access a locked card */
|
||||
SD_COM_CRC_FAILED = (15), /*!< CRC check of the previous command failed */
|
||||
SD_ILLEGAL_CMD = (16), /*!< Command is not legal for the card state */
|
||||
SD_CARD_ECC_FAILED = (17), /*!< Card internal ECC was applied but failed to correct the data */
|
||||
SD_CC_ERROR = (18), /*!< Internal card controller error */
|
||||
SD_GENERAL_UNKNOWN_ERROR = (19), /*!< General or Unknown error */
|
||||
SD_STREAM_READ_UNDERRUN = (20), /*!< The card could not sustain data transfer in stream read operation. */
|
||||
SD_STREAM_WRITE_OVERRUN = (21), /*!< The card could not sustain data programming in stream mode */
|
||||
SD_CID_CSD_OVERWRITE = (22), /*!< CID/CSD overwrite error */
|
||||
SD_WP_ERASE_SKIP = (23), /*!< only partial address space was erased */
|
||||
SD_CARD_ECC_DISABLED = (24), /*!< Command has been executed without using internal ECC */
|
||||
SD_ERASE_RESET = (25), /*!< Erase sequence was cleared before executing because an out of erase sequence command was received */
|
||||
SD_AKE_SEQ_ERROR = (26), /*!< Error in sequence of authentication. */
|
||||
SD_INVALID_VOLTRANGE = (27),
|
||||
SD_ADDR_OUT_OF_RANGE = (28),
|
||||
SD_SWITCH_ERROR = (29),
|
||||
SD_SDIO_DISABLED = (30),
|
||||
SD_SDIO_FUNCTION_BUSY = (31),
|
||||
SD_SDIO_FUNCTION_FAILED = (32),
|
||||
SD_SDIO_UNKNOWN_FUNCTION = (33),
|
||||
|
||||
/**
|
||||
* @brief Standard error defines
|
||||
*/
|
||||
SD_INTERNAL_ERROR,
|
||||
SD_NOT_CONFIGURED,
|
||||
SD_REQUEST_PENDING,
|
||||
SD_REQUEST_NOT_APPLICABLE,
|
||||
SD_INVALID_PARAMETER,
|
||||
SD_UNSUPPORTED_FEATURE,
|
||||
SD_UNSUPPORTED_HW,
|
||||
SD_ERROR,
|
||||
SD_OK = 0
|
||||
} SD_Error;
|
||||
|
||||
/**
|
||||
* @brief SDIO Transfer state
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SD_TRANSFER_OK = 0,
|
||||
SD_TRANSFER_BUSY = 1,
|
||||
SD_TRANSFER_ERROR
|
||||
} SDTransferState;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Card Specific Data: CSD Register
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint8_t CSDStruct; /*!< CSD structure */
|
||||
__IO uint8_t SysSpecVersion; /*!< System specification version */
|
||||
__IO uint8_t Reserved1; /*!< Reserved */
|
||||
__IO uint8_t TAAC; /*!< Data read access-time 1 */
|
||||
__IO uint8_t NSAC; /*!< Data read access-time 2 in CLK cycles */
|
||||
__IO uint8_t MaxBusClkFrec; /*!< Max. bus clock frequency */
|
||||
__IO uint16_t CardComdClasses; /*!< Card command classes */
|
||||
__IO uint8_t RdBlockLen; /*!< Max. read data block length */
|
||||
__IO uint8_t PartBlockRead; /*!< Partial blocks for read allowed */
|
||||
__IO uint8_t WrBlockMisalign; /*!< Write block misalignment */
|
||||
__IO uint8_t RdBlockMisalign; /*!< Read block misalignment */
|
||||
__IO uint8_t DSRImpl; /*!< DSR implemented */
|
||||
__IO uint8_t Reserved2; /*!< Reserved */
|
||||
__IO uint32_t DeviceSize; /*!< Device Size */
|
||||
__IO uint8_t MaxRdCurrentVDDMin; /*!< Max. read current @ VDD min */
|
||||
__IO uint8_t MaxRdCurrentVDDMax; /*!< Max. read current @ VDD max */
|
||||
__IO uint8_t MaxWrCurrentVDDMin; /*!< Max. write current @ VDD min */
|
||||
__IO uint8_t MaxWrCurrentVDDMax; /*!< Max. write current @ VDD max */
|
||||
__IO uint8_t DeviceSizeMul; /*!< Device size multiplier */
|
||||
__IO uint8_t EraseGrSize; /*!< Erase group size */
|
||||
__IO uint8_t EraseGrMul; /*!< Erase group size multiplier */
|
||||
__IO uint8_t WrProtectGrSize; /*!< Write protect group size */
|
||||
__IO uint8_t WrProtectGrEnable; /*!< Write protect group enable */
|
||||
__IO uint8_t ManDeflECC; /*!< Manufacturer default ECC */
|
||||
__IO uint8_t WrSpeedFact; /*!< Write speed factor */
|
||||
__IO uint8_t MaxWrBlockLen; /*!< Max. write data block length */
|
||||
__IO uint8_t WriteBlockPaPartial; /*!< Partial blocks for write allowed */
|
||||
__IO uint8_t Reserved3; /*!< Reserded */
|
||||
__IO uint8_t ContentProtectAppli; /*!< Content protection application */
|
||||
__IO uint8_t FileFormatGrouop; /*!< File format group */
|
||||
__IO uint8_t CopyFlag; /*!< Copy flag (OTP) */
|
||||
__IO uint8_t PermWrProtect; /*!< Permanent write protection */
|
||||
__IO uint8_t TempWrProtect; /*!< Temporary write protection */
|
||||
__IO uint8_t FileFormat; /*!< File Format */
|
||||
__IO uint8_t ECC; /*!< ECC code */
|
||||
__IO uint8_t CSD_CRC; /*!< CSD CRC */
|
||||
__IO uint8_t Reserved4; /*!< always 1*/
|
||||
} SD_CSD;
|
||||
|
||||
/**
|
||||
* @brief Card Identification Data: CID Register
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
__IO uint8_t ManufacturerID; /*!< ManufacturerID */
|
||||
__IO uint16_t OEM_AppliID; /*!< OEM/Application ID */
|
||||
__IO uint32_t ProdName1; /*!< Product Name part1 */
|
||||
__IO uint8_t ProdName2; /*!< Product Name part2*/
|
||||
__IO uint8_t ProdRev; /*!< Product Revision */
|
||||
__IO uint32_t ProdSN; /*!< Product Serial Number */
|
||||
__IO uint8_t Reserved1; /*!< Reserved1 */
|
||||
__IO uint16_t ManufactDate; /*!< Manufacturing Date */
|
||||
__IO uint8_t CID_CRC; /*!< CID CRC */
|
||||
__IO uint8_t Reserved2; /*!< always 1 */
|
||||
} SD_CID;
|
||||
|
||||
/**
|
||||
* @brief SD Card Status
|
||||
*/
|
||||
// typedef struct
|
||||
// {
|
||||
// __IO uint8_t DAT_BUS_WIDTH;
|
||||
// __IO uint8_t SECURED_MODE;
|
||||
// __IO uint16_t SD_CARD_TYPE;
|
||||
// __IO uint32_t SIZE_OF_PROTECTED_AREA;
|
||||
// __IO uint8_t SPEED_CLASS;
|
||||
// __IO uint8_t PERFORMANCE_MOVE;
|
||||
// __IO uint8_t AU_SIZE;
|
||||
// __IO uint16_t ERASE_SIZE;
|
||||
// __IO uint8_t ERASE_TIMEOUT;
|
||||
// __IO uint8_t ERASE_OFFSET;
|
||||
// } SD_CardStatus;
|
||||
|
||||
|
||||
/**
|
||||
* @brief SD Card information
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
SD_CSD SD_csd;
|
||||
SD_CID SD_cid;
|
||||
uint64_t CardCapacity; /*!< Card Capacity */
|
||||
uint32_t CardBlockSize; /*!< Card Block Size */
|
||||
uint16_t RCA;
|
||||
uint8_t CardType;
|
||||
} SD_CardInfo;
|
||||
|
||||
/**
|
||||
* @brief SD detection on its memory slot
|
||||
*/
|
||||
#define SD_PRESENT ((uint8_t)0x01)
|
||||
#define SD_NOT_PRESENT ((uint8_t)0x00)
|
||||
|
||||
// void SD_DeInit(void);
|
||||
SD_Error SD_Init(void);
|
||||
SDTransferState SD_GetStatus(void);
|
||||
uint8_t SD_Detect(void);
|
||||
SD_Error SD_PowerOFF(void);
|
||||
// SD_Error SD_GetCardStatus(SD_CardStatus *cardstatus);
|
||||
SD_Error SD_ReadBlock(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize);
|
||||
SD_Error SD_ReadMultiBlocks(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks);
|
||||
// SD_Error SD_ReadMultiBlocksFIXED(uint8_t *readbuff, uint32_t ReadAddr, uint32_t BlockSize, uint32_t NumberOfBlocks);
|
||||
SD_Error SD_WriteBlock(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize);
|
||||
SD_Error SD_WriteMultiBlocks(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize, uint32_t NumberOfBlocks);
|
||||
// SD_Error SD_WriteMultiBlocksFIXED(uint8_t *writebuff, uint32_t WriteAddr, uint32_t BlockSize, uint32_t NumberOfBlocks);
|
||||
SDTransferState SD_GetTransferState(void);
|
||||
// SD_Error SD_Erase(uint32_t startaddr, uint32_t endaddr);
|
||||
// SD_Error SD_SendSDStatus(uint32_t *psdstatus);
|
||||
SD_Error SD_WaitReadOperation(uint32_t timeout);
|
||||
SD_Error SD_WaitWriteOperation(uint32_t timeout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
extern SD_CardInfo SDCardInfo;
|
||||
|
||||
#endif // _SDIO_SD_H_
|
||||
|
||||
|
||||
@@ -1,466 +1,466 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 "board.h"
|
||||
|
||||
#define SDRAM_MEMORY_WIDTH FMC_SDMemory_Width_16b
|
||||
|
||||
#define SDRAM_CAS_LATENCY FMC_CAS_Latency_3
|
||||
|
||||
#define SDCLOCK_PERIOD FMC_SDClock_Period_2
|
||||
|
||||
#define SDRAM_TIMEOUT ((uint32_t)0xFFFF)
|
||||
|
||||
/**
|
||||
* @brief FMC SDRAM Mode definition register defines
|
||||
*/
|
||||
#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
|
||||
#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
|
||||
#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
|
||||
#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004)
|
||||
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
|
||||
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
|
||||
#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
|
||||
#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
|
||||
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
|
||||
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
|
||||
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
|
||||
|
||||
/**
|
||||
* @brief FMC SDRAM Memory Read Burst feature
|
||||
*/
|
||||
#define SDRAM_READBURST FMC_Read_Burst_Disable
|
||||
|
||||
static void __Delay(__IO uint32_t nCount)
|
||||
{
|
||||
__IO uint32_t index = 0;
|
||||
for(index = (100000 * nCount); index != 0; index--)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures all SDRAM memory I/Os pins.
|
||||
* @param None.
|
||||
* @retval None.
|
||||
*/
|
||||
void SDRAM_GPIOConfig(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
/* Enable GPIOs clock */
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD |
|
||||
RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOG|RCC_AHB1Periph_GPIOH, ENABLE);
|
||||
|
||||
/*-- GPIOs Configuration -----------------------------------------------------*/
|
||||
/*
|
||||
+-------------------+--------------------+--------------------+--------------------+
|
||||
+ SDRAM pins assignment +
|
||||
+-------------------+--------------------+--------------------+--------------------+
|
||||
| PD0 <-> FMC_D2 | PE0 <-> FMC_NBL0 | PF0 <-> FMC_A0 | PG0 <-> FMC_A10 |
|
||||
| PD1 <-> FMC_D3 | PE1 <-> FMC_NBL1 | PF1 <-> FMC_A1 | PG1 <-> FMC_A11 |
|
||||
| PD8 <-> FMC_D13 | PE7 <-> FMC_D4 | PF2 <-> FMC_A2 | PG8 <-> FMC_SDCLK |
|
||||
| PD9 <-> FMC_D14 | PE8 <-> FMC_D5 | PF3 <-> FMC_A3 | PG15 <-> FMC_NCAS |
|
||||
| PD10 <-> FMC_D15 | PE9 <-> FMC_D6 | PF4 <-> FMC_A4 |--------------------+
|
||||
| PD14 <-> FMC_D0 | PE10 <-> FMC_D7 | PF5 <-> FMC_A5 |
|
||||
| PD15 <-> FMC_D1 | PE11 <-> FMC_D8 | PF11 <-> FMC_NRAS |
|
||||
+-------------------| PE12 <-> FMC_D9 | PF12 <-> FMC_A6 |
|
||||
| PE13 <-> FMC_D10 | PF13 <-> FMC_A7 |
|
||||
| PE14 <-> FMC_D11 | PF14 <-> FMC_A8 |
|
||||
| PE15 <-> FMC_D12 | PF15 <-> FMC_A9 |
|
||||
+-------------------+--------------------+--------------------+
|
||||
| PB5 <-> FMC_SDCKE1|
|
||||
| PB6 <-> FMC_SDNE1 |
|
||||
| PH5 <-> FMC_SDNWE |///////
|
||||
+-------------------+
|
||||
|
||||
*/
|
||||
|
||||
/* Common GPIO configuration */
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
|
||||
/* GPIOB configuration */
|
||||
GPIO_PinAFConfig(GPIOB, GPIO_PinSource5 , GPIO_AF_FMC);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 ;
|
||||
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
|
||||
/* GPIOC configuration */
|
||||
GPIO_PinAFConfig(GPIOH, GPIO_PinSource5 , GPIO_AF_FMC);
|
||||
|
||||
GPIO_PinAFConfig(GPIOH, GPIO_PinSource6 , GPIO_AF_FMC);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;
|
||||
|
||||
GPIO_Init(GPIOH, &GPIO_InitStructure);
|
||||
|
||||
/* GPIOD configuration */
|
||||
GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FMC);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 |
|
||||
GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 |
|
||||
GPIO_Pin_15;
|
||||
|
||||
GPIO_Init(GPIOD, &GPIO_InitStructure);
|
||||
|
||||
/* GPIOE configuration */
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource0 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource1 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource7 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource8 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource9 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource10 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource11 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource12 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource13 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource14 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource15 , GPIO_AF_FMC);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_7 |
|
||||
GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
|
||||
GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 |
|
||||
GPIO_Pin_14 | GPIO_Pin_15;
|
||||
|
||||
GPIO_Init(GPIOE, &GPIO_InitStructure);
|
||||
|
||||
/* GPIOF configuration */
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource0 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource1 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource2 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource3 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource4 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource5 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource11 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource12 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource13 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource14 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource15 , GPIO_AF_FMC);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 |
|
||||
GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 |
|
||||
GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 |
|
||||
GPIO_Pin_14 | GPIO_Pin_15;
|
||||
|
||||
GPIO_Init(GPIOF, &GPIO_InitStructure);
|
||||
|
||||
/* GPIOG configuration */
|
||||
GPIO_PinAFConfig(GPIOG, GPIO_PinSource0 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOG, GPIO_PinSource1 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOG, GPIO_PinSource4 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOG, GPIO_PinSource5 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOG, GPIO_PinSource8 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOG, GPIO_PinSource15 , GPIO_AF_FMC);
|
||||
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 |
|
||||
GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_15;
|
||||
|
||||
GPIO_Init(GPIOG, &GPIO_InitStructure);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Executes the SDRAM memory initialization sequence.
|
||||
* @param None.
|
||||
* @retval None.
|
||||
*/
|
||||
void SDRAM_InitSequence(void)
|
||||
{
|
||||
FMC_SDRAMCommandTypeDef FMC_SDRAMCommandStructure;
|
||||
uint32_t tmpr = 0;
|
||||
uint32_t timeout = SDRAM_TIMEOUT;
|
||||
|
||||
/* Step 3 --------------------------------------------------------------------*/
|
||||
/* Configure a clock configuration enable command */
|
||||
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_CLK_Enabled;
|
||||
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
|
||||
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
|
||||
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
while((FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) && (timeout > 0))
|
||||
{
|
||||
timeout--;
|
||||
}
|
||||
/* Send the command */
|
||||
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
|
||||
|
||||
/* Step 4 --------------------------------------------------------------------*/
|
||||
/* Insert 100 ms delay */
|
||||
__Delay(10);
|
||||
|
||||
/* Step 5 --------------------------------------------------------------------*/
|
||||
/* Configure a PALL (precharge all) command */
|
||||
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_PALL;
|
||||
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
|
||||
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
|
||||
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
|
||||
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
timeout = SDRAM_TIMEOUT;
|
||||
while((FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) && (timeout > 0))
|
||||
{
|
||||
timeout--;
|
||||
}
|
||||
/* Send the command */
|
||||
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
|
||||
|
||||
/* Step 6 --------------------------------------------------------------------*/
|
||||
/* Configure a Auto-Refresh command */
|
||||
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_AutoRefresh;
|
||||
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
|
||||
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 8;
|
||||
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
|
||||
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
timeout = SDRAM_TIMEOUT;
|
||||
while((FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) && (timeout > 0))
|
||||
{
|
||||
timeout--;
|
||||
}
|
||||
/* Send the command */
|
||||
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
|
||||
|
||||
/* Step 7 --------------------------------------------------------------------*/
|
||||
/* Program the external memory mode register */
|
||||
tmpr = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 |
|
||||
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
|
||||
SDRAM_MODEREG_CAS_LATENCY_3 |
|
||||
SDRAM_MODEREG_OPERATING_MODE_STANDARD |
|
||||
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
|
||||
|
||||
/* Configure a load Mode register command*/
|
||||
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_LoadMode;
|
||||
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
|
||||
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
|
||||
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = tmpr;
|
||||
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
timeout = SDRAM_TIMEOUT;
|
||||
while((FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) && (timeout > 0))
|
||||
{
|
||||
timeout--;
|
||||
}
|
||||
/* Send the command */
|
||||
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
|
||||
|
||||
/* Step 8 --------------------------------------------------------------------*/
|
||||
|
||||
/* Set the refresh rate counter */
|
||||
/* (15.62 us x Freq) - 20 */
|
||||
/* Set the device refresh counter */
|
||||
FMC_SetRefreshCount(1385);
|
||||
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
timeout = SDRAM_TIMEOUT;
|
||||
while((FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) && (timeout > 0))
|
||||
{
|
||||
timeout--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Executes the SDRAM memory initialization sequence.
|
||||
* @param None.
|
||||
* @retval None.
|
||||
*/
|
||||
void SDRAMTest_InitSequence(void)
|
||||
{
|
||||
FMC_SDRAMCommandTypeDef FMC_SDRAMCommandStructure;
|
||||
uint32_t tmpr = 0;
|
||||
|
||||
/* Step 3 --------------------------------------------------------------------*/
|
||||
/* Configure a clock configuration enable command */
|
||||
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_CLK_Enabled;
|
||||
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2;
|
||||
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
|
||||
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET)
|
||||
{
|
||||
}
|
||||
/* Send the command */
|
||||
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
|
||||
|
||||
/* Step 4 --------------------------------------------------------------------*/
|
||||
/* Insert 100 ms delay */
|
||||
__Delay(10);
|
||||
|
||||
/* Step 5 --------------------------------------------------------------------*/
|
||||
/* Configure a PALL (precharge all) command */
|
||||
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_PALL;
|
||||
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2;
|
||||
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
|
||||
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET)
|
||||
{
|
||||
}
|
||||
/* Send the command */
|
||||
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
|
||||
|
||||
/* Step 6 --------------------------------------------------------------------*/
|
||||
/* Configure a Auto-Refresh command */
|
||||
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_AutoRefresh;
|
||||
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2;
|
||||
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 4;
|
||||
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET)
|
||||
{
|
||||
}
|
||||
/* Send the first command */
|
||||
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
|
||||
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET)
|
||||
{
|
||||
}
|
||||
/* Send the second command */
|
||||
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
|
||||
|
||||
/* Step 7 --------------------------------------------------------------------*/
|
||||
/* Program the external memory mode register */
|
||||
tmpr = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2 |
|
||||
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
|
||||
SDRAM_MODEREG_CAS_LATENCY_3 |
|
||||
SDRAM_MODEREG_OPERATING_MODE_STANDARD |
|
||||
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
|
||||
|
||||
/* Configure a load Mode register command*/
|
||||
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_LoadMode;
|
||||
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2;
|
||||
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
|
||||
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = tmpr;
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET)
|
||||
{
|
||||
}
|
||||
/* Send the command */
|
||||
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
|
||||
|
||||
/* Step 8 --------------------------------------------------------------------*/
|
||||
|
||||
/* Set the refresh rate counter */
|
||||
/* (15.62 us x Freq) - 20 */
|
||||
/* Set the device refresh counter */
|
||||
FMC_SetRefreshCount(1386);
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void SDRAM_Init(void)
|
||||
{
|
||||
FMC_SDRAMInitTypeDef FMC_SDRAMInitStructure;
|
||||
FMC_SDRAMTimingInitTypeDef FMC_SDRAMTimingInitStructure;
|
||||
|
||||
/* GPIO configuration for FMC SDRAM bank */
|
||||
SDRAM_GPIOConfig();
|
||||
|
||||
/* Enable FMC clock */
|
||||
RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FMC, ENABLE);
|
||||
|
||||
/* FMC Configuration ---------------------------------------------------------*/
|
||||
/* FMC SDRAM Bank configuration */
|
||||
/* Timing configuration for 90 Mhz of SD clock frequency (168Mhz/2) */
|
||||
/* TMRD: 2 Clock cycles */
|
||||
FMC_SDRAMTimingInitStructure.FMC_LoadToActiveDelay = 2;
|
||||
/* TXSR: min=70ns (7x11.11ns) */
|
||||
FMC_SDRAMTimingInitStructure.FMC_ExitSelfRefreshDelay = 7;
|
||||
/* TRAS: min=42ns (4x11.11ns) max=120k (ns) */
|
||||
FMC_SDRAMTimingInitStructure.FMC_SelfRefreshTime = 4;
|
||||
/* TRC: min=70 (7x11.11ns) */
|
||||
FMC_SDRAMTimingInitStructure.FMC_RowCycleDelay = 7;
|
||||
/* TWR: min=1+ 7ns (1+1x11.11ns) */
|
||||
FMC_SDRAMTimingInitStructure.FMC_WriteRecoveryTime = 2;
|
||||
/* TRP: 20ns => 2x11.11ns */
|
||||
FMC_SDRAMTimingInitStructure.FMC_RPDelay = 2;
|
||||
/* TRCD: 20ns => 2x11.11ns */
|
||||
FMC_SDRAMTimingInitStructure.FMC_RCDDelay = 2;
|
||||
|
||||
/* FMC SDRAM control configuration */
|
||||
FMC_SDRAMInitStructure.FMC_Bank = FMC_Bank2_SDRAM;
|
||||
/* Row addressing: [7:0] */
|
||||
FMC_SDRAMInitStructure.FMC_ColumnBitsNumber = FMC_ColumnBits_Number_8b;
|
||||
/* Column addressing: [11:0] */
|
||||
FMC_SDRAMInitStructure.FMC_RowBitsNumber = FMC_RowBits_Number_12b;
|
||||
FMC_SDRAMInitStructure.FMC_SDMemoryDataWidth = SDRAM_MEMORY_WIDTH;
|
||||
FMC_SDRAMInitStructure.FMC_InternalBankNumber = FMC_InternalBank_Number_4;
|
||||
FMC_SDRAMInitStructure.FMC_CASLatency = SDRAM_CAS_LATENCY;
|
||||
FMC_SDRAMInitStructure.FMC_WriteProtection = FMC_Write_Protection_Disable;
|
||||
FMC_SDRAMInitStructure.FMC_SDClockPeriod = SDCLOCK_PERIOD;
|
||||
FMC_SDRAMInitStructure.FMC_ReadBurst = SDRAM_READBURST;
|
||||
FMC_SDRAMInitStructure.FMC_ReadPipeDelay = FMC_ReadPipe_Delay_0;
|
||||
FMC_SDRAMInitStructure.FMC_SDRAMTimingStruct = &FMC_SDRAMTimingInitStructure;
|
||||
|
||||
/* FMC SDRAM bank initialization */
|
||||
FMC_SDRAMInit(&FMC_SDRAMInitStructure);
|
||||
|
||||
/* FMC SDRAM device initialization sequence */
|
||||
SDRAMTest_InitSequence();
|
||||
}
|
||||
|
||||
#if 0
|
||||
void SDRAM_WriteBuffer(uint32_t* pBuffer, uint32_t uwWriteAddress, uint32_t uwBufferSize)
|
||||
{
|
||||
__IO uint32_t write_pointer = (uint32_t)uwWriteAddress;
|
||||
|
||||
FMC_SDRAMWriteProtectionConfig(FMC_Bank1_SDRAM, DISABLE);
|
||||
|
||||
while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET)
|
||||
{
|
||||
}
|
||||
|
||||
for (; uwBufferSize != 0; uwBufferSize--)
|
||||
{
|
||||
|
||||
*(uint32_t *) (SDRAM_BANK_ADDR + write_pointer) = *pBuffer++;
|
||||
|
||||
write_pointer += 4;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SDRAM_ReadBuffer(uint32_t* pBuffer, uint32_t uwReadAddress, uint32_t uwBufferSize)
|
||||
{
|
||||
__IO uint32_t write_pointer = (uint32_t)uwReadAddress;
|
||||
|
||||
while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET)
|
||||
{
|
||||
}
|
||||
|
||||
for(; uwBufferSize != 0x00; uwBufferSize--)
|
||||
{
|
||||
*pBuffer++ = *(__IO uint32_t *)(SDRAM_BANK_ADDR + write_pointer );
|
||||
|
||||
write_pointer += 4;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 "board.h"
|
||||
|
||||
#define SDRAM_MEMORY_WIDTH FMC_SDMemory_Width_16b
|
||||
|
||||
#define SDRAM_CAS_LATENCY FMC_CAS_Latency_3
|
||||
|
||||
#define SDCLOCK_PERIOD FMC_SDClock_Period_2
|
||||
|
||||
#define SDRAM_TIMEOUT ((uint32_t)0xFFFF)
|
||||
|
||||
/**
|
||||
* @brief FMC SDRAM Mode definition register defines
|
||||
*/
|
||||
#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
|
||||
#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
|
||||
#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
|
||||
#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004)
|
||||
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
|
||||
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
|
||||
#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
|
||||
#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
|
||||
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
|
||||
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
|
||||
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
|
||||
|
||||
/**
|
||||
* @brief FMC SDRAM Memory Read Burst feature
|
||||
*/
|
||||
#define SDRAM_READBURST FMC_Read_Burst_Disable
|
||||
|
||||
static void __Delay(__IO uint32_t nCount)
|
||||
{
|
||||
__IO uint32_t index = 0;
|
||||
for(index = (100000 * nCount); index != 0; index--)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures all SDRAM memory I/Os pins.
|
||||
* @param None.
|
||||
* @retval None.
|
||||
*/
|
||||
void SDRAM_GPIOConfig(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
/* Enable GPIOs clock */
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD |
|
||||
RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOG|RCC_AHB1Periph_GPIOH, ENABLE);
|
||||
|
||||
/*-- GPIOs Configuration -----------------------------------------------------*/
|
||||
/*
|
||||
+-------------------+--------------------+--------------------+--------------------+
|
||||
+ SDRAM pins assignment +
|
||||
+-------------------+--------------------+--------------------+--------------------+
|
||||
| PD0 <-> FMC_D2 | PE0 <-> FMC_NBL0 | PF0 <-> FMC_A0 | PG0 <-> FMC_A10 |
|
||||
| PD1 <-> FMC_D3 | PE1 <-> FMC_NBL1 | PF1 <-> FMC_A1 | PG1 <-> FMC_A11 |
|
||||
| PD8 <-> FMC_D13 | PE7 <-> FMC_D4 | PF2 <-> FMC_A2 | PG8 <-> FMC_SDCLK |
|
||||
| PD9 <-> FMC_D14 | PE8 <-> FMC_D5 | PF3 <-> FMC_A3 | PG15 <-> FMC_NCAS |
|
||||
| PD10 <-> FMC_D15 | PE9 <-> FMC_D6 | PF4 <-> FMC_A4 |--------------------+
|
||||
| PD14 <-> FMC_D0 | PE10 <-> FMC_D7 | PF5 <-> FMC_A5 |
|
||||
| PD15 <-> FMC_D1 | PE11 <-> FMC_D8 | PF11 <-> FMC_NRAS |
|
||||
+-------------------| PE12 <-> FMC_D9 | PF12 <-> FMC_A6 |
|
||||
| PE13 <-> FMC_D10 | PF13 <-> FMC_A7 |
|
||||
| PE14 <-> FMC_D11 | PF14 <-> FMC_A8 |
|
||||
| PE15 <-> FMC_D12 | PF15 <-> FMC_A9 |
|
||||
+-------------------+--------------------+--------------------+
|
||||
| PB5 <-> FMC_SDCKE1|
|
||||
| PB6 <-> FMC_SDNE1 |
|
||||
| PH5 <-> FMC_SDNWE |///////
|
||||
+-------------------+
|
||||
|
||||
*/
|
||||
|
||||
/* Common GPIO configuration */
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
|
||||
/* GPIOB configuration */
|
||||
GPIO_PinAFConfig(GPIOB, GPIO_PinSource5 , GPIO_AF_FMC);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 ;
|
||||
|
||||
GPIO_Init(GPIOB, &GPIO_InitStructure);
|
||||
|
||||
/* GPIOC configuration */
|
||||
GPIO_PinAFConfig(GPIOH, GPIO_PinSource5 , GPIO_AF_FMC);
|
||||
|
||||
GPIO_PinAFConfig(GPIOH, GPIO_PinSource6 , GPIO_AF_FMC);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;
|
||||
|
||||
GPIO_Init(GPIOH, &GPIO_InitStructure);
|
||||
|
||||
/* GPIOD configuration */
|
||||
GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FMC);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 |
|
||||
GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 |
|
||||
GPIO_Pin_15;
|
||||
|
||||
GPIO_Init(GPIOD, &GPIO_InitStructure);
|
||||
|
||||
/* GPIOE configuration */
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource0 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource1 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource7 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource8 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource9 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource10 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource11 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource12 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource13 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource14 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOE, GPIO_PinSource15 , GPIO_AF_FMC);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_7 |
|
||||
GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
|
||||
GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 |
|
||||
GPIO_Pin_14 | GPIO_Pin_15;
|
||||
|
||||
GPIO_Init(GPIOE, &GPIO_InitStructure);
|
||||
|
||||
/* GPIOF configuration */
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource0 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource1 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource2 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource3 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource4 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource5 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource11 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource12 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource13 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource14 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOF, GPIO_PinSource15 , GPIO_AF_FMC);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 |
|
||||
GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 |
|
||||
GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 |
|
||||
GPIO_Pin_14 | GPIO_Pin_15;
|
||||
|
||||
GPIO_Init(GPIOF, &GPIO_InitStructure);
|
||||
|
||||
/* GPIOG configuration */
|
||||
GPIO_PinAFConfig(GPIOG, GPIO_PinSource0 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOG, GPIO_PinSource1 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOG, GPIO_PinSource4 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOG, GPIO_PinSource5 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOG, GPIO_PinSource8 , GPIO_AF_FMC);
|
||||
GPIO_PinAFConfig(GPIOG, GPIO_PinSource15 , GPIO_AF_FMC);
|
||||
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 |
|
||||
GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_15;
|
||||
|
||||
GPIO_Init(GPIOG, &GPIO_InitStructure);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Executes the SDRAM memory initialization sequence.
|
||||
* @param None.
|
||||
* @retval None.
|
||||
*/
|
||||
void SDRAM_InitSequence(void)
|
||||
{
|
||||
FMC_SDRAMCommandTypeDef FMC_SDRAMCommandStructure;
|
||||
uint32_t tmpr = 0;
|
||||
uint32_t timeout = SDRAM_TIMEOUT;
|
||||
|
||||
/* Step 3 --------------------------------------------------------------------*/
|
||||
/* Configure a clock configuration enable command */
|
||||
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_CLK_Enabled;
|
||||
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
|
||||
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
|
||||
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
while((FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) && (timeout > 0))
|
||||
{
|
||||
timeout--;
|
||||
}
|
||||
/* Send the command */
|
||||
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
|
||||
|
||||
/* Step 4 --------------------------------------------------------------------*/
|
||||
/* Insert 100 ms delay */
|
||||
__Delay(10);
|
||||
|
||||
/* Step 5 --------------------------------------------------------------------*/
|
||||
/* Configure a PALL (precharge all) command */
|
||||
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_PALL;
|
||||
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
|
||||
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
|
||||
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
|
||||
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
timeout = SDRAM_TIMEOUT;
|
||||
while((FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) && (timeout > 0))
|
||||
{
|
||||
timeout--;
|
||||
}
|
||||
/* Send the command */
|
||||
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
|
||||
|
||||
/* Step 6 --------------------------------------------------------------------*/
|
||||
/* Configure a Auto-Refresh command */
|
||||
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_AutoRefresh;
|
||||
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
|
||||
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 8;
|
||||
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
|
||||
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
timeout = SDRAM_TIMEOUT;
|
||||
while((FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) && (timeout > 0))
|
||||
{
|
||||
timeout--;
|
||||
}
|
||||
/* Send the command */
|
||||
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
|
||||
|
||||
/* Step 7 --------------------------------------------------------------------*/
|
||||
/* Program the external memory mode register */
|
||||
tmpr = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 |
|
||||
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
|
||||
SDRAM_MODEREG_CAS_LATENCY_3 |
|
||||
SDRAM_MODEREG_OPERATING_MODE_STANDARD |
|
||||
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
|
||||
|
||||
/* Configure a load Mode register command*/
|
||||
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_LoadMode;
|
||||
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank1;
|
||||
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
|
||||
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = tmpr;
|
||||
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
timeout = SDRAM_TIMEOUT;
|
||||
while((FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) && (timeout > 0))
|
||||
{
|
||||
timeout--;
|
||||
}
|
||||
/* Send the command */
|
||||
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
|
||||
|
||||
/* Step 8 --------------------------------------------------------------------*/
|
||||
|
||||
/* Set the refresh rate counter */
|
||||
/* (15.62 us x Freq) - 20 */
|
||||
/* Set the device refresh counter */
|
||||
FMC_SetRefreshCount(1385);
|
||||
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
timeout = SDRAM_TIMEOUT;
|
||||
while((FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET) && (timeout > 0))
|
||||
{
|
||||
timeout--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Executes the SDRAM memory initialization sequence.
|
||||
* @param None.
|
||||
* @retval None.
|
||||
*/
|
||||
void SDRAMTest_InitSequence(void)
|
||||
{
|
||||
FMC_SDRAMCommandTypeDef FMC_SDRAMCommandStructure;
|
||||
uint32_t tmpr = 0;
|
||||
|
||||
/* Step 3 --------------------------------------------------------------------*/
|
||||
/* Configure a clock configuration enable command */
|
||||
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_CLK_Enabled;
|
||||
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2;
|
||||
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
|
||||
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET)
|
||||
{
|
||||
}
|
||||
/* Send the command */
|
||||
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
|
||||
|
||||
/* Step 4 --------------------------------------------------------------------*/
|
||||
/* Insert 100 ms delay */
|
||||
__Delay(10);
|
||||
|
||||
/* Step 5 --------------------------------------------------------------------*/
|
||||
/* Configure a PALL (precharge all) command */
|
||||
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_PALL;
|
||||
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2;
|
||||
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
|
||||
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET)
|
||||
{
|
||||
}
|
||||
/* Send the command */
|
||||
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
|
||||
|
||||
/* Step 6 --------------------------------------------------------------------*/
|
||||
/* Configure a Auto-Refresh command */
|
||||
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_AutoRefresh;
|
||||
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2;
|
||||
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 4;
|
||||
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET)
|
||||
{
|
||||
}
|
||||
/* Send the first command */
|
||||
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
|
||||
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET)
|
||||
{
|
||||
}
|
||||
/* Send the second command */
|
||||
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
|
||||
|
||||
/* Step 7 --------------------------------------------------------------------*/
|
||||
/* Program the external memory mode register */
|
||||
tmpr = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2 |
|
||||
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
|
||||
SDRAM_MODEREG_CAS_LATENCY_3 |
|
||||
SDRAM_MODEREG_OPERATING_MODE_STANDARD |
|
||||
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
|
||||
|
||||
/* Configure a load Mode register command*/
|
||||
FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_LoadMode;
|
||||
FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2;
|
||||
FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
|
||||
FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = tmpr;
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET)
|
||||
{
|
||||
}
|
||||
/* Send the command */
|
||||
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);
|
||||
|
||||
/* Step 8 --------------------------------------------------------------------*/
|
||||
|
||||
/* Set the refresh rate counter */
|
||||
/* (15.62 us x Freq) - 20 */
|
||||
/* Set the device refresh counter */
|
||||
FMC_SetRefreshCount(1386);
|
||||
/* Wait until the SDRAM controller is ready */
|
||||
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void SDRAM_Init(void)
|
||||
{
|
||||
FMC_SDRAMInitTypeDef FMC_SDRAMInitStructure;
|
||||
FMC_SDRAMTimingInitTypeDef FMC_SDRAMTimingInitStructure;
|
||||
|
||||
/* GPIO configuration for FMC SDRAM bank */
|
||||
SDRAM_GPIOConfig();
|
||||
|
||||
/* Enable FMC clock */
|
||||
RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FMC, ENABLE);
|
||||
|
||||
/* FMC Configuration ---------------------------------------------------------*/
|
||||
/* FMC SDRAM Bank configuration */
|
||||
/* Timing configuration for 90 Mhz of SD clock frequency (168Mhz/2) */
|
||||
/* TMRD: 2 Clock cycles */
|
||||
FMC_SDRAMTimingInitStructure.FMC_LoadToActiveDelay = 2;
|
||||
/* TXSR: min=70ns (7x11.11ns) */
|
||||
FMC_SDRAMTimingInitStructure.FMC_ExitSelfRefreshDelay = 7;
|
||||
/* TRAS: min=42ns (4x11.11ns) max=120k (ns) */
|
||||
FMC_SDRAMTimingInitStructure.FMC_SelfRefreshTime = 4;
|
||||
/* TRC: min=70 (7x11.11ns) */
|
||||
FMC_SDRAMTimingInitStructure.FMC_RowCycleDelay = 7;
|
||||
/* TWR: min=1+ 7ns (1+1x11.11ns) */
|
||||
FMC_SDRAMTimingInitStructure.FMC_WriteRecoveryTime = 2;
|
||||
/* TRP: 20ns => 2x11.11ns */
|
||||
FMC_SDRAMTimingInitStructure.FMC_RPDelay = 2;
|
||||
/* TRCD: 20ns => 2x11.11ns */
|
||||
FMC_SDRAMTimingInitStructure.FMC_RCDDelay = 2;
|
||||
|
||||
/* FMC SDRAM control configuration */
|
||||
FMC_SDRAMInitStructure.FMC_Bank = FMC_Bank2_SDRAM;
|
||||
/* Row addressing: [7:0] */
|
||||
FMC_SDRAMInitStructure.FMC_ColumnBitsNumber = FMC_ColumnBits_Number_8b;
|
||||
/* Column addressing: [11:0] */
|
||||
FMC_SDRAMInitStructure.FMC_RowBitsNumber = FMC_RowBits_Number_12b;
|
||||
FMC_SDRAMInitStructure.FMC_SDMemoryDataWidth = SDRAM_MEMORY_WIDTH;
|
||||
FMC_SDRAMInitStructure.FMC_InternalBankNumber = FMC_InternalBank_Number_4;
|
||||
FMC_SDRAMInitStructure.FMC_CASLatency = SDRAM_CAS_LATENCY;
|
||||
FMC_SDRAMInitStructure.FMC_WriteProtection = FMC_Write_Protection_Disable;
|
||||
FMC_SDRAMInitStructure.FMC_SDClockPeriod = SDCLOCK_PERIOD;
|
||||
FMC_SDRAMInitStructure.FMC_ReadBurst = SDRAM_READBURST;
|
||||
FMC_SDRAMInitStructure.FMC_ReadPipeDelay = FMC_ReadPipe_Delay_0;
|
||||
FMC_SDRAMInitStructure.FMC_SDRAMTimingStruct = &FMC_SDRAMTimingInitStructure;
|
||||
|
||||
/* FMC SDRAM bank initialization */
|
||||
FMC_SDRAMInit(&FMC_SDRAMInitStructure);
|
||||
|
||||
/* FMC SDRAM device initialization sequence */
|
||||
SDRAMTest_InitSequence();
|
||||
}
|
||||
|
||||
#if 0
|
||||
void SDRAM_WriteBuffer(uint32_t* pBuffer, uint32_t uwWriteAddress, uint32_t uwBufferSize)
|
||||
{
|
||||
__IO uint32_t write_pointer = (uint32_t)uwWriteAddress;
|
||||
|
||||
FMC_SDRAMWriteProtectionConfig(FMC_Bank1_SDRAM, DISABLE);
|
||||
|
||||
while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET)
|
||||
{
|
||||
}
|
||||
|
||||
for (; uwBufferSize != 0; uwBufferSize--)
|
||||
{
|
||||
|
||||
*(uint32_t *) (SDRAM_BANK_ADDR + write_pointer) = *pBuffer++;
|
||||
|
||||
write_pointer += 4;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SDRAM_ReadBuffer(uint32_t* pBuffer, uint32_t uwReadAddress, uint32_t uwBufferSize)
|
||||
{
|
||||
__IO uint32_t write_pointer = (uint32_t)uwReadAddress;
|
||||
|
||||
while(FMC_GetFlagStatus(FMC_Bank1_SDRAM, FMC_FLAG_Busy) != RESET)
|
||||
{
|
||||
}
|
||||
|
||||
for(; uwBufferSize != 0x00; uwBufferSize--)
|
||||
{
|
||||
*pBuffer++ = *(__IO uint32_t *)(SDRAM_BANK_ADDR + write_pointer );
|
||||
|
||||
write_pointer += 4;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,232 +1,232 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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"
|
||||
|
||||
Fifo<uint8_t, TELEMETRY_FIFO_SIZE> telemetryNoDMAFifo;
|
||||
uint32_t telemetryErrors = 0;
|
||||
|
||||
#if defined(PCBX12S)
|
||||
DMAFifo<TELEMETRY_FIFO_SIZE> telemetryDMAFifo __DMA (TELEMETRY_DMA_Stream_RX);
|
||||
uint8_t telemetryFifoMode;
|
||||
#endif
|
||||
|
||||
void telemetryPortInit(uint32_t baudrate, uint8_t mode)
|
||||
{
|
||||
if (baudrate == 0) {
|
||||
USART_DeInit(TELEMETRY_USART);
|
||||
return;
|
||||
}
|
||||
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
NVIC_InitStructure.NVIC_IRQChannel = TELEMETRY_DMA_TX_Stream_IRQ;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /* Not used as 4 bits are used for the pre-emption priority. */;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
USART_InitTypeDef USART_InitStructure;
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
GPIO_PinAFConfig(TELEMETRY_GPIO, TELEMETRY_GPIO_PinSource_RX, TELEMETRY_GPIO_AF);
|
||||
GPIO_PinAFConfig(TELEMETRY_GPIO, TELEMETRY_GPIO_PinSource_TX, TELEMETRY_GPIO_AF);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = TELEMETRY_TX_GPIO_PIN | TELEMETRY_RX_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_Init(TELEMETRY_GPIO, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = TELEMETRY_DIR_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(TELEMETRY_DIR_GPIO, &GPIO_InitStructure);
|
||||
GPIO_ResetBits(TELEMETRY_DIR_GPIO, TELEMETRY_DIR_GPIO_PIN);
|
||||
|
||||
USART_InitStructure.USART_BaudRate = baudrate;
|
||||
if (mode & TELEMETRY_SERIAL_8E2) {
|
||||
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
|
||||
USART_InitStructure.USART_StopBits = USART_StopBits_2;
|
||||
USART_InitStructure.USART_Parity = USART_Parity_Even;
|
||||
}
|
||||
else {
|
||||
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
||||
USART_InitStructure.USART_StopBits = USART_StopBits_1;
|
||||
USART_InitStructure.USART_Parity = USART_Parity_No;
|
||||
}
|
||||
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
||||
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
|
||||
USART_Init(TELEMETRY_USART, &USART_InitStructure);
|
||||
|
||||
#if defined(PCBX12S)
|
||||
telemetryFifoMode = mode;
|
||||
|
||||
DMA_Cmd(TELEMETRY_DMA_Stream_RX, DISABLE);
|
||||
USART_DMACmd(TELEMETRY_USART, USART_DMAReq_Rx, DISABLE);
|
||||
DMA_DeInit(TELEMETRY_DMA_Stream_RX);
|
||||
|
||||
if (mode & TELEMETRY_SERIAL_WITHOUT_DMA) {
|
||||
USART_Cmd(TELEMETRY_USART, ENABLE);
|
||||
USART_ITConfig(TELEMETRY_USART, USART_IT_RXNE, ENABLE);
|
||||
NVIC_SetPriority(TELEMETRY_USART_IRQn, 6);
|
||||
NVIC_EnableIRQ(TELEMETRY_USART_IRQn);
|
||||
}
|
||||
else {
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
telemetryDMAFifo.clear();
|
||||
|
||||
USART_ITConfig(TELEMETRY_USART, USART_IT_RXNE, DISABLE);
|
||||
USART_ITConfig(TELEMETRY_USART, USART_IT_TXE, DISABLE);
|
||||
NVIC_SetPriority(TELEMETRY_USART_IRQn, 6);
|
||||
NVIC_EnableIRQ(TELEMETRY_USART_IRQn);
|
||||
|
||||
DMA_InitStructure.DMA_Channel = TELEMETRY_DMA_Channel_RX;
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&TELEMETRY_USART->DR);
|
||||
DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(telemetryDMAFifo.buffer());
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
|
||||
DMA_InitStructure.DMA_BufferSize = telemetryDMAFifo.size();
|
||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
|
||||
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
|
||||
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
||||
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
|
||||
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
DMA_Init(TELEMETRY_DMA_Stream_RX, &DMA_InitStructure);
|
||||
USART_DMACmd(TELEMETRY_USART, USART_DMAReq_Rx, ENABLE);
|
||||
USART_Cmd(TELEMETRY_USART, ENABLE);
|
||||
DMA_Cmd(TELEMETRY_DMA_Stream_RX, ENABLE);
|
||||
}
|
||||
#else
|
||||
USART_Cmd(TELEMETRY_USART, ENABLE);
|
||||
USART_ITConfig(TELEMETRY_USART, USART_IT_RXNE, ENABLE);
|
||||
NVIC_SetPriority(TELEMETRY_USART_IRQn, 6);
|
||||
NVIC_EnableIRQ(TELEMETRY_USART_IRQn);
|
||||
#endif
|
||||
}
|
||||
|
||||
void telemetryPortSetDirectionOutput()
|
||||
{
|
||||
TELEMETRY_DIR_GPIO->BSRRL = TELEMETRY_DIR_GPIO_PIN; // output enable
|
||||
TELEMETRY_USART->CR1 &= ~USART_CR1_RE; // turn off receiver
|
||||
}
|
||||
|
||||
void telemetryPortSetDirectionInput()
|
||||
{
|
||||
TELEMETRY_DIR_GPIO->BSRRH = TELEMETRY_DIR_GPIO_PIN; // output disable
|
||||
TELEMETRY_USART->CR1 |= USART_CR1_RE; // turn on receiver
|
||||
}
|
||||
|
||||
void sportSendBuffer(uint8_t * buffer, uint32_t count)
|
||||
{
|
||||
telemetryPortSetDirectionOutput();
|
||||
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
DMA_DeInit(TELEMETRY_DMA_Stream_TX);
|
||||
DMA_InitStructure.DMA_Channel = TELEMETRY_DMA_Channel_TX;
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&TELEMETRY_USART->DR);
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
|
||||
DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(buffer);
|
||||
DMA_InitStructure.DMA_BufferSize = count;
|
||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
||||
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
|
||||
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
||||
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
|
||||
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
DMA_Init(TELEMETRY_DMA_Stream_TX, &DMA_InitStructure);
|
||||
DMA_Cmd(TELEMETRY_DMA_Stream_TX, ENABLE);
|
||||
USART_DMACmd(TELEMETRY_USART, USART_DMAReq_Tx, ENABLE);
|
||||
DMA_ITConfig(TELEMETRY_DMA_Stream_TX, DMA_IT_TC, ENABLE);
|
||||
|
||||
// enable interrupt and set it's priority
|
||||
NVIC_EnableIRQ(TELEMETRY_DMA_TX_Stream_IRQ) ;
|
||||
NVIC_SetPriority(TELEMETRY_DMA_TX_Stream_IRQ, 7);
|
||||
}
|
||||
|
||||
extern "C" void TELEMETRY_DMA_TX_IRQHandler(void)
|
||||
{
|
||||
DEBUG_INTERRUPT(INT_TELEM_DMA);
|
||||
if (DMA_GetITStatus(TELEMETRY_DMA_Stream_TX, TELEMETRY_DMA_TX_FLAG_TC)) {
|
||||
DMA_ClearITPendingBit(TELEMETRY_DMA_Stream_TX, TELEMETRY_DMA_TX_FLAG_TC);
|
||||
TELEMETRY_USART->CR1 |= USART_CR1_TCIE;
|
||||
if (telemetryProtocol == PROTOCOL_FRSKY_SPORT) {
|
||||
outputTelemetryBufferSize = 0;
|
||||
outputTelemetryBufferTrigger = 0x7E;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE)
|
||||
extern "C" void TELEMETRY_USART_IRQHandler(void)
|
||||
{
|
||||
DEBUG_INTERRUPT(INT_TELEM_USART);
|
||||
uint32_t status = TELEMETRY_USART->SR;
|
||||
|
||||
if ((status & USART_SR_TC) && (TELEMETRY_USART->CR1 & USART_CR1_TCIE)) {
|
||||
TELEMETRY_USART->CR1 &= ~USART_CR1_TCIE;
|
||||
telemetryPortSetDirectionInput();
|
||||
while (status & (USART_FLAG_RXNE)) {
|
||||
status = TELEMETRY_USART->DR;
|
||||
status = TELEMETRY_USART->SR;
|
||||
}
|
||||
}
|
||||
|
||||
while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
|
||||
uint8_t data = TELEMETRY_USART->DR;
|
||||
if (status & USART_FLAG_ERRORS) {
|
||||
telemetryErrors++;
|
||||
}
|
||||
else {
|
||||
telemetryNoDMAFifo.push(data);
|
||||
#if defined(LUA)
|
||||
if (telemetryProtocol == PROTOCOL_FRSKY_SPORT) {
|
||||
static uint8_t prevdata;
|
||||
if (prevdata == 0x7E && outputTelemetryBufferSize > 0 && data == outputTelemetryBufferTrigger) {
|
||||
sportSendBuffer(outputTelemetryBuffer, outputTelemetryBufferSize);
|
||||
}
|
||||
prevdata = data;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
status = TELEMETRY_USART->SR;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO we should have telemetry in an higher layer, functions above should move to a sport_driver.cpp
|
||||
uint8_t telemetryGetByte(uint8_t * byte)
|
||||
{
|
||||
#if defined(PCBX12S)
|
||||
if (telemetryFifoMode & TELEMETRY_SERIAL_WITHOUT_DMA)
|
||||
return telemetryNoDMAFifo.pop(*byte);
|
||||
else
|
||||
return telemetryDMAFifo.pop(*byte);
|
||||
#else
|
||||
return telemetryNoDMAFifo.pop(*byte);
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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"
|
||||
|
||||
Fifo<uint8_t, TELEMETRY_FIFO_SIZE> telemetryNoDMAFifo;
|
||||
uint32_t telemetryErrors = 0;
|
||||
|
||||
#if defined(PCBX12S)
|
||||
DMAFifo<TELEMETRY_FIFO_SIZE> telemetryDMAFifo __DMA (TELEMETRY_DMA_Stream_RX);
|
||||
uint8_t telemetryFifoMode;
|
||||
#endif
|
||||
|
||||
void telemetryPortInit(uint32_t baudrate, uint8_t mode)
|
||||
{
|
||||
if (baudrate == 0) {
|
||||
USART_DeInit(TELEMETRY_USART);
|
||||
return;
|
||||
}
|
||||
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
NVIC_InitStructure.NVIC_IRQChannel = TELEMETRY_DMA_TX_Stream_IRQ;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /* Not used as 4 bits are used for the pre-emption priority. */;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
|
||||
USART_InitTypeDef USART_InitStructure;
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
GPIO_PinAFConfig(TELEMETRY_GPIO, TELEMETRY_GPIO_PinSource_RX, TELEMETRY_GPIO_AF);
|
||||
GPIO_PinAFConfig(TELEMETRY_GPIO, TELEMETRY_GPIO_PinSource_TX, TELEMETRY_GPIO_AF);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = TELEMETRY_TX_GPIO_PIN | TELEMETRY_RX_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_Init(TELEMETRY_GPIO, &GPIO_InitStructure);
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = TELEMETRY_DIR_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(TELEMETRY_DIR_GPIO, &GPIO_InitStructure);
|
||||
GPIO_ResetBits(TELEMETRY_DIR_GPIO, TELEMETRY_DIR_GPIO_PIN);
|
||||
|
||||
USART_InitStructure.USART_BaudRate = baudrate;
|
||||
if (mode & TELEMETRY_SERIAL_8E2) {
|
||||
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
|
||||
USART_InitStructure.USART_StopBits = USART_StopBits_2;
|
||||
USART_InitStructure.USART_Parity = USART_Parity_Even;
|
||||
}
|
||||
else {
|
||||
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
||||
USART_InitStructure.USART_StopBits = USART_StopBits_1;
|
||||
USART_InitStructure.USART_Parity = USART_Parity_No;
|
||||
}
|
||||
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
||||
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
|
||||
USART_Init(TELEMETRY_USART, &USART_InitStructure);
|
||||
|
||||
#if defined(PCBX12S)
|
||||
telemetryFifoMode = mode;
|
||||
|
||||
DMA_Cmd(TELEMETRY_DMA_Stream_RX, DISABLE);
|
||||
USART_DMACmd(TELEMETRY_USART, USART_DMAReq_Rx, DISABLE);
|
||||
DMA_DeInit(TELEMETRY_DMA_Stream_RX);
|
||||
|
||||
if (mode & TELEMETRY_SERIAL_WITHOUT_DMA) {
|
||||
USART_Cmd(TELEMETRY_USART, ENABLE);
|
||||
USART_ITConfig(TELEMETRY_USART, USART_IT_RXNE, ENABLE);
|
||||
NVIC_SetPriority(TELEMETRY_USART_IRQn, 6);
|
||||
NVIC_EnableIRQ(TELEMETRY_USART_IRQn);
|
||||
}
|
||||
else {
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
telemetryDMAFifo.clear();
|
||||
|
||||
USART_ITConfig(TELEMETRY_USART, USART_IT_RXNE, DISABLE);
|
||||
USART_ITConfig(TELEMETRY_USART, USART_IT_TXE, DISABLE);
|
||||
NVIC_SetPriority(TELEMETRY_USART_IRQn, 6);
|
||||
NVIC_EnableIRQ(TELEMETRY_USART_IRQn);
|
||||
|
||||
DMA_InitStructure.DMA_Channel = TELEMETRY_DMA_Channel_RX;
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&TELEMETRY_USART->DR);
|
||||
DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(telemetryDMAFifo.buffer());
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
|
||||
DMA_InitStructure.DMA_BufferSize = telemetryDMAFifo.size();
|
||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
|
||||
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
|
||||
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
||||
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
|
||||
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
DMA_Init(TELEMETRY_DMA_Stream_RX, &DMA_InitStructure);
|
||||
USART_DMACmd(TELEMETRY_USART, USART_DMAReq_Rx, ENABLE);
|
||||
USART_Cmd(TELEMETRY_USART, ENABLE);
|
||||
DMA_Cmd(TELEMETRY_DMA_Stream_RX, ENABLE);
|
||||
}
|
||||
#else
|
||||
USART_Cmd(TELEMETRY_USART, ENABLE);
|
||||
USART_ITConfig(TELEMETRY_USART, USART_IT_RXNE, ENABLE);
|
||||
NVIC_SetPriority(TELEMETRY_USART_IRQn, 6);
|
||||
NVIC_EnableIRQ(TELEMETRY_USART_IRQn);
|
||||
#endif
|
||||
}
|
||||
|
||||
void telemetryPortSetDirectionOutput()
|
||||
{
|
||||
TELEMETRY_DIR_GPIO->BSRRL = TELEMETRY_DIR_GPIO_PIN; // output enable
|
||||
TELEMETRY_USART->CR1 &= ~USART_CR1_RE; // turn off receiver
|
||||
}
|
||||
|
||||
void telemetryPortSetDirectionInput()
|
||||
{
|
||||
TELEMETRY_DIR_GPIO->BSRRH = TELEMETRY_DIR_GPIO_PIN; // output disable
|
||||
TELEMETRY_USART->CR1 |= USART_CR1_RE; // turn on receiver
|
||||
}
|
||||
|
||||
void sportSendBuffer(uint8_t * buffer, uint32_t count)
|
||||
{
|
||||
telemetryPortSetDirectionOutput();
|
||||
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
DMA_DeInit(TELEMETRY_DMA_Stream_TX);
|
||||
DMA_InitStructure.DMA_Channel = TELEMETRY_DMA_Channel_TX;
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&TELEMETRY_USART->DR);
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
|
||||
DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(buffer);
|
||||
DMA_InitStructure.DMA_BufferSize = count;
|
||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
||||
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
|
||||
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
||||
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
|
||||
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
DMA_Init(TELEMETRY_DMA_Stream_TX, &DMA_InitStructure);
|
||||
DMA_Cmd(TELEMETRY_DMA_Stream_TX, ENABLE);
|
||||
USART_DMACmd(TELEMETRY_USART, USART_DMAReq_Tx, ENABLE);
|
||||
DMA_ITConfig(TELEMETRY_DMA_Stream_TX, DMA_IT_TC, ENABLE);
|
||||
|
||||
// enable interrupt and set it's priority
|
||||
NVIC_EnableIRQ(TELEMETRY_DMA_TX_Stream_IRQ) ;
|
||||
NVIC_SetPriority(TELEMETRY_DMA_TX_Stream_IRQ, 7);
|
||||
}
|
||||
|
||||
extern "C" void TELEMETRY_DMA_TX_IRQHandler(void)
|
||||
{
|
||||
DEBUG_INTERRUPT(INT_TELEM_DMA);
|
||||
if (DMA_GetITStatus(TELEMETRY_DMA_Stream_TX, TELEMETRY_DMA_TX_FLAG_TC)) {
|
||||
DMA_ClearITPendingBit(TELEMETRY_DMA_Stream_TX, TELEMETRY_DMA_TX_FLAG_TC);
|
||||
TELEMETRY_USART->CR1 |= USART_CR1_TCIE;
|
||||
if (telemetryProtocol == PROTOCOL_FRSKY_SPORT) {
|
||||
outputTelemetryBufferSize = 0;
|
||||
outputTelemetryBufferTrigger = 0x7E;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE)
|
||||
extern "C" void TELEMETRY_USART_IRQHandler(void)
|
||||
{
|
||||
DEBUG_INTERRUPT(INT_TELEM_USART);
|
||||
uint32_t status = TELEMETRY_USART->SR;
|
||||
|
||||
if ((status & USART_SR_TC) && (TELEMETRY_USART->CR1 & USART_CR1_TCIE)) {
|
||||
TELEMETRY_USART->CR1 &= ~USART_CR1_TCIE;
|
||||
telemetryPortSetDirectionInput();
|
||||
while (status & (USART_FLAG_RXNE)) {
|
||||
status = TELEMETRY_USART->DR;
|
||||
status = TELEMETRY_USART->SR;
|
||||
}
|
||||
}
|
||||
|
||||
while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
|
||||
uint8_t data = TELEMETRY_USART->DR;
|
||||
if (status & USART_FLAG_ERRORS) {
|
||||
telemetryErrors++;
|
||||
}
|
||||
else {
|
||||
telemetryNoDMAFifo.push(data);
|
||||
#if defined(LUA)
|
||||
if (telemetryProtocol == PROTOCOL_FRSKY_SPORT) {
|
||||
static uint8_t prevdata;
|
||||
if (prevdata == 0x7E && outputTelemetryBufferSize > 0 && data == outputTelemetryBufferTrigger) {
|
||||
sportSendBuffer(outputTelemetryBuffer, outputTelemetryBufferSize);
|
||||
}
|
||||
prevdata = data;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
status = TELEMETRY_USART->SR;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO we should have telemetry in an higher layer, functions above should move to a sport_driver.cpp
|
||||
uint8_t telemetryGetByte(uint8_t * byte)
|
||||
{
|
||||
#if defined(PCBX12S)
|
||||
if (telemetryFifoMode & TELEMETRY_SERIAL_WITHOUT_DMA)
|
||||
return telemetryNoDMAFifo.pop(*byte);
|
||||
else
|
||||
return telemetryDMAFifo.pop(*byte);
|
||||
#else
|
||||
return telemetryNoDMAFifo.pop(*byte);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,154 +1,154 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 trainerSendNextFrame();
|
||||
|
||||
void init_trainer_ppm()
|
||||
{
|
||||
GPIO_PinAFConfig(TRAINER_GPIO, TRAINER_OUT_GPIO_PinSource, TRAINER_GPIO_AF);
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = TRAINER_OUT_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(TRAINER_GPIO, &GPIO_InitStructure);
|
||||
|
||||
TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN;
|
||||
TRAINER_TIMER->PSC = TRAINER_TIMER_FREQ / 2000000 - 1; // 0.5uS
|
||||
TRAINER_TIMER->ARR = 45000;
|
||||
TRAINER_TIMER->CCR2 = GET_PPM_DELAY(TRAINER_MODULE)*2;
|
||||
TRAINER_TIMER->CCER = TIM_CCER_CC2E | (g_model.moduleData[TRAINER_MODULE].ppm.pulsePol ? 0 : TIM_CCER_CC2P);
|
||||
TRAINER_TIMER->CCMR1 = TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_0; // Force O/P high
|
||||
TRAINER_TIMER->BDTR = TIM_BDTR_MOE;
|
||||
TRAINER_TIMER->EGR = 1;
|
||||
TRAINER_TIMER->DIER |= TIM_DIER_UDE;
|
||||
TRAINER_TIMER->CCMR1 = TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2PE; // PWM mode 1
|
||||
TRAINER_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
|
||||
setupPulsesPPMTrainer();
|
||||
trainerSendNextFrame();
|
||||
|
||||
NVIC_EnableIRQ(TRAINER_DMA_IRQn);
|
||||
NVIC_SetPriority(TRAINER_DMA_IRQn, 7);
|
||||
NVIC_EnableIRQ(TRAINER_TIMER_IRQn);
|
||||
NVIC_SetPriority(TRAINER_TIMER_IRQn, 7);
|
||||
}
|
||||
|
||||
void stop_trainer_ppm()
|
||||
{
|
||||
NVIC_DisableIRQ(TRAINER_DMA_IRQn);
|
||||
NVIC_DisableIRQ(TRAINER_TIMER_IRQn);
|
||||
|
||||
TRAINER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
|
||||
TRAINER_TIMER->DIER = 0; // Stop Interrupt
|
||||
TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter
|
||||
}
|
||||
|
||||
void init_trainer_capture()
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = TRAINER_IN_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(TRAINER_GPIO, &GPIO_InitStructure);
|
||||
GPIO_PinAFConfig(TRAINER_GPIO, TRAINER_IN_GPIO_PinSource, TRAINER_GPIO_AF);
|
||||
|
||||
TRAINER_TIMER->ARR = 0xFFFF;
|
||||
TRAINER_TIMER->PSC = TRAINER_TIMER_FREQ / 2000000 - 1; // 0.5uS
|
||||
TRAINER_TIMER->CR2 = 0;
|
||||
TRAINER_TIMER->CCMR1 = TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_CC1S_0;
|
||||
TRAINER_TIMER->CCER = TIM_CCER_CC1E;
|
||||
TRAINER_TIMER->SR &= ~TIM_SR_CC1IF & ~TIM_SR_CC2IF & ~TIM_SR_UIF; // Clear flags
|
||||
TRAINER_TIMER->DIER |= TIM_DIER_CC1IE;
|
||||
TRAINER_TIMER->CR1 = TIM_CR1_CEN;
|
||||
|
||||
NVIC_EnableIRQ(TRAINER_TIMER_IRQn);
|
||||
NVIC_SetPriority(TRAINER_TIMER_IRQn, 7);
|
||||
}
|
||||
|
||||
void stop_trainer_capture()
|
||||
{
|
||||
NVIC_DisableIRQ(TRAINER_TIMER_IRQn); // Stop Interrupt
|
||||
|
||||
TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter
|
||||
TRAINER_TIMER->DIER = 0; // Stop Interrupt
|
||||
}
|
||||
|
||||
void trainerSendNextFrame()
|
||||
{
|
||||
TRAINER_TIMER->CCR2 = GET_PPM_DELAY(TRAINER_MODULE)*2;
|
||||
TRAINER_TIMER->CCER = TIM_CCER_CC2E | (g_model.moduleData[TRAINER_MODULE].ppm.pulsePol ? 0 : TIM_CCER_CC2P);
|
||||
TRAINER_TIMER->CCR1 = *(trainerPulsesData.ppm.ptr - 1) - 4000; // 2mS in advance
|
||||
|
||||
TRAINER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
|
||||
TRAINER_DMA_STREAM->CR |= TRAINER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
|
||||
TRAINER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&TRAINER_TIMER->ARR);
|
||||
TRAINER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(trainerPulsesData.ppm.pulses);
|
||||
TRAINER_DMA_STREAM->NDTR = trainerPulsesData.ppm.ptr - trainerPulsesData.ppm.pulses;
|
||||
TRAINER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
|
||||
}
|
||||
|
||||
extern "C" void TRAINER_DMA_IRQHandler()
|
||||
{
|
||||
if (!DMA_GetITStatus(TRAINER_DMA_STREAM, TRAINER_DMA_FLAG_TC))
|
||||
return;
|
||||
|
||||
DMA_ClearITPendingBit(TRAINER_DMA_STREAM, TRAINER_DMA_FLAG_TC);
|
||||
|
||||
TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag
|
||||
TRAINER_TIMER->DIER |= TIM_DIER_CC1IE; // Enable this interrupt
|
||||
}
|
||||
|
||||
extern "C" void TRAINER_TIMER_IRQHandler()
|
||||
{
|
||||
DEBUG_INTERRUPT(INT_TRAINER);
|
||||
|
||||
uint16_t capture = 0;
|
||||
bool doCapture = false;
|
||||
|
||||
// What mode? in or out?
|
||||
if ((TRAINER_TIMER->DIER & TIM_DIER_CC1IE) && (TRAINER_TIMER->SR & TIM_SR_CC1IF)) {
|
||||
// capture mode on trainer jack
|
||||
capture = TRAINER_TIMER->CCR1;
|
||||
if (TRAINER_CONNECTED() && currentTrainerMode == TRAINER_MODE_MASTER_TRAINER_JACK) {
|
||||
doCapture = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (doCapture) {
|
||||
captureTrainerPulses(capture);
|
||||
}
|
||||
|
||||
// PPM out compare interrupt
|
||||
if ((TRAINER_TIMER->DIER & TIM_DIER_CC1IE) && (TRAINER_TIMER->SR & TIM_SR_CC1IF)) {
|
||||
// compare interrupt
|
||||
TRAINER_TIMER->DIER &= ~TIM_DIER_CC1IE; // stop this interrupt
|
||||
TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag
|
||||
setupPulsesPPMTrainer();
|
||||
trainerSendNextFrame();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 trainerSendNextFrame();
|
||||
|
||||
void init_trainer_ppm()
|
||||
{
|
||||
GPIO_PinAFConfig(TRAINER_GPIO, TRAINER_OUT_GPIO_PinSource, TRAINER_GPIO_AF);
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_InitStructure.GPIO_Pin = TRAINER_OUT_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(TRAINER_GPIO, &GPIO_InitStructure);
|
||||
|
||||
TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN;
|
||||
TRAINER_TIMER->PSC = TRAINER_TIMER_FREQ / 2000000 - 1; // 0.5uS
|
||||
TRAINER_TIMER->ARR = 45000;
|
||||
TRAINER_TIMER->CCR2 = GET_PPM_DELAY(TRAINER_MODULE)*2;
|
||||
TRAINER_TIMER->CCER = TIM_CCER_CC2E | (g_model.moduleData[TRAINER_MODULE].ppm.pulsePol ? 0 : TIM_CCER_CC2P);
|
||||
TRAINER_TIMER->CCMR1 = TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_0; // Force O/P high
|
||||
TRAINER_TIMER->BDTR = TIM_BDTR_MOE;
|
||||
TRAINER_TIMER->EGR = 1;
|
||||
TRAINER_TIMER->DIER |= TIM_DIER_UDE;
|
||||
TRAINER_TIMER->CCMR1 = TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2PE; // PWM mode 1
|
||||
TRAINER_TIMER->CR1 |= TIM_CR1_CEN;
|
||||
|
||||
setupPulsesPPMTrainer();
|
||||
trainerSendNextFrame();
|
||||
|
||||
NVIC_EnableIRQ(TRAINER_DMA_IRQn);
|
||||
NVIC_SetPriority(TRAINER_DMA_IRQn, 7);
|
||||
NVIC_EnableIRQ(TRAINER_TIMER_IRQn);
|
||||
NVIC_SetPriority(TRAINER_TIMER_IRQn, 7);
|
||||
}
|
||||
|
||||
void stop_trainer_ppm()
|
||||
{
|
||||
NVIC_DisableIRQ(TRAINER_DMA_IRQn);
|
||||
NVIC_DisableIRQ(TRAINER_TIMER_IRQn);
|
||||
|
||||
TRAINER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
|
||||
TRAINER_TIMER->DIER = 0; // Stop Interrupt
|
||||
TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter
|
||||
}
|
||||
|
||||
void init_trainer_capture()
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
|
||||
GPIO_InitStructure.GPIO_Pin = TRAINER_IN_GPIO_PIN;
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||
GPIO_Init(TRAINER_GPIO, &GPIO_InitStructure);
|
||||
GPIO_PinAFConfig(TRAINER_GPIO, TRAINER_IN_GPIO_PinSource, TRAINER_GPIO_AF);
|
||||
|
||||
TRAINER_TIMER->ARR = 0xFFFF;
|
||||
TRAINER_TIMER->PSC = TRAINER_TIMER_FREQ / 2000000 - 1; // 0.5uS
|
||||
TRAINER_TIMER->CR2 = 0;
|
||||
TRAINER_TIMER->CCMR1 = TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_CC1S_0;
|
||||
TRAINER_TIMER->CCER = TIM_CCER_CC1E;
|
||||
TRAINER_TIMER->SR &= ~TIM_SR_CC1IF & ~TIM_SR_CC2IF & ~TIM_SR_UIF; // Clear flags
|
||||
TRAINER_TIMER->DIER |= TIM_DIER_CC1IE;
|
||||
TRAINER_TIMER->CR1 = TIM_CR1_CEN;
|
||||
|
||||
NVIC_EnableIRQ(TRAINER_TIMER_IRQn);
|
||||
NVIC_SetPriority(TRAINER_TIMER_IRQn, 7);
|
||||
}
|
||||
|
||||
void stop_trainer_capture()
|
||||
{
|
||||
NVIC_DisableIRQ(TRAINER_TIMER_IRQn); // Stop Interrupt
|
||||
|
||||
TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter
|
||||
TRAINER_TIMER->DIER = 0; // Stop Interrupt
|
||||
}
|
||||
|
||||
void trainerSendNextFrame()
|
||||
{
|
||||
TRAINER_TIMER->CCR2 = GET_PPM_DELAY(TRAINER_MODULE)*2;
|
||||
TRAINER_TIMER->CCER = TIM_CCER_CC2E | (g_model.moduleData[TRAINER_MODULE].ppm.pulsePol ? 0 : TIM_CCER_CC2P);
|
||||
TRAINER_TIMER->CCR1 = *(trainerPulsesData.ppm.ptr - 1) - 4000; // 2mS in advance
|
||||
|
||||
TRAINER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
|
||||
TRAINER_DMA_STREAM->CR |= TRAINER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
|
||||
TRAINER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&TRAINER_TIMER->ARR);
|
||||
TRAINER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(trainerPulsesData.ppm.pulses);
|
||||
TRAINER_DMA_STREAM->NDTR = trainerPulsesData.ppm.ptr - trainerPulsesData.ppm.pulses;
|
||||
TRAINER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
|
||||
}
|
||||
|
||||
extern "C" void TRAINER_DMA_IRQHandler()
|
||||
{
|
||||
if (!DMA_GetITStatus(TRAINER_DMA_STREAM, TRAINER_DMA_FLAG_TC))
|
||||
return;
|
||||
|
||||
DMA_ClearITPendingBit(TRAINER_DMA_STREAM, TRAINER_DMA_FLAG_TC);
|
||||
|
||||
TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag
|
||||
TRAINER_TIMER->DIER |= TIM_DIER_CC1IE; // Enable this interrupt
|
||||
}
|
||||
|
||||
extern "C" void TRAINER_TIMER_IRQHandler()
|
||||
{
|
||||
DEBUG_INTERRUPT(INT_TRAINER);
|
||||
|
||||
uint16_t capture = 0;
|
||||
bool doCapture = false;
|
||||
|
||||
// What mode? in or out?
|
||||
if ((TRAINER_TIMER->DIER & TIM_DIER_CC1IE) && (TRAINER_TIMER->SR & TIM_SR_CC1IF)) {
|
||||
// capture mode on trainer jack
|
||||
capture = TRAINER_TIMER->CCR1;
|
||||
if (TRAINER_CONNECTED() && currentTrainerMode == TRAINER_MODE_MASTER_TRAINER_JACK) {
|
||||
doCapture = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (doCapture) {
|
||||
captureTrainerPulses(capture);
|
||||
}
|
||||
|
||||
// PPM out compare interrupt
|
||||
if ((TRAINER_TIMER->DIER & TIM_DIER_CC1IE) && (TRAINER_TIMER->SR & TIM_SR_CC1IF)) {
|
||||
// compare interrupt
|
||||
TRAINER_TIMER->DIER &= ~TIM_DIER_CC1IE; // stop this interrupt
|
||||
TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag
|
||||
setupPulsesPPMTrainer();
|
||||
trainerSendNextFrame();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
MEGA2560 board
|
||||
|
||||
======================= DESCRIPTION =======================
|
||||
DIY radio wih :
|
||||
- Arduino MEGA2560 or compatible
|
||||
- Gruvin9x features (soft-off, SD-Card, RTC, haptic, voice, rotary encoders)
|
||||
- LCD 128x64 8 bits parallel mode
|
||||
MEGA2560 board
|
||||
|
||||
======================= DESCRIPTION =======================
|
||||
DIY radio wih :
|
||||
- Arduino MEGA2560 or compatible
|
||||
- Gruvin9x features (soft-off, SD-Card, RTC, haptic, voice, rotary encoders)
|
||||
- LCD 128x64 8 bits parallel mode
|
||||
- home made case
|
||||
+196
-196
@@ -1,196 +1,196 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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_
|
||||
|
||||
#include "../common/avr/board_avr.h"
|
||||
|
||||
// Board driver
|
||||
void boardInit(void);
|
||||
#define boardOff() pwrOff()
|
||||
|
||||
// Keys
|
||||
#define KEYS_GPIO_REG_MENU pinl
|
||||
#define KEYS_GPIO_PIN_MENU (1<<4)
|
||||
#define KEYS_GPIO_REG_EXIT pinl
|
||||
#define KEYS_GPIO_PIN_EXIT (1<<5)
|
||||
#define KEYS_GPIO_REG_RIGHT pinl
|
||||
#define KEYS_GPIO_PIN_RIGHT (1<<2)
|
||||
#define KEYS_GPIO_REG_LEFT pinl
|
||||
#define KEYS_GPIO_PIN_LEFT (1<<3)
|
||||
#define KEYS_GPIO_REG_UP pinl
|
||||
#define KEYS_GPIO_PIN_UP (1<<1)
|
||||
#define KEYS_GPIO_REG_DOWN pinl
|
||||
#define KEYS_GPIO_PIN_DOWN (1<<0)
|
||||
|
||||
// Trims
|
||||
#define TRIMS_GPIO_REG_LHL pinf
|
||||
#define TRIMS_GPIO_PIN_LHL (1<<7)
|
||||
#define TRIMS_GPIO_REG_LVD pinf
|
||||
#define TRIMS_GPIO_PIN_LVD (1<<5)
|
||||
#define TRIMS_GPIO_REG_RVU pinf
|
||||
#define TRIMS_GPIO_PIN_RVU (1<<2)
|
||||
#define TRIMS_GPIO_REG_RHL pinf
|
||||
#define TRIMS_GPIO_PIN_RHL (1<<1)
|
||||
#define TRIMS_GPIO_REG_LHR pinf
|
||||
#define TRIMS_GPIO_PIN_LHR (1<<6)
|
||||
#define TRIMS_GPIO_REG_LVU pinf
|
||||
#define TRIMS_GPIO_PIN_LVU (1<<4)
|
||||
#define TRIMS_GPIO_REG_RVD pinf
|
||||
#define TRIMS_GPIO_PIN_RVD (1<<3)
|
||||
#define TRIMS_GPIO_REG_RHR pinf
|
||||
#define TRIMS_GPIO_PIN_RHR (1<<0)
|
||||
|
||||
#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() ~PINH & (1<<INP_H_RF_Activated)
|
||||
#define JACK_PPM_OUT() PORTB &= ~(1<<OUT_B_SIM_CTL)
|
||||
#define JACK_PPM_IN() PORTB |= (1<<OUT_B_SIM_CTL)
|
||||
|
||||
// Backlight driver
|
||||
#define backlightEnable() PORTC |= (1<<OUT_C_LIGHT)
|
||||
#define backlightDisable() PORTC &= ~(1<<OUT_C_LIGHT)
|
||||
#define isBacklightEnabled() PORTC & (1<<OUT_C_LIGHT)
|
||||
#define BACKLIGHT_ENABLE() backlightEnable()
|
||||
#define BACKLIGHT_DISABLE() backlightDisable()
|
||||
|
||||
// SD driver
|
||||
#define BLOCK_SIZE 512 /* Block Size in Bytes */
|
||||
#define sdDone()
|
||||
#define SD_IS_HC() (0)
|
||||
#define SD_GET_SPEED() (0)
|
||||
#if !defined(SIMU)
|
||||
bool sdMounted(void);
|
||||
void sdMountPoll(void);
|
||||
void sdPoll10ms(void);
|
||||
#endif
|
||||
|
||||
// Switchs driver
|
||||
#define INP_C_ID2 1
|
||||
#define INP_C_ID1 0
|
||||
#define INP_D_AileDR 7
|
||||
#define INP_G_ThrCt 2
|
||||
#define INP_G_Gear 1
|
||||
#define INP_G_RuddDR 0
|
||||
#define INP_L_ElevDR 6
|
||||
#define INP_L_Trainer 7
|
||||
|
||||
// Servitudes driver
|
||||
#define INP_E_PPM_IN 7 //directly used
|
||||
#define INP_B_VoiceBuzy 7 //directly used
|
||||
#define OUT_B_PPM 6
|
||||
#define OUT_B_SIM_CTL 5
|
||||
#define I_O_B_UNUSED 4 //unused, was Buzzer
|
||||
#define INP_D_I2C_SCL 1
|
||||
#define INP_D_I2C_SDA 0
|
||||
#define OUT_E_VoiceData 3
|
||||
#define INP_E_TELEM_RX 1
|
||||
#define OUT_E_TELEM_TX 0
|
||||
#define OUT_G_VoiceClock 5
|
||||
#define INP_H_RF_Activated 6
|
||||
#define INP_H_DSC_Activated 5 //pwrCheck(), directly used
|
||||
#define INP_H_Hold_Power 4 //pwrCheck(), directly used
|
||||
#define OUT_H_SpeakerBuzzer 3
|
||||
#define OUT_H_VoiceReset 1
|
||||
#define OUT_H_HAPTIC 0
|
||||
|
||||
// Rotary encoders driver
|
||||
#define INP_E_ROT_ENC_1_A 4
|
||||
#define INP_E_ROT_ENC_1_B 5
|
||||
#define INP_D_ROT_ENC_2_A 2
|
||||
#define INP_D_ROT_ENC_2_B 3
|
||||
#define INP_J_ROT_ENC_1_PUSH 0
|
||||
#define INP_J_ROT_ENC_2_PUSH 1
|
||||
#define REA_DOWN() (~PINJ & (1<<INP_J_ROT_ENC_1_PUSH))
|
||||
#define REB_DOWN() (~PINJ & (1<<INP_J_ROT_ENC_2_PUSH))
|
||||
#define ROTENC_DOWN() (REA_DOWN() || REB_DOWN())
|
||||
#define ROTENC_DIV2 // rotary encoders resolution/2
|
||||
|
||||
// LCD driver
|
||||
#define PORTA_LCD_DAT PORTA
|
||||
#define PORTC_LCD_CTRL PORTC
|
||||
#if defined(LCD_KS108) // (For KS108 LCD only) MEGA R/W pin always at 0 state in Opentx then
|
||||
#define OUT_C_LCD_CS2 6 // use this pin to control second KS108 (CS2)
|
||||
#else // and connect KS108 R/W pin to ground via a 1k resistor
|
||||
#define OUT_C_LCD_RnW 6
|
||||
#endif
|
||||
#define OUT_C_LCD_E 7
|
||||
#define OUT_C_LCD_A0 5
|
||||
#define OUT_C_LCD_RES 4
|
||||
#define OUT_C_LCD_CS1 3
|
||||
#define OUT_C_LIGHT 2
|
||||
|
||||
// DBLKeys driver
|
||||
#define KEYS_PRESSED() (~PINL)
|
||||
|
||||
// Power driver
|
||||
uint8_t pwrCheck();
|
||||
void pwrOff();
|
||||
#if defined(PWRMANAGE)
|
||||
#define UNEXPECTED_SHUTDOWN() ((mcusr & (1 << WDRF)) || g_eeGeneral.unexpectedShutdown)
|
||||
#else
|
||||
#define UNEXPECTED_SHUTDOWN() (mcusr & (1 << WDRF))
|
||||
#endif
|
||||
|
||||
// USB fake driver
|
||||
#define usbPlugged() false
|
||||
|
||||
// Haptic driver
|
||||
#define hapticOn() PORTH |= (1 << OUT_H_HAPTIC)
|
||||
#define hapticOff() PORTH &= ~(1 << OUT_H_HAPTIC)
|
||||
|
||||
// Buzzer driver
|
||||
#define buzzerOn() PORTH |= (1 << OUT_H_SpeakerBuzzer)
|
||||
#define buzzerOff() PORTH &= ~(1 << OUT_H_SpeakerBuzzer)
|
||||
|
||||
// Speaker driver
|
||||
#if defined(AUDIO)
|
||||
#define speakerOn() TCCR4A |= (1 << COM4A0)
|
||||
#define speakerOff() TCCR4A &= ~(1 << COM4A0)
|
||||
#endif
|
||||
|
||||
// Voice driver (WTV20)
|
||||
#if defined(VOICE_WTV20)
|
||||
#define WTV20_Data_on PORTE |= (1<<OUT_E_VoiceData)
|
||||
#define WTV20_Data_off PORTE &= ~(1<<OUT_E_VoiceData)
|
||||
#define WTV20_BUSY (PINB & (1<<INP_B_VoiceBuzy))
|
||||
#define WTV20_Clock_on PORTG |= (1<<OUT_G_VoiceClock)
|
||||
#define WTV20_Clock_off PORTG &= ~(1<<OUT_G_VoiceClock)
|
||||
#define WTV20_CLK (PING & (1<<OUT_G_VoiceClock))
|
||||
#define WTV20_Reset_on PORTH |= (1<<OUT_H_VoiceReset)
|
||||
#define WTV20_Reset_off PORTH &= ~(1<<OUT_H_VoiceReset)
|
||||
#endif
|
||||
|
||||
// Voice driver (JQ6500)
|
||||
#if defined(VOICE_JQ6500)
|
||||
#define JQ6500_Serial_on PORTE |= (1<<OUT_E_VoiceData)
|
||||
#define JQ6500_Serial_off PORTE &= ~(1<<OUT_E_VoiceData)
|
||||
#define JQ6500_BUSY (PINB & (1<<INP_B_VoiceBuzy))
|
||||
#endif
|
||||
|
||||
#endif // _BOARD_MEGA2560_H_
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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_
|
||||
|
||||
#include "../common/avr/board_avr.h"
|
||||
|
||||
// Board driver
|
||||
void boardInit(void);
|
||||
#define boardOff() pwrOff()
|
||||
|
||||
// Keys
|
||||
#define KEYS_GPIO_REG_MENU pinl
|
||||
#define KEYS_GPIO_PIN_MENU (1<<4)
|
||||
#define KEYS_GPIO_REG_EXIT pinl
|
||||
#define KEYS_GPIO_PIN_EXIT (1<<5)
|
||||
#define KEYS_GPIO_REG_RIGHT pinl
|
||||
#define KEYS_GPIO_PIN_RIGHT (1<<2)
|
||||
#define KEYS_GPIO_REG_LEFT pinl
|
||||
#define KEYS_GPIO_PIN_LEFT (1<<3)
|
||||
#define KEYS_GPIO_REG_UP pinl
|
||||
#define KEYS_GPIO_PIN_UP (1<<1)
|
||||
#define KEYS_GPIO_REG_DOWN pinl
|
||||
#define KEYS_GPIO_PIN_DOWN (1<<0)
|
||||
|
||||
// Trims
|
||||
#define TRIMS_GPIO_REG_LHL pinf
|
||||
#define TRIMS_GPIO_PIN_LHL (1<<7)
|
||||
#define TRIMS_GPIO_REG_LVD pinf
|
||||
#define TRIMS_GPIO_PIN_LVD (1<<5)
|
||||
#define TRIMS_GPIO_REG_RVU pinf
|
||||
#define TRIMS_GPIO_PIN_RVU (1<<2)
|
||||
#define TRIMS_GPIO_REG_RHL pinf
|
||||
#define TRIMS_GPIO_PIN_RHL (1<<1)
|
||||
#define TRIMS_GPIO_REG_LHR pinf
|
||||
#define TRIMS_GPIO_PIN_LHR (1<<6)
|
||||
#define TRIMS_GPIO_REG_LVU pinf
|
||||
#define TRIMS_GPIO_PIN_LVU (1<<4)
|
||||
#define TRIMS_GPIO_REG_RVD pinf
|
||||
#define TRIMS_GPIO_PIN_RVD (1<<3)
|
||||
#define TRIMS_GPIO_REG_RHR pinf
|
||||
#define TRIMS_GPIO_PIN_RHR (1<<0)
|
||||
|
||||
#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() ~PINH & (1<<INP_H_RF_Activated)
|
||||
#define JACK_PPM_OUT() PORTB &= ~(1<<OUT_B_SIM_CTL)
|
||||
#define JACK_PPM_IN() PORTB |= (1<<OUT_B_SIM_CTL)
|
||||
|
||||
// Backlight driver
|
||||
#define backlightEnable() PORTC |= (1<<OUT_C_LIGHT)
|
||||
#define backlightDisable() PORTC &= ~(1<<OUT_C_LIGHT)
|
||||
#define isBacklightEnabled() PORTC & (1<<OUT_C_LIGHT)
|
||||
#define BACKLIGHT_ENABLE() backlightEnable()
|
||||
#define BACKLIGHT_DISABLE() backlightDisable()
|
||||
|
||||
// SD driver
|
||||
#define BLOCK_SIZE 512 /* Block Size in Bytes */
|
||||
#define sdDone()
|
||||
#define SD_IS_HC() (0)
|
||||
#define SD_GET_SPEED() (0)
|
||||
#if !defined(SIMU)
|
||||
bool sdMounted(void);
|
||||
void sdMountPoll(void);
|
||||
void sdPoll10ms(void);
|
||||
#endif
|
||||
|
||||
// Switchs driver
|
||||
#define INP_C_ID2 1
|
||||
#define INP_C_ID1 0
|
||||
#define INP_D_AileDR 7
|
||||
#define INP_G_ThrCt 2
|
||||
#define INP_G_Gear 1
|
||||
#define INP_G_RuddDR 0
|
||||
#define INP_L_ElevDR 6
|
||||
#define INP_L_Trainer 7
|
||||
|
||||
// Servitudes driver
|
||||
#define INP_E_PPM_IN 7 //directly used
|
||||
#define INP_B_VoiceBuzy 7 //directly used
|
||||
#define OUT_B_PPM 6
|
||||
#define OUT_B_SIM_CTL 5
|
||||
#define I_O_B_UNUSED 4 //unused, was Buzzer
|
||||
#define INP_D_I2C_SCL 1
|
||||
#define INP_D_I2C_SDA 0
|
||||
#define OUT_E_VoiceData 3
|
||||
#define INP_E_TELEM_RX 1
|
||||
#define OUT_E_TELEM_TX 0
|
||||
#define OUT_G_VoiceClock 5
|
||||
#define INP_H_RF_Activated 6
|
||||
#define INP_H_DSC_Activated 5 //pwrCheck(), directly used
|
||||
#define INP_H_Hold_Power 4 //pwrCheck(), directly used
|
||||
#define OUT_H_SpeakerBuzzer 3
|
||||
#define OUT_H_VoiceReset 1
|
||||
#define OUT_H_HAPTIC 0
|
||||
|
||||
// Rotary encoders driver
|
||||
#define INP_E_ROT_ENC_1_A 4
|
||||
#define INP_E_ROT_ENC_1_B 5
|
||||
#define INP_D_ROT_ENC_2_A 2
|
||||
#define INP_D_ROT_ENC_2_B 3
|
||||
#define INP_J_ROT_ENC_1_PUSH 0
|
||||
#define INP_J_ROT_ENC_2_PUSH 1
|
||||
#define REA_DOWN() (~PINJ & (1<<INP_J_ROT_ENC_1_PUSH))
|
||||
#define REB_DOWN() (~PINJ & (1<<INP_J_ROT_ENC_2_PUSH))
|
||||
#define ROTENC_DOWN() (REA_DOWN() || REB_DOWN())
|
||||
#define ROTENC_DIV2 // rotary encoders resolution/2
|
||||
|
||||
// LCD driver
|
||||
#define PORTA_LCD_DAT PORTA
|
||||
#define PORTC_LCD_CTRL PORTC
|
||||
#if defined(LCD_KS108) // (For KS108 LCD only) MEGA R/W pin always at 0 state in Opentx then
|
||||
#define OUT_C_LCD_CS2 6 // use this pin to control second KS108 (CS2)
|
||||
#else // and connect KS108 R/W pin to ground via a 1k resistor
|
||||
#define OUT_C_LCD_RnW 6
|
||||
#endif
|
||||
#define OUT_C_LCD_E 7
|
||||
#define OUT_C_LCD_A0 5
|
||||
#define OUT_C_LCD_RES 4
|
||||
#define OUT_C_LCD_CS1 3
|
||||
#define OUT_C_LIGHT 2
|
||||
|
||||
// DBLKeys driver
|
||||
#define KEYS_PRESSED() (~PINL)
|
||||
|
||||
// Power driver
|
||||
uint8_t pwrCheck();
|
||||
void pwrOff();
|
||||
#if defined(PWRMANAGE)
|
||||
#define UNEXPECTED_SHUTDOWN() ((mcusr & (1 << WDRF)) || g_eeGeneral.unexpectedShutdown)
|
||||
#else
|
||||
#define UNEXPECTED_SHUTDOWN() (mcusr & (1 << WDRF))
|
||||
#endif
|
||||
|
||||
// USB fake driver
|
||||
#define usbPlugged() false
|
||||
|
||||
// Haptic driver
|
||||
#define hapticOn() PORTH |= (1 << OUT_H_HAPTIC)
|
||||
#define hapticOff() PORTH &= ~(1 << OUT_H_HAPTIC)
|
||||
|
||||
// Buzzer driver
|
||||
#define buzzerOn() PORTH |= (1 << OUT_H_SpeakerBuzzer)
|
||||
#define buzzerOff() PORTH &= ~(1 << OUT_H_SpeakerBuzzer)
|
||||
|
||||
// Speaker driver
|
||||
#if defined(AUDIO)
|
||||
#define speakerOn() TCCR4A |= (1 << COM4A0)
|
||||
#define speakerOff() TCCR4A &= ~(1 << COM4A0)
|
||||
#endif
|
||||
|
||||
// Voice driver (WTV20)
|
||||
#if defined(VOICE_WTV20)
|
||||
#define WTV20_Data_on PORTE |= (1<<OUT_E_VoiceData)
|
||||
#define WTV20_Data_off PORTE &= ~(1<<OUT_E_VoiceData)
|
||||
#define WTV20_BUSY (PINB & (1<<INP_B_VoiceBuzy))
|
||||
#define WTV20_Clock_on PORTG |= (1<<OUT_G_VoiceClock)
|
||||
#define WTV20_Clock_off PORTG &= ~(1<<OUT_G_VoiceClock)
|
||||
#define WTV20_CLK (PING & (1<<OUT_G_VoiceClock))
|
||||
#define WTV20_Reset_on PORTH |= (1<<OUT_H_VoiceReset)
|
||||
#define WTV20_Reset_off PORTH &= ~(1<<OUT_H_VoiceReset)
|
||||
#endif
|
||||
|
||||
// Voice driver (JQ6500)
|
||||
#if defined(VOICE_JQ6500)
|
||||
#define JQ6500_Serial_on PORTE |= (1<<OUT_E_VoiceData)
|
||||
#define JQ6500_Serial_off PORTE &= ~(1<<OUT_E_VoiceData)
|
||||
#define JQ6500_BUSY (PINB & (1<<INP_B_VoiceBuzy))
|
||||
#endif
|
||||
|
||||
#endif // _BOARD_MEGA2560_H_
|
||||
|
||||
+7012
-7012
File diff suppressed because it is too large
Load Diff
+7113
-7113
File diff suppressed because it is too large
Load Diff
+246
-246
@@ -1,246 +1,246 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Headers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include <string.h>
|
||||
#include "debug.h"
|
||||
#include "diskio.h"
|
||||
#include "board_lowlevel.h"
|
||||
#include "Media.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Constants
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// Number of SD Slots
|
||||
#define NUM_SD_SLOTS 1
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// 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 = 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Headers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include <string.h>
|
||||
#include "debug.h"
|
||||
#include "diskio.h"
|
||||
#include "board_lowlevel.h"
|
||||
#include "Media.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Constants
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/// Number of SD Slots
|
||||
#define NUM_SD_SLOTS 1
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// 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 = 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;
|
||||
}
|
||||
|
||||
|
||||
+256
-256
@@ -18,262 +18,262 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \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.
|
||||
///
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \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);
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 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_
|
||||
|
||||
|
||||
|
||||
@@ -1,148 +1,148 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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"
|
||||
|
||||
uint16_t adcValues[NUM_ANALOGS];
|
||||
|
||||
#if defined(FRSKY_STICKS)
|
||||
const char ana_direction[NUM_ANALOGS] = {1, 1, 0, 1 ,0 ,1 ,0, 0, 0};
|
||||
#endif
|
||||
|
||||
|
||||
// Settings for mode register ADC_MR
|
||||
// USEQ off - silicon problem, doesn't work
|
||||
// TRANSFER = 3
|
||||
// TRACKTIM = 15 (16 clock periods)
|
||||
// ANACH = 1
|
||||
// SETTLING = 6 (not used if ANACH = 0)
|
||||
// STARTUP = 6 (96 clock periods)
|
||||
// PRESCAL = 9.0 MHz clock (between 1 and 20MHz)
|
||||
// FREERUN = 0
|
||||
// FWUP = 0
|
||||
// SLEEP = 0
|
||||
// LOWRES = 0
|
||||
// TRGSEL = 0
|
||||
// TRGEN = 0 (software trigger only)
|
||||
void adcInit()
|
||||
{
|
||||
Adc *padc ;
|
||||
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 = 0x3FB60000 | timer ; // 0011 1111 1011 0110 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 adcSingleRead()
|
||||
{
|
||||
Adc *padc;
|
||||
uint32_t y;
|
||||
uint32_t x;
|
||||
|
||||
for (uint8_t i=0; i<4; i++)
|
||||
padc = ADC;
|
||||
y = padc->ADC_ISR; // Clear EOC flags
|
||||
for (y = NUM_ANALOGS+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
|
||||
adcValues[0] = ADC->ADC_CDR1;
|
||||
adcValues[1] = ADC->ADC_CDR2;
|
||||
adcValues[2] = ADC->ADC_CDR3;
|
||||
adcValues[3] = ADC->ADC_CDR4;
|
||||
adcValues[4] = ADC->ADC_CDR5;
|
||||
adcValues[5] = ADC->ADC_CDR9;
|
||||
adcValues[6] = ADC->ADC_CDR13;
|
||||
adcValues[7] = ADC->ADC_CDR14;
|
||||
|
||||
#if !defined(REVA)
|
||||
adcValues[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(FRSKY_STICKS)
|
||||
uint32_t i ;
|
||||
for (i=0; i<NUM_ANALOGS; i++) {
|
||||
if (ana_direction[i]) {
|
||||
adcValues[i] = 4096-adcValues[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void adcRead()
|
||||
{
|
||||
uint16_t temp[NUM_ANALOGS] = { 0 };
|
||||
|
||||
for (int i=0; i<4; i++) {
|
||||
adcSingleRead();
|
||||
for (uint8_t x=0; x<NUM_ANALOGS; x++) {
|
||||
uint16_t val = adcValues[x];
|
||||
#if defined(JITTER_MEASURE)
|
||||
if (JITTER_MEASURE_ACTIVE()) {
|
||||
rawJitter[x].measure(val);
|
||||
}
|
||||
#endif
|
||||
temp[x] += val;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t x=0; x<NUM_ANALOGS; x++) {
|
||||
adcValues[x] = temp[x] >> 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if !defined(SIMU)
|
||||
uint16_t getAnalogValue(uint8_t index)
|
||||
{
|
||||
#if defined(PCBSKY9X) && !defined(REVA)
|
||||
static const uint8_t mapping[] = {1,5,7,0,4,6,2,3};
|
||||
index = mapping[index];
|
||||
#endif
|
||||
return adcValues[index];
|
||||
}
|
||||
#endif // #if !defined(SIMU)
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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"
|
||||
|
||||
uint16_t adcValues[NUM_ANALOGS];
|
||||
|
||||
#if defined(FRSKY_STICKS)
|
||||
const char ana_direction[NUM_ANALOGS] = {1, 1, 0, 1 ,0 ,1 ,0, 0, 0};
|
||||
#endif
|
||||
|
||||
|
||||
// Settings for mode register ADC_MR
|
||||
// USEQ off - silicon problem, doesn't work
|
||||
// TRANSFER = 3
|
||||
// TRACKTIM = 15 (16 clock periods)
|
||||
// ANACH = 1
|
||||
// SETTLING = 6 (not used if ANACH = 0)
|
||||
// STARTUP = 6 (96 clock periods)
|
||||
// PRESCAL = 9.0 MHz clock (between 1 and 20MHz)
|
||||
// FREERUN = 0
|
||||
// FWUP = 0
|
||||
// SLEEP = 0
|
||||
// LOWRES = 0
|
||||
// TRGSEL = 0
|
||||
// TRGEN = 0 (software trigger only)
|
||||
void adcInit()
|
||||
{
|
||||
Adc *padc ;
|
||||
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 = 0x3FB60000 | timer ; // 0011 1111 1011 0110 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 adcSingleRead()
|
||||
{
|
||||
Adc *padc;
|
||||
uint32_t y;
|
||||
uint32_t x;
|
||||
|
||||
for (uint8_t i=0; i<4; i++)
|
||||
padc = ADC;
|
||||
y = padc->ADC_ISR; // Clear EOC flags
|
||||
for (y = NUM_ANALOGS+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
|
||||
adcValues[0] = ADC->ADC_CDR1;
|
||||
adcValues[1] = ADC->ADC_CDR2;
|
||||
adcValues[2] = ADC->ADC_CDR3;
|
||||
adcValues[3] = ADC->ADC_CDR4;
|
||||
adcValues[4] = ADC->ADC_CDR5;
|
||||
adcValues[5] = ADC->ADC_CDR9;
|
||||
adcValues[6] = ADC->ADC_CDR13;
|
||||
adcValues[7] = ADC->ADC_CDR14;
|
||||
|
||||
#if !defined(REVA)
|
||||
adcValues[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(FRSKY_STICKS)
|
||||
uint32_t i ;
|
||||
for (i=0; i<NUM_ANALOGS; i++) {
|
||||
if (ana_direction[i]) {
|
||||
adcValues[i] = 4096-adcValues[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void adcRead()
|
||||
{
|
||||
uint16_t temp[NUM_ANALOGS] = { 0 };
|
||||
|
||||
for (int i=0; i<4; i++) {
|
||||
adcSingleRead();
|
||||
for (uint8_t x=0; x<NUM_ANALOGS; x++) {
|
||||
uint16_t val = adcValues[x];
|
||||
#if defined(JITTER_MEASURE)
|
||||
if (JITTER_MEASURE_ACTIVE()) {
|
||||
rawJitter[x].measure(val);
|
||||
}
|
||||
#endif
|
||||
temp[x] += val;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t x=0; x<NUM_ANALOGS; x++) {
|
||||
adcValues[x] = temp[x] >> 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if !defined(SIMU)
|
||||
uint16_t getAnalogValue(uint8_t index)
|
||||
{
|
||||
#if defined(PCBSKY9X) && !defined(REVA)
|
||||
static const uint8_t mapping[] = {1,5,7,0,4,6,2,3};
|
||||
index = mapping[index];
|
||||
#endif
|
||||
return adcValues[index];
|
||||
}
|
||||
#endif // #if !defined(SIMU)
|
||||
|
||||
@@ -1,195 +1,195 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 dacStarted = false;
|
||||
|
||||
#if !defined(SIMU)
|
||||
|
||||
#if !defined(SOFTWARE_VOLUME)
|
||||
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
|
||||
} ;
|
||||
#endif
|
||||
|
||||
void setSampleRate(uint32_t frequency)
|
||||
{
|
||||
Tc *ptc ;
|
||||
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()
|
||||
{
|
||||
Tc *ptc ;
|
||||
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
|
||||
|
||||
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) ;
|
||||
}
|
||||
|
||||
inline void dacStart()
|
||||
{
|
||||
PMC->PMC_PCER0 |= 0x40000000L ; // Enable peripheral clock to DAC
|
||||
DACC->DACC_IER = DACC_IER_ENDTX ;
|
||||
dacStarted = true;
|
||||
}
|
||||
|
||||
inline void dacStop()
|
||||
{
|
||||
DACC->DACC_IDR = DACC_IDR_ENDTX ; // Disable interrupt
|
||||
dacStarted = false;
|
||||
}
|
||||
|
||||
void audioConsumeCurrentBuffer()
|
||||
{
|
||||
if (!dacStarted) {
|
||||
dacStart();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern "C" void DAC_IRQHandler()
|
||||
{
|
||||
uint32_t sr = DACC->DACC_ISR;
|
||||
if (sr & DACC_ISR_ENDTX) {
|
||||
audioQueue.buffersFifo.freeNextFilledBuffer();
|
||||
const AudioBuffer * nextBuffer = audioQueue.buffersFifo.getNextFilledBuffer();
|
||||
if (nextBuffer) {
|
||||
// Try the first PDC buffer
|
||||
if ((DACC->DACC_TCR == 0) && (DACC->DACC_TNCR == 0)) {
|
||||
DACC->DACC_TPR = CONVERT_PTR_UINT(nextBuffer->data);
|
||||
DACC->DACC_TCR = nextBuffer->size/2;
|
||||
DACC->DACC_PTCR = DACC_PTCR_TXTEN;
|
||||
return;
|
||||
}
|
||||
// Try the second PDC buffer
|
||||
if (DACC->DACC_TNCR == 0) {
|
||||
DACC->DACC_TNPR = CONVERT_PTR_UINT(nextBuffer->data);
|
||||
DACC->DACC_TNCR = nextBuffer->size/2;
|
||||
DACC->DACC_PTCR = DACC_PTCR_TXTEN;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
dacStop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sound routines
|
||||
void audioInit()
|
||||
{
|
||||
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
|
||||
|
||||
#if defined(REVX)
|
||||
configure_pins( PIO_PC26, PIN_ENABLE | PIN_LOW | PIN_OUTPUT | PIN_PORTC | PIN_NO_PULLUP ) ;
|
||||
PIOC->PIO_CODR = PIO_PC26 ;
|
||||
#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
|
||||
}
|
||||
|
||||
#if !defined(SOFTWARE_VOLUME)
|
||||
void setScaledVolume(uint8_t volume)
|
||||
{
|
||||
volumeRequired = volumeScale[min<uint8_t>(volume, VOLUME_LEVEL_MAX)];
|
||||
__disable_irq() ;
|
||||
i2cCheck() ;
|
||||
__enable_irq() ;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // #if !defined(SIMU)
|
||||
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 dacStarted = false;
|
||||
|
||||
#if !defined(SIMU)
|
||||
|
||||
#if !defined(SOFTWARE_VOLUME)
|
||||
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
|
||||
} ;
|
||||
#endif
|
||||
|
||||
void setSampleRate(uint32_t frequency)
|
||||
{
|
||||
Tc *ptc ;
|
||||
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()
|
||||
{
|
||||
Tc *ptc ;
|
||||
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
|
||||
|
||||
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) ;
|
||||
}
|
||||
|
||||
inline void dacStart()
|
||||
{
|
||||
PMC->PMC_PCER0 |= 0x40000000L ; // Enable peripheral clock to DAC
|
||||
DACC->DACC_IER = DACC_IER_ENDTX ;
|
||||
dacStarted = true;
|
||||
}
|
||||
|
||||
inline void dacStop()
|
||||
{
|
||||
DACC->DACC_IDR = DACC_IDR_ENDTX ; // Disable interrupt
|
||||
dacStarted = false;
|
||||
}
|
||||
|
||||
void audioConsumeCurrentBuffer()
|
||||
{
|
||||
if (!dacStarted) {
|
||||
dacStart();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern "C" void DAC_IRQHandler()
|
||||
{
|
||||
uint32_t sr = DACC->DACC_ISR;
|
||||
if (sr & DACC_ISR_ENDTX) {
|
||||
audioQueue.buffersFifo.freeNextFilledBuffer();
|
||||
const AudioBuffer * nextBuffer = audioQueue.buffersFifo.getNextFilledBuffer();
|
||||
if (nextBuffer) {
|
||||
// Try the first PDC buffer
|
||||
if ((DACC->DACC_TCR == 0) && (DACC->DACC_TNCR == 0)) {
|
||||
DACC->DACC_TPR = CONVERT_PTR_UINT(nextBuffer->data);
|
||||
DACC->DACC_TCR = nextBuffer->size/2;
|
||||
DACC->DACC_PTCR = DACC_PTCR_TXTEN;
|
||||
return;
|
||||
}
|
||||
// Try the second PDC buffer
|
||||
if (DACC->DACC_TNCR == 0) {
|
||||
DACC->DACC_TNPR = CONVERT_PTR_UINT(nextBuffer->data);
|
||||
DACC->DACC_TNCR = nextBuffer->size/2;
|
||||
DACC->DACC_PTCR = DACC_PTCR_TXTEN;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
dacStop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sound routines
|
||||
void audioInit()
|
||||
{
|
||||
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
|
||||
|
||||
#if defined(REVX)
|
||||
configure_pins( PIO_PC26, PIN_ENABLE | PIN_LOW | PIN_OUTPUT | PIN_PORTC | PIN_NO_PULLUP ) ;
|
||||
PIOC->PIO_CODR = PIO_PC26 ;
|
||||
#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
|
||||
}
|
||||
|
||||
#if !defined(SOFTWARE_VOLUME)
|
||||
void setScaledVolume(uint8_t volume)
|
||||
{
|
||||
volumeRequired = volumeScale[min<uint8_t>(volume, VOLUME_LEVEL_MAX)];
|
||||
__disable_irq() ;
|
||||
i2cCheck() ;
|
||||
__enable_irq() ;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // #if !defined(SIMU)
|
||||
|
||||
|
||||
+609
-609
File diff suppressed because it is too large
Load Diff
+414
-414
@@ -1,414 +1,414 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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_lowlevel.h"
|
||||
#include "audio_driver.h"
|
||||
|
||||
extern uint16_t ResetReason;
|
||||
|
||||
#define BOOTLOADER_SIZE 0x8000
|
||||
#define FIRMWARE_SIZE (256*1024)
|
||||
#define FIRMWARE_ADDRESS 0x00400000
|
||||
|
||||
// Board driver
|
||||
void boardInit(void);
|
||||
#define boardOff() pwrOff()
|
||||
|
||||
// Rotary Encoder driver
|
||||
void rotencInit();
|
||||
void rotencEnd();
|
||||
|
||||
#if !defined(REVX) && !defined(AR9X)
|
||||
#define ROTARY_ENCODERS 1
|
||||
#define ROTARY_ENCODER_NAVIGATION
|
||||
#define REA_DOWN() (!(PIOB->PIO_PDSR & 0x40))
|
||||
#else
|
||||
#define REA_DOWN() (0)
|
||||
#endif
|
||||
|
||||
// Keys driver
|
||||
#define NUM_SWITCHES 7
|
||||
enum EnumKeys
|
||||
{
|
||||
KEY_MENU,
|
||||
KEY_ENTER=KEY_MENU,
|
||||
KEY_EXIT,
|
||||
KEY_DOWN,
|
||||
KEY_MINUS = KEY_DOWN,
|
||||
KEY_UP,
|
||||
KEY_PLUS = KEY_UP,
|
||||
KEY_RIGHT,
|
||||
KEY_LEFT,
|
||||
|
||||
TRM_BASE,
|
||||
TRM_LH_DWN = TRM_BASE,
|
||||
TRM_LH_UP,
|
||||
TRM_LV_DWN,
|
||||
TRM_LV_UP,
|
||||
TRM_RV_DWN,
|
||||
TRM_RV_UP,
|
||||
TRM_RH_DWN,
|
||||
TRM_RH_UP,
|
||||
TRM_LAST = TRM_RH_UP,
|
||||
|
||||
#if defined(ROTARY_ENCODERS)
|
||||
BTN_REa,
|
||||
#endif
|
||||
|
||||
NUM_KEYS
|
||||
};
|
||||
|
||||
enum EnumSwitches
|
||||
{
|
||||
SW_ID0,
|
||||
SW_ID1,
|
||||
SW_ID2,
|
||||
SW_THR,
|
||||
SW_RUD,
|
||||
SW_ELE,
|
||||
SW_AIL,
|
||||
SW_GEA,
|
||||
SW_TRN,
|
||||
};
|
||||
#define IS_3POS(sw) ((sw) == 0)
|
||||
#define IS_TOGGLE(sw) ((sw) == SWSRC_TRN)
|
||||
|
||||
#if defined(REVA)
|
||||
#define KEYS_GPIO_REG_MENU PIOB->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_EXIT PIOA->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_UP PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_DOWN PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_RIGHT PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_LEFT PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_PIN_MENU 0x00000040
|
||||
#define KEYS_GPIO_PIN_EXIT 0x80000000
|
||||
#define KEYS_GPIO_PIN_UP 0x00000004
|
||||
#define KEYS_GPIO_PIN_DOWN 0x00000008
|
||||
#define KEYS_GPIO_PIN_RIGHT 0x00000010
|
||||
#define KEYS_GPIO_PIN_LEFT 0x00000020
|
||||
#else
|
||||
#define KEYS_GPIO_REG_MENU PIOB->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_EXIT PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_UP PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_DOWN PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_RIGHT PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_LEFT PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_PIN_MENU 0x00000020
|
||||
#define KEYS_GPIO_PIN_EXIT 0x01000000
|
||||
#define KEYS_GPIO_PIN_UP 0x00000002
|
||||
#define KEYS_GPIO_PIN_DOWN 0x00000020
|
||||
#define KEYS_GPIO_PIN_RIGHT 0x00000010
|
||||
#define KEYS_GPIO_PIN_LEFT 0x00000008
|
||||
#endif
|
||||
|
||||
#if defined(REVX)
|
||||
#define TRIMS_GPIO_REG_LHL PIOB->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_LVD PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RVU PIOC->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RHL PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_LHR PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_LVU PIOC->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RVD PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RHR PIOC->PIO_PDSR
|
||||
#else
|
||||
#define TRIMS_GPIO_REG_LHL PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_LVD PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RVU PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RHL PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_LHR PIOB->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_LVU PIOC->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RVD PIOC->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RHR PIOC->PIO_PDSR
|
||||
#endif
|
||||
|
||||
#if defined(REVX)
|
||||
#define TRIMS_GPIO_PIN_LHL 0x00000010
|
||||
#define TRIMS_GPIO_PIN_LVD 0x01000000
|
||||
#define TRIMS_GPIO_PIN_RVU 0x00000400
|
||||
#define TRIMS_GPIO_PIN_RHL 0x00000001
|
||||
#define TRIMS_GPIO_PIN_LHR 0x00800000
|
||||
#define TRIMS_GPIO_PIN_LVU 0x10000000
|
||||
#define TRIMS_GPIO_PIN_RVD 0x00000002
|
||||
#define TRIMS_GPIO_PIN_RHR 0x00000200
|
||||
#elif defined(REVA)
|
||||
#define TRIMS_GPIO_PIN_LHL 0x00000080
|
||||
#define TRIMS_GPIO_PIN_LVD 0x08000000
|
||||
#define TRIMS_GPIO_PIN_RVU 0x40000000
|
||||
#define TRIMS_GPIO_PIN_RHL 0x20000000
|
||||
#define TRIMS_GPIO_PIN_LHR 0x00000010
|
||||
#define TRIMS_GPIO_PIN_LVU 0x10000000
|
||||
#define TRIMS_GPIO_PIN_RVD 0x00000400
|
||||
#define TRIMS_GPIO_PIN_RHR 0x00000200
|
||||
#else
|
||||
#define TRIMS_GPIO_PIN_LHL 0x00800000
|
||||
#define TRIMS_GPIO_PIN_LVD 0x01000000
|
||||
#define TRIMS_GPIO_PIN_RVU 0x00000002
|
||||
#define TRIMS_GPIO_PIN_RHL 0x00000001
|
||||
#define TRIMS_GPIO_PIN_LHR 0x00000010
|
||||
#define TRIMS_GPIO_PIN_LVU 0x10000000
|
||||
#define TRIMS_GPIO_PIN_RVD 0x00000400
|
||||
#define TRIMS_GPIO_PIN_RHR 0x00000200
|
||||
#endif
|
||||
|
||||
// LCD driver
|
||||
#define LCD_W 128
|
||||
#define LCD_H 64
|
||||
#define LCD_DEPTH 1
|
||||
#define LCD_CONTRAST_MIN 10
|
||||
#define LCD_CONTRAST_MAX 45
|
||||
#define LCD_CONTRAST_DEFAULT 25
|
||||
void lcdInit(void);
|
||||
void lcdRefresh(void);
|
||||
#define lcdRefreshWait()
|
||||
void lcdSetRefVolt(uint8_t val);
|
||||
void lcdSetContrast(void);
|
||||
|
||||
// USB driver
|
||||
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
|
||||
|
||||
// Telemetry port
|
||||
#define SECOND_USART USART0
|
||||
#define SECOND_ID ID_USART0
|
||||
#define SECOND_PINS { PINS_USART0 }
|
||||
|
||||
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;
|
||||
void calcConsumption();
|
||||
#endif
|
||||
|
||||
// Trainer driver
|
||||
#define SLAVE_MODE() (pwrCheck() == e_power_trainer)
|
||||
#define TRAINER_CONNECTED() (PIOA->PIO_PDSR & PIO_PA8)
|
||||
void checkTrainerSettings();
|
||||
void init_trainer_capture();
|
||||
|
||||
// Write Flash driver
|
||||
#define FLASH_PAGESIZE 256
|
||||
void flashWrite(uint32_t * address, uint32_t * buffer);
|
||||
|
||||
// Keys driver
|
||||
uint8_t keyState(uint8_t index);
|
||||
uint32_t switchState(uint8_t index);
|
||||
uint32_t readKeys(void);
|
||||
uint32_t readTrims(void);
|
||||
#define TRIMS_PRESSED() readTrims()
|
||||
#define KEYS_PRESSED() readKeys()
|
||||
|
||||
// Pulses driver
|
||||
void init_no_pulses(uint32_t port);
|
||||
void disable_no_pulses(uint32_t port);
|
||||
void init_ppm(uint32_t port);
|
||||
void disable_ppm(uint32_t port);
|
||||
void init_pxx(uint32_t port);
|
||||
void disable_pxx(uint32_t port);
|
||||
void init_dsm2(uint32_t port);
|
||||
void disable_dsm2(uint32_t port);
|
||||
|
||||
#if defined(MULTIMODULE)
|
||||
void init_multimodule(uint32_t module_index);
|
||||
void disable_multimodule(uint32_t module_index);
|
||||
#endif
|
||||
|
||||
// SD driver
|
||||
#if defined(SIMU)
|
||||
#define sdInit()
|
||||
#define sdDone()
|
||||
#else
|
||||
#define sdPoll10ms()
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
void init_SDcard();
|
||||
void sdInit();
|
||||
void sdDone();
|
||||
uint32_t sd_card_ready();
|
||||
uint32_t sdMounted();
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// WDT driver
|
||||
#if defined(WATCHDOG_DISABLED) || defined(SIMU)
|
||||
#define wdt_disable()
|
||||
#define wdt_enable(x)
|
||||
#define wdt_reset()
|
||||
#else
|
||||
#define wdt_disable()
|
||||
#define wdt_enable(x) WDT->WDT_MR = 0x3FFF207F
|
||||
#define wdt_reset() WDT->WDT_CR = 0xA5000001
|
||||
#endif
|
||||
|
||||
// Backlight driver
|
||||
#define backlightEnable() (PWM->PWM_CH_NUM[0].PWM_CDTY = g_eeGeneral.backlightBright)
|
||||
#define backlightDisable() (PWM->PWM_CH_NUM[0].PWM_CDTY = 100)
|
||||
#define isBacklightEnabled() (PWM->PWM_CH_NUM[0].PWM_CDTY != 100)
|
||||
#define BACKLIGHT_ENABLE() backlightEnable()
|
||||
#define BACKLIGHT_DISABLE() backlightDisable()
|
||||
|
||||
// ADC driver
|
||||
#define NUM_POTS 3
|
||||
#define NUM_SLIDERS 0
|
||||
#define NUM_XPOTS 0
|
||||
enum Analogs {
|
||||
STICK1,
|
||||
STICK2,
|
||||
STICK3,
|
||||
STICK4,
|
||||
POT_FIRST,
|
||||
POT1 = POT_FIRST,
|
||||
POT2,
|
||||
POT3,
|
||||
POT_LAST = POT3,
|
||||
TX_VOLTAGE,
|
||||
#if !defined(REVA)
|
||||
TX_CURRENT,
|
||||
#endif
|
||||
NUM_ANALOGS
|
||||
};
|
||||
enum CalibratedAnalogs {
|
||||
CALIBRATED_STICK1,
|
||||
CALIBRATED_STICK2,
|
||||
CALIBRATED_STICK3,
|
||||
CALIBRATED_STICK4,
|
||||
CALIBRATED_POT_FIRST,
|
||||
CALIBRATED_POT1 = CALIBRATED_POT_FIRST,
|
||||
CALIBRATED_POT2,
|
||||
CALIBRATED_POT3,
|
||||
CALIBRATED_POT_LAST = CALIBRATED_POT3,
|
||||
NUM_CALIBRATED_ANALOGS
|
||||
};
|
||||
#define IS_POT(x) ((x)>=POT_FIRST && (x)<=POT_LAST)
|
||||
#define IS_SLIDER(x) false
|
||||
void adcInit();
|
||||
void adcRead(void);
|
||||
uint16_t getAnalogValue(uint8_t index);
|
||||
uint16_t getBatteryVoltage(); // returns current battery voltage in 10mV steps
|
||||
void setSticksGain(uint8_t gains);
|
||||
|
||||
// Buzzer driver
|
||||
void buzzerSound(uint8_t duration);
|
||||
void buzzerHeartbeat();
|
||||
#define BUZZER_HEARTBEAT buzzerHeartbeat
|
||||
|
||||
// i2c driver
|
||||
void i2cCheck();
|
||||
|
||||
// Coproc driver
|
||||
void coprocInit();
|
||||
void coprocWriteData(uint8_t *data, uint32_t size);
|
||||
#if defined(__cplusplus)
|
||||
void coprocReadData(bool onlytemp=false);
|
||||
#endif
|
||||
extern int8_t volumeRequired;
|
||||
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
|
||||
#define TRAINER_PWR
|
||||
#if !defined(REVA)
|
||||
#define SOFT_PWR_CTRL
|
||||
#endif
|
||||
void pwrInit();
|
||||
void pwrOff();
|
||||
uint32_t pwrCheck();
|
||||
uint32_t pwrPressed();
|
||||
#define UNEXPECTED_SHUTDOWN() (g_eeGeneral.unexpectedShutdown)
|
||||
|
||||
// EEPROM driver
|
||||
#define EEPROM_SIZE (4*1024*1024/8)
|
||||
#define EEPROM_BLOCK_SIZE (4*1024)
|
||||
void eepromInit();
|
||||
uint8_t eepromReadStatus();
|
||||
uint8_t eepromIsTransferComplete(void);
|
||||
void eepromBlockErase(uint32_t address);
|
||||
void eepromStartRead(uint8_t * buffer, size_t address, size_t size);
|
||||
void eepromStartWrite(uint8_t * buffer, size_t address, size_t size);
|
||||
|
||||
// Debug driver
|
||||
void debugPutc(const char c);
|
||||
|
||||
// Telemetry driver
|
||||
void telemetryPortInit(uint32_t baudrate, uint8_t mode);
|
||||
uint32_t telemetryTransmitPending();
|
||||
void telemetryTransmitBuffer(uint8_t * buffer, uint32_t size);
|
||||
void rxPdcUsart( void (*pChProcess)(uint8_t x) );
|
||||
|
||||
// Second UART driver
|
||||
void serial2TelemetryInit(unsigned int protocol);
|
||||
#if defined(__cplusplus)
|
||||
bool telemetrySecondPortReceive(uint8_t & data);
|
||||
#endif
|
||||
|
||||
extern const uint8_t BootCode[];
|
||||
|
||||
#endif // _BOARD_SKY9X_H_
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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_lowlevel.h"
|
||||
#include "audio_driver.h"
|
||||
|
||||
extern uint16_t ResetReason;
|
||||
|
||||
#define BOOTLOADER_SIZE 0x8000
|
||||
#define FIRMWARE_SIZE (256*1024)
|
||||
#define FIRMWARE_ADDRESS 0x00400000
|
||||
|
||||
// Board driver
|
||||
void boardInit(void);
|
||||
#define boardOff() pwrOff()
|
||||
|
||||
// Rotary Encoder driver
|
||||
void rotencInit();
|
||||
void rotencEnd();
|
||||
|
||||
#if !defined(REVX) && !defined(AR9X)
|
||||
#define ROTARY_ENCODERS 1
|
||||
#define ROTARY_ENCODER_NAVIGATION
|
||||
#define REA_DOWN() (!(PIOB->PIO_PDSR & 0x40))
|
||||
#else
|
||||
#define REA_DOWN() (0)
|
||||
#endif
|
||||
|
||||
// Keys driver
|
||||
#define NUM_SWITCHES 7
|
||||
enum EnumKeys
|
||||
{
|
||||
KEY_MENU,
|
||||
KEY_ENTER=KEY_MENU,
|
||||
KEY_EXIT,
|
||||
KEY_DOWN,
|
||||
KEY_MINUS = KEY_DOWN,
|
||||
KEY_UP,
|
||||
KEY_PLUS = KEY_UP,
|
||||
KEY_RIGHT,
|
||||
KEY_LEFT,
|
||||
|
||||
TRM_BASE,
|
||||
TRM_LH_DWN = TRM_BASE,
|
||||
TRM_LH_UP,
|
||||
TRM_LV_DWN,
|
||||
TRM_LV_UP,
|
||||
TRM_RV_DWN,
|
||||
TRM_RV_UP,
|
||||
TRM_RH_DWN,
|
||||
TRM_RH_UP,
|
||||
TRM_LAST = TRM_RH_UP,
|
||||
|
||||
#if defined(ROTARY_ENCODERS)
|
||||
BTN_REa,
|
||||
#endif
|
||||
|
||||
NUM_KEYS
|
||||
};
|
||||
|
||||
enum EnumSwitches
|
||||
{
|
||||
SW_ID0,
|
||||
SW_ID1,
|
||||
SW_ID2,
|
||||
SW_THR,
|
||||
SW_RUD,
|
||||
SW_ELE,
|
||||
SW_AIL,
|
||||
SW_GEA,
|
||||
SW_TRN,
|
||||
};
|
||||
#define IS_3POS(sw) ((sw) == 0)
|
||||
#define IS_TOGGLE(sw) ((sw) == SWSRC_TRN)
|
||||
|
||||
#if defined(REVA)
|
||||
#define KEYS_GPIO_REG_MENU PIOB->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_EXIT PIOA->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_UP PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_DOWN PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_RIGHT PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_LEFT PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_PIN_MENU 0x00000040
|
||||
#define KEYS_GPIO_PIN_EXIT 0x80000000
|
||||
#define KEYS_GPIO_PIN_UP 0x00000004
|
||||
#define KEYS_GPIO_PIN_DOWN 0x00000008
|
||||
#define KEYS_GPIO_PIN_RIGHT 0x00000010
|
||||
#define KEYS_GPIO_PIN_LEFT 0x00000020
|
||||
#else
|
||||
#define KEYS_GPIO_REG_MENU PIOB->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_EXIT PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_UP PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_DOWN PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_RIGHT PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_REG_LEFT PIOC->PIO_PDSR
|
||||
#define KEYS_GPIO_PIN_MENU 0x00000020
|
||||
#define KEYS_GPIO_PIN_EXIT 0x01000000
|
||||
#define KEYS_GPIO_PIN_UP 0x00000002
|
||||
#define KEYS_GPIO_PIN_DOWN 0x00000020
|
||||
#define KEYS_GPIO_PIN_RIGHT 0x00000010
|
||||
#define KEYS_GPIO_PIN_LEFT 0x00000008
|
||||
#endif
|
||||
|
||||
#if defined(REVX)
|
||||
#define TRIMS_GPIO_REG_LHL PIOB->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_LVD PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RVU PIOC->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RHL PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_LHR PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_LVU PIOC->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RVD PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RHR PIOC->PIO_PDSR
|
||||
#else
|
||||
#define TRIMS_GPIO_REG_LHL PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_LVD PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RVU PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RHL PIOA->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_LHR PIOB->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_LVU PIOC->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RVD PIOC->PIO_PDSR
|
||||
#define TRIMS_GPIO_REG_RHR PIOC->PIO_PDSR
|
||||
#endif
|
||||
|
||||
#if defined(REVX)
|
||||
#define TRIMS_GPIO_PIN_LHL 0x00000010
|
||||
#define TRIMS_GPIO_PIN_LVD 0x01000000
|
||||
#define TRIMS_GPIO_PIN_RVU 0x00000400
|
||||
#define TRIMS_GPIO_PIN_RHL 0x00000001
|
||||
#define TRIMS_GPIO_PIN_LHR 0x00800000
|
||||
#define TRIMS_GPIO_PIN_LVU 0x10000000
|
||||
#define TRIMS_GPIO_PIN_RVD 0x00000002
|
||||
#define TRIMS_GPIO_PIN_RHR 0x00000200
|
||||
#elif defined(REVA)
|
||||
#define TRIMS_GPIO_PIN_LHL 0x00000080
|
||||
#define TRIMS_GPIO_PIN_LVD 0x08000000
|
||||
#define TRIMS_GPIO_PIN_RVU 0x40000000
|
||||
#define TRIMS_GPIO_PIN_RHL 0x20000000
|
||||
#define TRIMS_GPIO_PIN_LHR 0x00000010
|
||||
#define TRIMS_GPIO_PIN_LVU 0x10000000
|
||||
#define TRIMS_GPIO_PIN_RVD 0x00000400
|
||||
#define TRIMS_GPIO_PIN_RHR 0x00000200
|
||||
#else
|
||||
#define TRIMS_GPIO_PIN_LHL 0x00800000
|
||||
#define TRIMS_GPIO_PIN_LVD 0x01000000
|
||||
#define TRIMS_GPIO_PIN_RVU 0x00000002
|
||||
#define TRIMS_GPIO_PIN_RHL 0x00000001
|
||||
#define TRIMS_GPIO_PIN_LHR 0x00000010
|
||||
#define TRIMS_GPIO_PIN_LVU 0x10000000
|
||||
#define TRIMS_GPIO_PIN_RVD 0x00000400
|
||||
#define TRIMS_GPIO_PIN_RHR 0x00000200
|
||||
#endif
|
||||
|
||||
// LCD driver
|
||||
#define LCD_W 128
|
||||
#define LCD_H 64
|
||||
#define LCD_DEPTH 1
|
||||
#define LCD_CONTRAST_MIN 10
|
||||
#define LCD_CONTRAST_MAX 45
|
||||
#define LCD_CONTRAST_DEFAULT 25
|
||||
void lcdInit(void);
|
||||
void lcdRefresh(void);
|
||||
#define lcdRefreshWait()
|
||||
void lcdSetRefVolt(uint8_t val);
|
||||
void lcdSetContrast(void);
|
||||
|
||||
// USB driver
|
||||
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
|
||||
|
||||
// Telemetry port
|
||||
#define SECOND_USART USART0
|
||||
#define SECOND_ID ID_USART0
|
||||
#define SECOND_PINS { PINS_USART0 }
|
||||
|
||||
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;
|
||||
void calcConsumption();
|
||||
#endif
|
||||
|
||||
// Trainer driver
|
||||
#define SLAVE_MODE() (pwrCheck() == e_power_trainer)
|
||||
#define TRAINER_CONNECTED() (PIOA->PIO_PDSR & PIO_PA8)
|
||||
void checkTrainerSettings();
|
||||
void init_trainer_capture();
|
||||
|
||||
// Write Flash driver
|
||||
#define FLASH_PAGESIZE 256
|
||||
void flashWrite(uint32_t * address, uint32_t * buffer);
|
||||
|
||||
// Keys driver
|
||||
uint8_t keyState(uint8_t index);
|
||||
uint32_t switchState(uint8_t index);
|
||||
uint32_t readKeys(void);
|
||||
uint32_t readTrims(void);
|
||||
#define TRIMS_PRESSED() readTrims()
|
||||
#define KEYS_PRESSED() readKeys()
|
||||
|
||||
// Pulses driver
|
||||
void init_no_pulses(uint32_t port);
|
||||
void disable_no_pulses(uint32_t port);
|
||||
void init_ppm(uint32_t port);
|
||||
void disable_ppm(uint32_t port);
|
||||
void init_pxx(uint32_t port);
|
||||
void disable_pxx(uint32_t port);
|
||||
void init_dsm2(uint32_t port);
|
||||
void disable_dsm2(uint32_t port);
|
||||
|
||||
#if defined(MULTIMODULE)
|
||||
void init_multimodule(uint32_t module_index);
|
||||
void disable_multimodule(uint32_t module_index);
|
||||
#endif
|
||||
|
||||
// SD driver
|
||||
#if defined(SIMU)
|
||||
#define sdInit()
|
||||
#define sdDone()
|
||||
#else
|
||||
#define sdPoll10ms()
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
void init_SDcard();
|
||||
void sdInit();
|
||||
void sdDone();
|
||||
uint32_t sd_card_ready();
|
||||
uint32_t sdMounted();
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// WDT driver
|
||||
#if defined(WATCHDOG_DISABLED) || defined(SIMU)
|
||||
#define wdt_disable()
|
||||
#define wdt_enable(x)
|
||||
#define wdt_reset()
|
||||
#else
|
||||
#define wdt_disable()
|
||||
#define wdt_enable(x) WDT->WDT_MR = 0x3FFF207F
|
||||
#define wdt_reset() WDT->WDT_CR = 0xA5000001
|
||||
#endif
|
||||
|
||||
// Backlight driver
|
||||
#define backlightEnable() (PWM->PWM_CH_NUM[0].PWM_CDTY = g_eeGeneral.backlightBright)
|
||||
#define backlightDisable() (PWM->PWM_CH_NUM[0].PWM_CDTY = 100)
|
||||
#define isBacklightEnabled() (PWM->PWM_CH_NUM[0].PWM_CDTY != 100)
|
||||
#define BACKLIGHT_ENABLE() backlightEnable()
|
||||
#define BACKLIGHT_DISABLE() backlightDisable()
|
||||
|
||||
// ADC driver
|
||||
#define NUM_POTS 3
|
||||
#define NUM_SLIDERS 0
|
||||
#define NUM_XPOTS 0
|
||||
enum Analogs {
|
||||
STICK1,
|
||||
STICK2,
|
||||
STICK3,
|
||||
STICK4,
|
||||
POT_FIRST,
|
||||
POT1 = POT_FIRST,
|
||||
POT2,
|
||||
POT3,
|
||||
POT_LAST = POT3,
|
||||
TX_VOLTAGE,
|
||||
#if !defined(REVA)
|
||||
TX_CURRENT,
|
||||
#endif
|
||||
NUM_ANALOGS
|
||||
};
|
||||
enum CalibratedAnalogs {
|
||||
CALIBRATED_STICK1,
|
||||
CALIBRATED_STICK2,
|
||||
CALIBRATED_STICK3,
|
||||
CALIBRATED_STICK4,
|
||||
CALIBRATED_POT_FIRST,
|
||||
CALIBRATED_POT1 = CALIBRATED_POT_FIRST,
|
||||
CALIBRATED_POT2,
|
||||
CALIBRATED_POT3,
|
||||
CALIBRATED_POT_LAST = CALIBRATED_POT3,
|
||||
NUM_CALIBRATED_ANALOGS
|
||||
};
|
||||
#define IS_POT(x) ((x)>=POT_FIRST && (x)<=POT_LAST)
|
||||
#define IS_SLIDER(x) false
|
||||
void adcInit();
|
||||
void adcRead(void);
|
||||
uint16_t getAnalogValue(uint8_t index);
|
||||
uint16_t getBatteryVoltage(); // returns current battery voltage in 10mV steps
|
||||
void setSticksGain(uint8_t gains);
|
||||
|
||||
// Buzzer driver
|
||||
void buzzerSound(uint8_t duration);
|
||||
void buzzerHeartbeat();
|
||||
#define BUZZER_HEARTBEAT buzzerHeartbeat
|
||||
|
||||
// i2c driver
|
||||
void i2cCheck();
|
||||
|
||||
// Coproc driver
|
||||
void coprocInit();
|
||||
void coprocWriteData(uint8_t *data, uint32_t size);
|
||||
#if defined(__cplusplus)
|
||||
void coprocReadData(bool onlytemp=false);
|
||||
#endif
|
||||
extern int8_t volumeRequired;
|
||||
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
|
||||
#define TRAINER_PWR
|
||||
#if !defined(REVA)
|
||||
#define SOFT_PWR_CTRL
|
||||
#endif
|
||||
void pwrInit();
|
||||
void pwrOff();
|
||||
uint32_t pwrCheck();
|
||||
uint32_t pwrPressed();
|
||||
#define UNEXPECTED_SHUTDOWN() (g_eeGeneral.unexpectedShutdown)
|
||||
|
||||
// EEPROM driver
|
||||
#define EEPROM_SIZE (4*1024*1024/8)
|
||||
#define EEPROM_BLOCK_SIZE (4*1024)
|
||||
void eepromInit();
|
||||
uint8_t eepromReadStatus();
|
||||
uint8_t eepromIsTransferComplete(void);
|
||||
void eepromBlockErase(uint32_t address);
|
||||
void eepromStartRead(uint8_t * buffer, size_t address, size_t size);
|
||||
void eepromStartWrite(uint8_t * buffer, size_t address, size_t size);
|
||||
|
||||
// Debug driver
|
||||
void debugPutc(const char c);
|
||||
|
||||
// Telemetry driver
|
||||
void telemetryPortInit(uint32_t baudrate, uint8_t mode);
|
||||
uint32_t telemetryTransmitPending();
|
||||
void telemetryTransmitBuffer(uint8_t * buffer, uint32_t size);
|
||||
void rxPdcUsart( void (*pChProcess)(uint8_t x) );
|
||||
|
||||
// Second UART driver
|
||||
void serial2TelemetryInit(unsigned int protocol);
|
||||
#if defined(__cplusplus)
|
||||
bool telemetrySecondPortReceive(uint8_t & data);
|
||||
#endif
|
||||
|
||||
extern const uint8_t BootCode[];
|
||||
|
||||
#endif // _BOARD_SKY9X_H_
|
||||
|
||||
@@ -1,253 +1,253 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \par Purpose
|
||||
*
|
||||
* Provides the low-level initialization function that gets called on chip startup.
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "board_lowlevel.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
|
||||
|
||||
uint32_t timeout = 0 ;
|
||||
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()
|
||||
{
|
||||
uint32_t timeout = 0;
|
||||
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
|
||||
}
|
||||
|
||||
#if defined(BOOT)
|
||||
// extern void sam_bootx( void ) ;
|
||||
// extern void dispUSB( void ) ;
|
||||
// extern uint32_t init
|
||||
// ReadTrims( void ) ;
|
||||
// extern void run_application( void ) ;
|
||||
|
||||
static void lowLevelUsbCheck( void )
|
||||
{
|
||||
PMC->PMC_PCER0 = (1<<ID_PIOC) ; // Enable clock to PIOC
|
||||
PIOC->PIO_PER = PIO_PC25 ; // Enable bit C25 (USB-detect)
|
||||
|
||||
uint32_t i ;
|
||||
for ( i = 0 ; i < 50 ; i += 1 ) {
|
||||
__asm("nop") ;
|
||||
}
|
||||
|
||||
for ( i = 0 ; i < 10 ; i += 1 ) {
|
||||
if ( PIOC->PIO_PDSR & 0x02000000 ) {
|
||||
PMC->PMC_PCDR0 = (1<<ID_PIOC) ; // Disable clock to PIOC
|
||||
dispUSB() ;
|
||||
sam_bootx() ;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t x = initReadTrims() ;
|
||||
if ((x & 0x42) != 0x42) {
|
||||
run_application();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Performs the low-level initialization of the chip. This includes EFC,
|
||||
* master clock and watchdog configuration.
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
uint32_t SystemInit (void)
|
||||
{
|
||||
#if defined(BOOT)
|
||||
lowLevelUsbCheck() ;
|
||||
#endif
|
||||
|
||||
// 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();
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \par Purpose
|
||||
*
|
||||
* Provides the low-level initialization function that gets called on chip startup.
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "board_lowlevel.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
|
||||
|
||||
uint32_t timeout = 0 ;
|
||||
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()
|
||||
{
|
||||
uint32_t timeout = 0;
|
||||
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
|
||||
}
|
||||
|
||||
#if defined(BOOT)
|
||||
// extern void sam_bootx( void ) ;
|
||||
// extern void dispUSB( void ) ;
|
||||
// extern uint32_t init
|
||||
// ReadTrims( void ) ;
|
||||
// extern void run_application( void ) ;
|
||||
|
||||
static void lowLevelUsbCheck( void )
|
||||
{
|
||||
PMC->PMC_PCER0 = (1<<ID_PIOC) ; // Enable clock to PIOC
|
||||
PIOC->PIO_PER = PIO_PC25 ; // Enable bit C25 (USB-detect)
|
||||
|
||||
uint32_t i ;
|
||||
for ( i = 0 ; i < 50 ; i += 1 ) {
|
||||
__asm("nop") ;
|
||||
}
|
||||
|
||||
for ( i = 0 ; i < 10 ; i += 1 ) {
|
||||
if ( PIOC->PIO_PDSR & 0x02000000 ) {
|
||||
PMC->PMC_PCDR0 = (1<<ID_PIOC) ; // Disable clock to PIOC
|
||||
dispUSB() ;
|
||||
sam_bootx() ;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t x = initReadTrims() ;
|
||||
if ((x & 0x42) != 0x42) {
|
||||
run_application();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Performs the low-level initialization of the chip. This includes EFC,
|
||||
* master clock and watchdog configuration.
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
uint32_t SystemInit (void)
|
||||
{
|
||||
#if defined(BOOT)
|
||||
lowLevelUsbCheck() ;
|
||||
#endif
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,59 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,104 +18,104 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \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".
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \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
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 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 // _CHIP_H_
|
||||
|
||||
|
||||
|
||||
@@ -1,205 +1,205 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 volumeRequired ;
|
||||
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;
|
||||
#if !defined(SIMU)
|
||||
// TODO not used? static uint8_t *Twi_read_address ;
|
||||
#endif
|
||||
static uint8_t TwiOperation ;
|
||||
|
||||
#define TWI_NONE 0
|
||||
#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 i2cCheck()
|
||||
{
|
||||
if ( TWI0->TWI_IMR & TWI_IMR_TXCOMP ) {
|
||||
return ; // Busy
|
||||
}
|
||||
|
||||
if ( volumeRequired >= 0 ) { // Set volume to this value
|
||||
TWI0->TWI_MMR = 0x002F0000 ; // Device 5E (>>1) and master is writing
|
||||
TwiOperation = TWI_WRITE_VOL ;
|
||||
TWI0->TWI_THR = volumeRequired ; // Send data
|
||||
volumeRequired = -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 ( 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() ;
|
||||
i2cCheck() ;
|
||||
__enable_irq() ;
|
||||
}
|
||||
|
||||
void coprocWriteData(uint8_t *data, uint32_t size)
|
||||
{
|
||||
coprocWriteDataPtr = data;
|
||||
coprocWriteDataSize = size;
|
||||
coprocWriteDataPending = 1;
|
||||
__disable_irq();
|
||||
i2cCheck();
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
#if !defined(SIMU)
|
||||
extern "C" void TWI0_IRQHandler()
|
||||
{
|
||||
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 )) - TM_YEAR_BASE;
|
||||
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 ;
|
||||
i2cCheck() ;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 volumeRequired ;
|
||||
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;
|
||||
#if !defined(SIMU)
|
||||
// TODO not used? static uint8_t *Twi_read_address ;
|
||||
#endif
|
||||
static uint8_t TwiOperation ;
|
||||
|
||||
#define TWI_NONE 0
|
||||
#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 i2cCheck()
|
||||
{
|
||||
if ( TWI0->TWI_IMR & TWI_IMR_TXCOMP ) {
|
||||
return ; // Busy
|
||||
}
|
||||
|
||||
if ( volumeRequired >= 0 ) { // Set volume to this value
|
||||
TWI0->TWI_MMR = 0x002F0000 ; // Device 5E (>>1) and master is writing
|
||||
TwiOperation = TWI_WRITE_VOL ;
|
||||
TWI0->TWI_THR = volumeRequired ; // Send data
|
||||
volumeRequired = -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 ( 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() ;
|
||||
i2cCheck() ;
|
||||
__enable_irq() ;
|
||||
}
|
||||
|
||||
void coprocWriteData(uint8_t *data, uint32_t size)
|
||||
{
|
||||
coprocWriteDataPtr = data;
|
||||
coprocWriteDataSize = size;
|
||||
coprocWriteDataPending = 1;
|
||||
__disable_irq();
|
||||
i2cCheck();
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
#if !defined(SIMU)
|
||||
extern "C" void TWI0_IRQHandler()
|
||||
{
|
||||
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 )) - TM_YEAR_BASE;
|
||||
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 ;
|
||||
i2cCheck() ;
|
||||
}
|
||||
#endif
|
||||
|
||||
+848
-848
File diff suppressed because it is too large
Load Diff
+1792
-1792
File diff suppressed because it is too large
Load Diff
+131
-131
@@ -1,131 +1,131 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 __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)
|
||||
{
|
||||
{
|
||||
uint32_t *pSrc;
|
||||
uint32_t *pDest;
|
||||
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 ***/
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 __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)
|
||||
{
|
||||
{
|
||||
uint32_t *pSrc;
|
||||
uint32_t *pDest;
|
||||
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 ***/
|
||||
|
||||
+1380
-1380
File diff suppressed because it is too large
Load Diff
@@ -1,200 +1,200 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 Spi_complete = 1;
|
||||
uint8_t Spi_tx_buf[24];
|
||||
|
||||
uint8_t eepromIsTransferComplete()
|
||||
{
|
||||
return Spi_complete;
|
||||
}
|
||||
|
||||
uint32_t eepromTransmitData(uint8_t *command, uint8_t *tx, uint8_t *rx, uint32_t comlen, uint32_t count)
|
||||
{
|
||||
Spi * spiptr = SPI;
|
||||
uint32_t condition;
|
||||
static uint8_t discard_rx_command[4];
|
||||
|
||||
if (comlen > 4) {
|
||||
return 0x4FFFF;
|
||||
}
|
||||
|
||||
Spi_complete = 0;
|
||||
condition = SPI_SR_TXEMPTY;
|
||||
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;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t eepromTransmitByte(uint8_t out, bool skipFirst)
|
||||
{
|
||||
Spi * spiptr = SPI;
|
||||
uint32_t delay;
|
||||
|
||||
spiptr->SPI_CR = 1; // Enable
|
||||
(void) spiptr->SPI_RDR; // Dump any rx data
|
||||
|
||||
spiptr->SPI_TDR = out;
|
||||
|
||||
delay = 0;
|
||||
while ((spiptr->SPI_SR & SPI_SR_RDRF) == 0) {
|
||||
// wait for received
|
||||
if (++delay > 10000) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (skipFirst) {
|
||||
(void) spiptr->SPI_RDR; // Dump the rx data
|
||||
spiptr->SPI_TDR = 0;
|
||||
delay = 0;
|
||||
while ((spiptr->SPI_SR & SPI_SR_RDRF) == 0) {
|
||||
// wait for received
|
||||
if (++delay > 10000) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spiptr->SPI_CR = 2; // Disable
|
||||
return spiptr->SPI_RDR;
|
||||
}
|
||||
|
||||
enum EepromCommand {
|
||||
COMMAND_WRITE_STATUS_REGISTER = 0x01,
|
||||
COMMAND_BYTE_PROGRAM = 0x02,
|
||||
COMMAND_READ_ARRAY = 0x03,
|
||||
COMMAND_READ_STATUS = 0x05,
|
||||
COMMAND_WRITE_ENABLE = 0x06,
|
||||
COMMAND_BLOCK_ERASE = 0x20,
|
||||
};
|
||||
|
||||
void eepromPrepareCommand(EepromCommand command, uint32_t address)
|
||||
{
|
||||
uint8_t * p = Spi_tx_buf;
|
||||
*p = command;
|
||||
*(p+1) = address >> 16;
|
||||
*(p+2) = address >> 8;
|
||||
*(p+3) = address;
|
||||
}
|
||||
|
||||
uint8_t eepromReadStatus()
|
||||
{
|
||||
uint8_t read_status = eepromTransmitByte(COMMAND_READ_STATUS, true);
|
||||
return !(read_status & 1);
|
||||
}
|
||||
|
||||
void eepromWriteStatusRegister()
|
||||
{
|
||||
eepromTransmitByte(COMMAND_WRITE_STATUS_REGISTER, true);
|
||||
}
|
||||
|
||||
void eepromWriteEnable()
|
||||
{
|
||||
eepromTransmitByte(COMMAND_WRITE_ENABLE, false);
|
||||
}
|
||||
|
||||
void eepromStartWrite(uint8_t * buffer, size_t address, size_t size)
|
||||
{
|
||||
eepromWriteEnable();
|
||||
eepromPrepareCommand(COMMAND_BYTE_PROGRAM, address);
|
||||
eepromTransmitData(Spi_tx_buf, buffer, 0, 4, size);
|
||||
}
|
||||
|
||||
void eepromStartRead(uint8_t * buffer, size_t address, size_t size)
|
||||
{
|
||||
eepromPrepareCommand(COMMAND_READ_ARRAY, address);
|
||||
eepromTransmitData(Spi_tx_buf, 0, buffer, 4, size);
|
||||
}
|
||||
|
||||
void eepromBlockErase(uint32_t address)
|
||||
{
|
||||
eepromWriteEnable();
|
||||
eepromPrepareCommand(COMMAND_BLOCK_ERASE, address);
|
||||
eepromTransmitData(Spi_tx_buf, 0, 0, 4, 0);
|
||||
}
|
||||
|
||||
// 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()
|
||||
{
|
||||
Spi * spiptr = SPI;
|
||||
uint32_t timer;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
eepromWriteEnable();
|
||||
eepromWriteStatusRegister();
|
||||
}
|
||||
|
||||
extern "C" void SPI_IRQHandler()
|
||||
{
|
||||
Spi * 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
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 Spi_complete = 1;
|
||||
uint8_t Spi_tx_buf[24];
|
||||
|
||||
uint8_t eepromIsTransferComplete()
|
||||
{
|
||||
return Spi_complete;
|
||||
}
|
||||
|
||||
uint32_t eepromTransmitData(uint8_t *command, uint8_t *tx, uint8_t *rx, uint32_t comlen, uint32_t count)
|
||||
{
|
||||
Spi * spiptr = SPI;
|
||||
uint32_t condition;
|
||||
static uint8_t discard_rx_command[4];
|
||||
|
||||
if (comlen > 4) {
|
||||
return 0x4FFFF;
|
||||
}
|
||||
|
||||
Spi_complete = 0;
|
||||
condition = SPI_SR_TXEMPTY;
|
||||
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;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t eepromTransmitByte(uint8_t out, bool skipFirst)
|
||||
{
|
||||
Spi * spiptr = SPI;
|
||||
uint32_t delay;
|
||||
|
||||
spiptr->SPI_CR = 1; // Enable
|
||||
(void) spiptr->SPI_RDR; // Dump any rx data
|
||||
|
||||
spiptr->SPI_TDR = out;
|
||||
|
||||
delay = 0;
|
||||
while ((spiptr->SPI_SR & SPI_SR_RDRF) == 0) {
|
||||
// wait for received
|
||||
if (++delay > 10000) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (skipFirst) {
|
||||
(void) spiptr->SPI_RDR; // Dump the rx data
|
||||
spiptr->SPI_TDR = 0;
|
||||
delay = 0;
|
||||
while ((spiptr->SPI_SR & SPI_SR_RDRF) == 0) {
|
||||
// wait for received
|
||||
if (++delay > 10000) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spiptr->SPI_CR = 2; // Disable
|
||||
return spiptr->SPI_RDR;
|
||||
}
|
||||
|
||||
enum EepromCommand {
|
||||
COMMAND_WRITE_STATUS_REGISTER = 0x01,
|
||||
COMMAND_BYTE_PROGRAM = 0x02,
|
||||
COMMAND_READ_ARRAY = 0x03,
|
||||
COMMAND_READ_STATUS = 0x05,
|
||||
COMMAND_WRITE_ENABLE = 0x06,
|
||||
COMMAND_BLOCK_ERASE = 0x20,
|
||||
};
|
||||
|
||||
void eepromPrepareCommand(EepromCommand command, uint32_t address)
|
||||
{
|
||||
uint8_t * p = Spi_tx_buf;
|
||||
*p = command;
|
||||
*(p+1) = address >> 16;
|
||||
*(p+2) = address >> 8;
|
||||
*(p+3) = address;
|
||||
}
|
||||
|
||||
uint8_t eepromReadStatus()
|
||||
{
|
||||
uint8_t read_status = eepromTransmitByte(COMMAND_READ_STATUS, true);
|
||||
return !(read_status & 1);
|
||||
}
|
||||
|
||||
void eepromWriteStatusRegister()
|
||||
{
|
||||
eepromTransmitByte(COMMAND_WRITE_STATUS_REGISTER, true);
|
||||
}
|
||||
|
||||
void eepromWriteEnable()
|
||||
{
|
||||
eepromTransmitByte(COMMAND_WRITE_ENABLE, false);
|
||||
}
|
||||
|
||||
void eepromStartWrite(uint8_t * buffer, size_t address, size_t size)
|
||||
{
|
||||
eepromWriteEnable();
|
||||
eepromPrepareCommand(COMMAND_BYTE_PROGRAM, address);
|
||||
eepromTransmitData(Spi_tx_buf, buffer, 0, 4, size);
|
||||
}
|
||||
|
||||
void eepromStartRead(uint8_t * buffer, size_t address, size_t size)
|
||||
{
|
||||
eepromPrepareCommand(COMMAND_READ_ARRAY, address);
|
||||
eepromTransmitData(Spi_tx_buf, 0, buffer, 4, size);
|
||||
}
|
||||
|
||||
void eepromBlockErase(uint32_t address)
|
||||
{
|
||||
eepromWriteEnable();
|
||||
eepromPrepareCommand(COMMAND_BLOCK_ERASE, address);
|
||||
eepromTransmitData(Spi_tx_buf, 0, 0, 4, 0);
|
||||
}
|
||||
|
||||
// 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()
|
||||
{
|
||||
Spi * spiptr = SPI;
|
||||
uint32_t timer;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
eepromWriteEnable();
|
||||
eepromWriteStatusRegister();
|
||||
}
|
||||
|
||||
extern "C" void SPI_IRQHandler()
|
||||
{
|
||||
Spi * 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
|
||||
}
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 )
|
||||
{
|
||||
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
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 )
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
@@ -1,197 +1,197 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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()
|
||||
{
|
||||
uint32_t x;
|
||||
uint32_t result = 0;
|
||||
|
||||
x = lcdLock ? lcdInputs : PIOC->PIO_PDSR; // 6 LEFT, 5 RIGHT, 4 DOWN, 3 UP ()
|
||||
x = ~x;
|
||||
|
||||
#if defined(REVA)
|
||||
if (x & KEYS_GPIO_PIN_RIGHT)
|
||||
result |= 0x02 << KEY_RIGHT;
|
||||
if (x & KEYS_GPIO_PIN_LEFT)
|
||||
result |= 0x02 << KEY_LEFT;
|
||||
if (x & KEYS_GPIO_PIN_UP)
|
||||
result |= 0x02 << KEY_UP;
|
||||
if (x & KEYS_GPIO_PIN_DOWN)
|
||||
result |= 0x02 << KEY_DOWN;
|
||||
if (~KEYS_GPIO_REG_EXIT & KEYS_GPIO_PIN_EXIT)
|
||||
result |= 0x02 << KEY_EXIT;
|
||||
if (~KEYS_GPIO_REG_MENU & KEYS_GPIO_PIN_MENU)
|
||||
result |= 0x02 << KEY_MENU;
|
||||
#else
|
||||
if (x & KEYS_GPIO_PIN_RIGHT)
|
||||
result |= 0x02 << KEY_RIGHT;
|
||||
if (x & KEYS_GPIO_PIN_UP)
|
||||
result |= 0x02 << KEY_UP;
|
||||
if (x & KEYS_GPIO_PIN_LEFT)
|
||||
result |= 0x02 << KEY_LEFT;
|
||||
if (x & KEYS_GPIO_PIN_DOWN)
|
||||
result |= 0x02 << KEY_DOWN;
|
||||
if (x & KEYS_GPIO_PIN_EXIT)
|
||||
result |= 0x02 << KEY_EXIT;
|
||||
if (~KEYS_GPIO_REG_MENU & KEYS_GPIO_PIN_MENU)
|
||||
result |= 0x02 << KEY_MENU;
|
||||
#endif
|
||||
|
||||
// TRACE("readKeys(): %x => %x", x, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t readTrims()
|
||||
{
|
||||
uint32_t result = 0;
|
||||
|
||||
if (~TRIMS_GPIO_REG_LHL & TRIMS_GPIO_PIN_LHL)
|
||||
result |= 0x01;
|
||||
if (~TRIMS_GPIO_REG_LVD & TRIMS_GPIO_PIN_LVD)
|
||||
result |= 0x04;
|
||||
if (~TRIMS_GPIO_REG_RVU & TRIMS_GPIO_PIN_RVU)
|
||||
result |= 0x20;
|
||||
if (~TRIMS_GPIO_REG_RHL & TRIMS_GPIO_PIN_RHL)
|
||||
result |= 0x40;
|
||||
if (~TRIMS_GPIO_REG_LHR & TRIMS_GPIO_PIN_LHR)
|
||||
result |= 0x02;
|
||||
if (~TRIMS_GPIO_REG_LVU & TRIMS_GPIO_PIN_LVU)
|
||||
result |= 0x08;
|
||||
if (~TRIMS_GPIO_REG_RVD & TRIMS_GPIO_PIN_RVD)
|
||||
result |= 0x10;
|
||||
if (~TRIMS_GPIO_REG_RHR & TRIMS_GPIO_PIN_RHR)
|
||||
result |= 0x80;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t trimDown(uint8_t idx)
|
||||
{
|
||||
return readTrims() & (1 << idx);
|
||||
}
|
||||
|
||||
uint8_t keyDown()
|
||||
{
|
||||
return readKeys() || REA_DOWN();
|
||||
}
|
||||
|
||||
void readKeysAndTrims()
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
#if ROTARY_ENCODERS > 0
|
||||
keys[BTN_REa].input(REA_DOWN());
|
||||
#endif
|
||||
|
||||
uint8_t index = KEY_MENU;
|
||||
uint8_t in = readKeys();
|
||||
for (i = 1; i < 7; i++) {
|
||||
keys[index].input(in & (1 << i));
|
||||
++index;
|
||||
}
|
||||
|
||||
in = readTrims();
|
||||
|
||||
for (i = 1; i < 256; i <<= 1) {
|
||||
keys[index].input(in & i);
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t keyState(uint8_t index)
|
||||
{
|
||||
return keys[index].state();
|
||||
}
|
||||
|
||||
uint32_t switchState(uint8_t index)
|
||||
{
|
||||
uint32_t a = PIOA->PIO_PDSR;
|
||||
uint32_t c = PIOC->PIO_PDSR;
|
||||
|
||||
uint32_t xxx = 0;
|
||||
|
||||
switch (index) {
|
||||
#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;
|
||||
|
||||
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;
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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()
|
||||
{
|
||||
uint32_t x;
|
||||
uint32_t result = 0;
|
||||
|
||||
x = lcdLock ? lcdInputs : PIOC->PIO_PDSR; // 6 LEFT, 5 RIGHT, 4 DOWN, 3 UP ()
|
||||
x = ~x;
|
||||
|
||||
#if defined(REVA)
|
||||
if (x & KEYS_GPIO_PIN_RIGHT)
|
||||
result |= 0x02 << KEY_RIGHT;
|
||||
if (x & KEYS_GPIO_PIN_LEFT)
|
||||
result |= 0x02 << KEY_LEFT;
|
||||
if (x & KEYS_GPIO_PIN_UP)
|
||||
result |= 0x02 << KEY_UP;
|
||||
if (x & KEYS_GPIO_PIN_DOWN)
|
||||
result |= 0x02 << KEY_DOWN;
|
||||
if (~KEYS_GPIO_REG_EXIT & KEYS_GPIO_PIN_EXIT)
|
||||
result |= 0x02 << KEY_EXIT;
|
||||
if (~KEYS_GPIO_REG_MENU & KEYS_GPIO_PIN_MENU)
|
||||
result |= 0x02 << KEY_MENU;
|
||||
#else
|
||||
if (x & KEYS_GPIO_PIN_RIGHT)
|
||||
result |= 0x02 << KEY_RIGHT;
|
||||
if (x & KEYS_GPIO_PIN_UP)
|
||||
result |= 0x02 << KEY_UP;
|
||||
if (x & KEYS_GPIO_PIN_LEFT)
|
||||
result |= 0x02 << KEY_LEFT;
|
||||
if (x & KEYS_GPIO_PIN_DOWN)
|
||||
result |= 0x02 << KEY_DOWN;
|
||||
if (x & KEYS_GPIO_PIN_EXIT)
|
||||
result |= 0x02 << KEY_EXIT;
|
||||
if (~KEYS_GPIO_REG_MENU & KEYS_GPIO_PIN_MENU)
|
||||
result |= 0x02 << KEY_MENU;
|
||||
#endif
|
||||
|
||||
// TRACE("readKeys(): %x => %x", x, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t readTrims()
|
||||
{
|
||||
uint32_t result = 0;
|
||||
|
||||
if (~TRIMS_GPIO_REG_LHL & TRIMS_GPIO_PIN_LHL)
|
||||
result |= 0x01;
|
||||
if (~TRIMS_GPIO_REG_LVD & TRIMS_GPIO_PIN_LVD)
|
||||
result |= 0x04;
|
||||
if (~TRIMS_GPIO_REG_RVU & TRIMS_GPIO_PIN_RVU)
|
||||
result |= 0x20;
|
||||
if (~TRIMS_GPIO_REG_RHL & TRIMS_GPIO_PIN_RHL)
|
||||
result |= 0x40;
|
||||
if (~TRIMS_GPIO_REG_LHR & TRIMS_GPIO_PIN_LHR)
|
||||
result |= 0x02;
|
||||
if (~TRIMS_GPIO_REG_LVU & TRIMS_GPIO_PIN_LVU)
|
||||
result |= 0x08;
|
||||
if (~TRIMS_GPIO_REG_RVD & TRIMS_GPIO_PIN_RVD)
|
||||
result |= 0x10;
|
||||
if (~TRIMS_GPIO_REG_RHR & TRIMS_GPIO_PIN_RHR)
|
||||
result |= 0x80;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t trimDown(uint8_t idx)
|
||||
{
|
||||
return readTrims() & (1 << idx);
|
||||
}
|
||||
|
||||
uint8_t keyDown()
|
||||
{
|
||||
return readKeys() || REA_DOWN();
|
||||
}
|
||||
|
||||
void readKeysAndTrims()
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
#if ROTARY_ENCODERS > 0
|
||||
keys[BTN_REa].input(REA_DOWN());
|
||||
#endif
|
||||
|
||||
uint8_t index = KEY_MENU;
|
||||
uint8_t in = readKeys();
|
||||
for (i = 1; i < 7; i++) {
|
||||
keys[index].input(in & (1 << i));
|
||||
++index;
|
||||
}
|
||||
|
||||
in = readTrims();
|
||||
|
||||
for (i = 1; i < 256; i <<= 1) {
|
||||
keys[index].input(in & i);
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t keyState(uint8_t index)
|
||||
{
|
||||
return keys[index].state();
|
||||
}
|
||||
|
||||
uint32_t switchState(uint8_t index)
|
||||
{
|
||||
uint32_t a = PIOA->PIO_PDSR;
|
||||
uint32_t c = PIOC->PIO_PDSR;
|
||||
|
||||
uint32_t xxx = 0;
|
||||
|
||||
switch (index) {
|
||||
#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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1,208 +1,208 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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);
|
||||
}
|
||||
|
||||
/** 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();
|
||||
logsClose();
|
||||
f_mount(NULL, "", 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
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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);
|
||||
}
|
||||
|
||||
/** 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();
|
||||
logsClose();
|
||||
f_mount(NULL, "", 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
|
||||
|
||||
@@ -1,367 +1,367 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 setExternalModulePolarity()
|
||||
{
|
||||
Pwm * pwmptr = PWM;
|
||||
pwmptr->PWM_CH_NUM[3].PWM_CDTYUPD = GET_PPM_DELAY(EXTERNAL_MODULE) * 2; // Duty in half uS
|
||||
if (GET_PPM_POLARITY(EXTERNAL_MODULE))
|
||||
pwmptr->PWM_CH_NUM[3].PWM_CMR &= ~0x00000200; // CPOL
|
||||
else
|
||||
pwmptr->PWM_CH_NUM[3].PWM_CMR |= 0x00000200; // CPOL
|
||||
}
|
||||
|
||||
void setExtraModulePolarity()
|
||||
{
|
||||
Pwm * pwmptr = PWM;
|
||||
pwmptr->PWM_CH_NUM[1].PWM_CDTYUPD = GET_PPM_DELAY(EXTRA_MODULE) * 2; // Duty in half uS
|
||||
if (GET_PPM_POLARITY(EXTRA_MODULE))
|
||||
pwmptr->PWM_CH_NUM[1].PWM_CMR &= ~0x00000200; // CPOL
|
||||
else
|
||||
pwmptr->PWM_CH_NUM[1].PWM_CMR |= 0x00000200; // CPOL
|
||||
}
|
||||
|
||||
void module_output_active()
|
||||
{
|
||||
Pio *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
|
||||
#if defined(REVX)
|
||||
if (g_model.moduleData[EXTERNAL_MODULE].ppm.outputType) {
|
||||
pioptr->PIO_MDDR = PIO_PA17; // Push Pull O/p in A17
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 setExternalModulePolarity()
|
||||
{
|
||||
Pwm * pwmptr = PWM;
|
||||
pwmptr->PWM_CH_NUM[3].PWM_CDTYUPD = GET_PPM_DELAY(EXTERNAL_MODULE) * 2; // Duty in half uS
|
||||
if (GET_PPM_POLARITY(EXTERNAL_MODULE))
|
||||
pwmptr->PWM_CH_NUM[3].PWM_CMR &= ~0x00000200; // CPOL
|
||||
else
|
||||
pwmptr->PWM_CH_NUM[3].PWM_CMR |= 0x00000200; // CPOL
|
||||
}
|
||||
|
||||
void setExtraModulePolarity()
|
||||
{
|
||||
Pwm * pwmptr = PWM;
|
||||
pwmptr->PWM_CH_NUM[1].PWM_CDTYUPD = GET_PPM_DELAY(EXTRA_MODULE) * 2; // Duty in half uS
|
||||
if (GET_PPM_POLARITY(EXTRA_MODULE))
|
||||
pwmptr->PWM_CH_NUM[1].PWM_CMR &= ~0x00000200; // CPOL
|
||||
else
|
||||
pwmptr->PWM_CH_NUM[1].PWM_CMR |= 0x00000200; // CPOL
|
||||
}
|
||||
|
||||
void module_output_active()
|
||||
{
|
||||
Pio *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
|
||||
#if defined(REVX)
|
||||
if (g_model.moduleData[EXTERNAL_MODULE].ppm.outputType) {
|
||||
pioptr->PIO_MDDR = PIO_PA17; // Push Pull O/p in A17
|
||||
}
|
||||
else {
|
||||
pioptr->PIO_MDER = PIO_PA17; // Open Drain O/p in A17
|
||||
}
|
||||
#else
|
||||
pioptr->PIO_MDDR = PIO_PA17; // Push Pull O/p in A17
|
||||
#endif
|
||||
pioptr->PIO_PUER = PIO_PA17; // With pull up
|
||||
}
|
||||
|
||||
void init_main_ppm(uint32_t period, uint32_t out_enable)
|
||||
{
|
||||
Pwm * pwmptr;
|
||||
|
||||
setupPulsesPPMModule(EXTERNAL_MODULE);
|
||||
|
||||
if (out_enable) {
|
||||
module_output_active();
|
||||
}
|
||||
|
||||
pwmptr = PWM;
|
||||
// PWM3 for PPM output
|
||||
pwmptr->PWM_CH_NUM[3].PWM_CMR = 0x0004000B; // CLKA
|
||||
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 = GET_PPM_DELAY(EXTERNAL_MODULE) * 2; // Duty in half uS
|
||||
pwmptr->PWM_ENA = PWM_ENA_CHID3; // Enable channel 3
|
||||
pwmptr->PWM_IER1 = PWM_IER1_CHID3;
|
||||
|
||||
setExternalModulePolarity();
|
||||
|
||||
NVIC_SetPriority(PWM_IRQn, 3);
|
||||
NVIC_EnableIRQ(PWM_IRQn);
|
||||
}
|
||||
|
||||
void disable_main_ppm()
|
||||
{
|
||||
Pio * pioptr = PIOA;
|
||||
pioptr->PIO_PER = PIO_PA17; // Assign A17 to PIO
|
||||
PWM->PWM_IDR1 = PWM_IDR1_CHID3;
|
||||
}
|
||||
|
||||
void init_second_ppm(uint32_t period)
|
||||
{
|
||||
#if !defined(REVA)
|
||||
// PWM1 for PPM2
|
||||
Pwm * pwmptr = PWM;
|
||||
configure_pins(PIO_PC15, PIN_PERIPHERAL | PIN_INPUT | PIN_PER_B | PIN_PORTC | PIN_NO_PULLUP);
|
||||
pwmptr->PWM_CH_NUM[1].PWM_CMR = 0x0000000B; // CLKB
|
||||
if (!GET_PPM_POLARITY(EXTRA_MODULE)) {
|
||||
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 = GET_PPM_DELAY(EXTRA_MODULE)*2; // Duty
|
||||
pwmptr->PWM_CH_NUM[1].PWM_CDTYUPD = GET_PPM_DELAY(EXTRA_MODULE)*2; // Duty
|
||||
pwmptr->PWM_ENA = PWM_ENA_CHID1; // Enable channel 1
|
||||
pwmptr->PWM_IER1 = PWM_IER1_CHID1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void disable_second_ppm()
|
||||
{
|
||||
#if !defined(REVA)
|
||||
Pio * pioptr = PIOC;
|
||||
pioptr->PIO_PER = PIO_PC15; // Assign C17 to PIO
|
||||
PWM->PWM_IDR1 = PWM_IDR1_CHID1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void init_no_pulses(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
init_main_ppm(3000, 0);
|
||||
}
|
||||
else {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
void disable_no_pulses(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
disable_ppm(EXTERNAL_MODULE);
|
||||
}
|
||||
else {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
void init_ppm(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
init_main_ppm(3000, 1);
|
||||
}
|
||||
else {
|
||||
init_second_ppm(3000);
|
||||
}
|
||||
}
|
||||
|
||||
void disable_ppm(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
disable_main_ppm();
|
||||
}
|
||||
else {
|
||||
disable_second_ppm();
|
||||
}
|
||||
}
|
||||
|
||||
// Initialise the SSC to allow PXX output.
|
||||
// TD is on PA17, peripheral A
|
||||
void init_ssc(uint8_t baudrateDiv1000)
|
||||
{
|
||||
Ssc *sscptr;
|
||||
|
||||
PMC->PMC_PCER0 |= 0x00400000L; // Enable peripheral clock to SSC
|
||||
|
||||
configure_pins(PIO_PA17, PIN_PERIPHERAL | PIN_INPUT | PIN_PER_A | PIN_PORTA);
|
||||
|
||||
sscptr = SSC;
|
||||
sscptr->SSC_THR = 0xFF; // Make the output high.
|
||||
sscptr->SSC_TFMR = 0x00000027; // 0000 0000 0000 0000 0000 0000 1010 0111 (8 bit data, lsb)
|
||||
sscptr->SSC_CMR = Master_frequency / (1000 * baudrateDiv1000 * 2);
|
||||
sscptr->SSC_TCMR = 0;
|
||||
sscptr->SSC_CR = SSC_CR_TXEN;
|
||||
|
||||
#if defined(REVX)
|
||||
if (IS_MODULE_MULTIMODULE(EXTERNAL_MODULE)) {
|
||||
PIOA->PIO_MDDR = PIO_PA17; // Push Pull O/p in A17
|
||||
} else {
|
||||
PIOA->PIO_MDER = PIO_PA17; // Open Drain O/p in A17
|
||||
}
|
||||
#else
|
||||
PIOA->PIO_MDDR = PIO_PA17; // Push Pull O/p in A17
|
||||
#endif
|
||||
}
|
||||
|
||||
void disable_ssc()
|
||||
{
|
||||
Pio *pioptr;
|
||||
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;
|
||||
}
|
||||
|
||||
void init_pxx(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
init_main_ppm(2500 * 2, 0);
|
||||
init_ssc(125); // 8us per bit
|
||||
}
|
||||
else {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
void disable_pxx(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
disable_ssc();
|
||||
disable_ppm(EXTERNAL_MODULE);
|
||||
}
|
||||
else {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
void init_dsm2(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
init_main_ppm(2500 * 2, 0);
|
||||
init_ssc(125);
|
||||
}
|
||||
else {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
void disable_dsm2(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
disable_ssc();
|
||||
disable_ppm(EXTERNAL_MODULE);
|
||||
}
|
||||
else {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(MULTIMODULE)
|
||||
void init_multimodule(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
init_main_ppm(3500 * 2, 0);
|
||||
init_ssc(100);
|
||||
}
|
||||
else {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
void disable_multimodule(uint32_t port)
|
||||
{
|
||||
disable_dsm2(port);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(SIMU)
|
||||
extern "C" void PWM_IRQHandler(void)
|
||||
{
|
||||
Pwm * pwmptr = PWM;
|
||||
uint32_t reason = pwmptr->PWM_ISR1;
|
||||
uint32_t period;
|
||||
|
||||
if (reason & PWM_ISR1_CHID3) {
|
||||
// Use the current protocol, don't switch until set_up_pulses
|
||||
switch (s_current_protocol[EXTERNAL_MODULE]) {
|
||||
case PROTO_PXX:
|
||||
// Alternate periods of 6.5mS and 2.5 mS
|
||||
period = pwmptr->PWM_CH_NUM[3].PWM_CPDR;
|
||||
if (period == 2500 * 2) {
|
||||
period = 6500 * 2;
|
||||
}
|
||||
else {
|
||||
period = 2500 * 2;
|
||||
}
|
||||
pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period; // Period in half uS
|
||||
if (period != 2500 * 2) {
|
||||
setupPulses(EXTERNAL_MODULE);
|
||||
setExternalModulePolarity();
|
||||
}
|
||||
else {
|
||||
// Kick off serial output here
|
||||
Ssc * sscptr = SSC;
|
||||
sscptr->SSC_TPR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].pxx.pulses);
|
||||
sscptr->SSC_TCR = (uint8_t *)modulePulsesData[EXTERNAL_MODULE].pxx.ptr - (uint8_t *)modulePulsesData[EXTERNAL_MODULE].pxx.pulses;
|
||||
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 == 2500 * 2) {
|
||||
period = 19500 * 2;
|
||||
}
|
||||
else {
|
||||
period = 2500 * 2;
|
||||
}
|
||||
pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period; // Period in half uS
|
||||
if (period != 2500 * 2) {
|
||||
setupPulses(EXTERNAL_MODULE);
|
||||
}
|
||||
else {
|
||||
// Kick off serial output here
|
||||
Ssc * sscptr = SSC;
|
||||
sscptr->SSC_TPR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].dsm2.pulses);
|
||||
sscptr->SSC_TCR = (uint8_t *)modulePulsesData[EXTERNAL_MODULE].dsm2.ptr - (uint8_t *)modulePulsesData[EXTERNAL_MODULE].dsm2.pulses;
|
||||
sscptr->SSC_PTCR = SSC_PTCR_TXTEN; // Start transfers
|
||||
}
|
||||
break;
|
||||
|
||||
#if defined(MULTIMODULE)
|
||||
case PROTO_MULTIMODULE:
|
||||
// Alternate periods of 5.5mS and 3.5 mS
|
||||
period = pwmptr->PWM_CH_NUM[3].PWM_CPDR;
|
||||
if (period == 3500 * 2) {
|
||||
period = 5500 * 2;
|
||||
}
|
||||
else {
|
||||
period = 3500 * 2;
|
||||
}
|
||||
pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period; // Period in half uS
|
||||
if (period != 3500 * 2) {
|
||||
setupPulses(EXTERNAL_MODULE);
|
||||
}
|
||||
else {
|
||||
// Kick off serial output here
|
||||
Ssc * sscptr = SSC;
|
||||
sscptr->SSC_TPR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].dsm2.pulses);
|
||||
sscptr->SSC_TCR = (uint8_t *)modulePulsesData[EXTERNAL_MODULE].dsm2.ptr - (uint8_t *)modulePulsesData[EXTERNAL_MODULE].dsm2.pulses;
|
||||
sscptr->SSC_PTCR = SSC_PTCR_TXTEN; // Start transfers
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = *modulePulsesData[EXTERNAL_MODULE].ppm.ptr++;
|
||||
if (*modulePulsesData[EXTERNAL_MODULE].ppm.ptr == 0) {
|
||||
setExternalModulePolarity();
|
||||
setupPulses(EXTERNAL_MODULE);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(REVA)
|
||||
if (reason & PWM_ISR1_CHID1) {
|
||||
pwmptr->PWM_CH_NUM[1].PWM_CPDRUPD = *modulePulsesData[EXTRA_MODULE].ppm.ptr++;
|
||||
if (*modulePulsesData[EXTRA_MODULE].ppm.ptr == 0) {
|
||||
setupPulsesPPMModule(EXTRA_MODULE);
|
||||
setExtraModulePolarity();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
pioptr->PIO_MDDR = PIO_PA17; // Push Pull O/p in A17
|
||||
#endif
|
||||
pioptr->PIO_PUER = PIO_PA17; // With pull up
|
||||
}
|
||||
|
||||
void init_main_ppm(uint32_t period, uint32_t out_enable)
|
||||
{
|
||||
Pwm * pwmptr;
|
||||
|
||||
setupPulsesPPMModule(EXTERNAL_MODULE);
|
||||
|
||||
if (out_enable) {
|
||||
module_output_active();
|
||||
}
|
||||
|
||||
pwmptr = PWM;
|
||||
// PWM3 for PPM output
|
||||
pwmptr->PWM_CH_NUM[3].PWM_CMR = 0x0004000B; // CLKA
|
||||
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 = GET_PPM_DELAY(EXTERNAL_MODULE) * 2; // Duty in half uS
|
||||
pwmptr->PWM_ENA = PWM_ENA_CHID3; // Enable channel 3
|
||||
pwmptr->PWM_IER1 = PWM_IER1_CHID3;
|
||||
|
||||
setExternalModulePolarity();
|
||||
|
||||
NVIC_SetPriority(PWM_IRQn, 3);
|
||||
NVIC_EnableIRQ(PWM_IRQn);
|
||||
}
|
||||
|
||||
void disable_main_ppm()
|
||||
{
|
||||
Pio * pioptr = PIOA;
|
||||
pioptr->PIO_PER = PIO_PA17; // Assign A17 to PIO
|
||||
PWM->PWM_IDR1 = PWM_IDR1_CHID3;
|
||||
}
|
||||
|
||||
void init_second_ppm(uint32_t period)
|
||||
{
|
||||
#if !defined(REVA)
|
||||
// PWM1 for PPM2
|
||||
Pwm * pwmptr = PWM;
|
||||
configure_pins(PIO_PC15, PIN_PERIPHERAL | PIN_INPUT | PIN_PER_B | PIN_PORTC | PIN_NO_PULLUP);
|
||||
pwmptr->PWM_CH_NUM[1].PWM_CMR = 0x0000000B; // CLKB
|
||||
if (!GET_PPM_POLARITY(EXTRA_MODULE)) {
|
||||
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 = GET_PPM_DELAY(EXTRA_MODULE)*2; // Duty
|
||||
pwmptr->PWM_CH_NUM[1].PWM_CDTYUPD = GET_PPM_DELAY(EXTRA_MODULE)*2; // Duty
|
||||
pwmptr->PWM_ENA = PWM_ENA_CHID1; // Enable channel 1
|
||||
pwmptr->PWM_IER1 = PWM_IER1_CHID1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void disable_second_ppm()
|
||||
{
|
||||
#if !defined(REVA)
|
||||
Pio * pioptr = PIOC;
|
||||
pioptr->PIO_PER = PIO_PC15; // Assign C17 to PIO
|
||||
PWM->PWM_IDR1 = PWM_IDR1_CHID1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void init_no_pulses(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
init_main_ppm(3000, 0);
|
||||
}
|
||||
else {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
void disable_no_pulses(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
disable_ppm(EXTERNAL_MODULE);
|
||||
}
|
||||
else {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
void init_ppm(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
init_main_ppm(3000, 1);
|
||||
}
|
||||
else {
|
||||
init_second_ppm(3000);
|
||||
}
|
||||
}
|
||||
|
||||
void disable_ppm(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
disable_main_ppm();
|
||||
}
|
||||
else {
|
||||
disable_second_ppm();
|
||||
}
|
||||
}
|
||||
|
||||
// Initialise the SSC to allow PXX output.
|
||||
// TD is on PA17, peripheral A
|
||||
void init_ssc(uint8_t baudrateDiv1000)
|
||||
{
|
||||
Ssc *sscptr;
|
||||
|
||||
PMC->PMC_PCER0 |= 0x00400000L; // Enable peripheral clock to SSC
|
||||
|
||||
configure_pins(PIO_PA17, PIN_PERIPHERAL | PIN_INPUT | PIN_PER_A | PIN_PORTA);
|
||||
|
||||
sscptr = SSC;
|
||||
sscptr->SSC_THR = 0xFF; // Make the output high.
|
||||
sscptr->SSC_TFMR = 0x00000027; // 0000 0000 0000 0000 0000 0000 1010 0111 (8 bit data, lsb)
|
||||
sscptr->SSC_CMR = Master_frequency / (1000 * baudrateDiv1000 * 2);
|
||||
sscptr->SSC_TCMR = 0;
|
||||
sscptr->SSC_CR = SSC_CR_TXEN;
|
||||
|
||||
#if defined(REVX)
|
||||
if (IS_MODULE_MULTIMODULE(EXTERNAL_MODULE)) {
|
||||
PIOA->PIO_MDDR = PIO_PA17; // Push Pull O/p in A17
|
||||
} else {
|
||||
PIOA->PIO_MDER = PIO_PA17; // Open Drain O/p in A17
|
||||
}
|
||||
#else
|
||||
PIOA->PIO_MDDR = PIO_PA17; // Push Pull O/p in A17
|
||||
#endif
|
||||
}
|
||||
|
||||
void disable_ssc()
|
||||
{
|
||||
Pio *pioptr;
|
||||
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;
|
||||
}
|
||||
|
||||
void init_pxx(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
init_main_ppm(2500 * 2, 0);
|
||||
init_ssc(125); // 8us per bit
|
||||
}
|
||||
else {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
void disable_pxx(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
disable_ssc();
|
||||
disable_ppm(EXTERNAL_MODULE);
|
||||
}
|
||||
else {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
void init_dsm2(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
init_main_ppm(2500 * 2, 0);
|
||||
init_ssc(125);
|
||||
}
|
||||
else {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
void disable_dsm2(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
disable_ssc();
|
||||
disable_ppm(EXTERNAL_MODULE);
|
||||
}
|
||||
else {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(MULTIMODULE)
|
||||
void init_multimodule(uint32_t port)
|
||||
{
|
||||
if (port == EXTERNAL_MODULE) {
|
||||
init_main_ppm(3500 * 2, 0);
|
||||
init_ssc(100);
|
||||
}
|
||||
else {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
void disable_multimodule(uint32_t port)
|
||||
{
|
||||
disable_dsm2(port);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(SIMU)
|
||||
extern "C" void PWM_IRQHandler(void)
|
||||
{
|
||||
Pwm * pwmptr = PWM;
|
||||
uint32_t reason = pwmptr->PWM_ISR1;
|
||||
uint32_t period;
|
||||
|
||||
if (reason & PWM_ISR1_CHID3) {
|
||||
// Use the current protocol, don't switch until set_up_pulses
|
||||
switch (s_current_protocol[EXTERNAL_MODULE]) {
|
||||
case PROTO_PXX:
|
||||
// Alternate periods of 6.5mS and 2.5 mS
|
||||
period = pwmptr->PWM_CH_NUM[3].PWM_CPDR;
|
||||
if (period == 2500 * 2) {
|
||||
period = 6500 * 2;
|
||||
}
|
||||
else {
|
||||
period = 2500 * 2;
|
||||
}
|
||||
pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period; // Period in half uS
|
||||
if (period != 2500 * 2) {
|
||||
setupPulses(EXTERNAL_MODULE);
|
||||
setExternalModulePolarity();
|
||||
}
|
||||
else {
|
||||
// Kick off serial output here
|
||||
Ssc * sscptr = SSC;
|
||||
sscptr->SSC_TPR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].pxx.pulses);
|
||||
sscptr->SSC_TCR = (uint8_t *)modulePulsesData[EXTERNAL_MODULE].pxx.ptr - (uint8_t *)modulePulsesData[EXTERNAL_MODULE].pxx.pulses;
|
||||
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 == 2500 * 2) {
|
||||
period = 19500 * 2;
|
||||
}
|
||||
else {
|
||||
period = 2500 * 2;
|
||||
}
|
||||
pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period; // Period in half uS
|
||||
if (period != 2500 * 2) {
|
||||
setupPulses(EXTERNAL_MODULE);
|
||||
}
|
||||
else {
|
||||
// Kick off serial output here
|
||||
Ssc * sscptr = SSC;
|
||||
sscptr->SSC_TPR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].dsm2.pulses);
|
||||
sscptr->SSC_TCR = (uint8_t *)modulePulsesData[EXTERNAL_MODULE].dsm2.ptr - (uint8_t *)modulePulsesData[EXTERNAL_MODULE].dsm2.pulses;
|
||||
sscptr->SSC_PTCR = SSC_PTCR_TXTEN; // Start transfers
|
||||
}
|
||||
break;
|
||||
|
||||
#if defined(MULTIMODULE)
|
||||
case PROTO_MULTIMODULE:
|
||||
// Alternate periods of 5.5mS and 3.5 mS
|
||||
period = pwmptr->PWM_CH_NUM[3].PWM_CPDR;
|
||||
if (period == 3500 * 2) {
|
||||
period = 5500 * 2;
|
||||
}
|
||||
else {
|
||||
period = 3500 * 2;
|
||||
}
|
||||
pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period; // Period in half uS
|
||||
if (period != 3500 * 2) {
|
||||
setupPulses(EXTERNAL_MODULE);
|
||||
}
|
||||
else {
|
||||
// Kick off serial output here
|
||||
Ssc * sscptr = SSC;
|
||||
sscptr->SSC_TPR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].dsm2.pulses);
|
||||
sscptr->SSC_TCR = (uint8_t *)modulePulsesData[EXTERNAL_MODULE].dsm2.ptr - (uint8_t *)modulePulsesData[EXTERNAL_MODULE].dsm2.pulses;
|
||||
sscptr->SSC_PTCR = SSC_PTCR_TXTEN; // Start transfers
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = *modulePulsesData[EXTERNAL_MODULE].ppm.ptr++;
|
||||
if (*modulePulsesData[EXTERNAL_MODULE].ppm.ptr == 0) {
|
||||
setExternalModulePolarity();
|
||||
setupPulses(EXTERNAL_MODULE);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(REVA)
|
||||
if (reason & PWM_ISR1_CHID1) {
|
||||
pwmptr->PWM_CH_NUM[1].PWM_CPDRUPD = *modulePulsesData[EXTRA_MODULE].ppm.ptr++;
|
||||
if (*modulePulsesData[EXTRA_MODULE].ppm.ptr == 0) {
|
||||
setupPulsesPPMModule(EXTRA_MODULE);
|
||||
setExtraModulePolarity();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 pwrPressed()
|
||||
{
|
||||
#if defined(SIMU) || defined(REVA)
|
||||
return true;
|
||||
#else
|
||||
return PIOC->PIO_PDSR & PIO_PC17;
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 pwrPressed()
|
||||
{
|
||||
#if defined(SIMU) || defined(REVA)
|
||||
return true;
|
||||
#else
|
||||
return PIOC->PIO_PDSR & PIO_PC17;
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
@@ -1,57 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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()
|
||||
{
|
||||
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 ;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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()
|
||||
{
|
||||
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 ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,287 +1,287 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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(REVX)
|
||||
// TODO change this, not the right place
|
||||
#define TWI_NONE 0
|
||||
#define TWI_WRITE_VOL 2
|
||||
#define TWI_WAIT_COMP 7
|
||||
#define TWI_READ_RTC 8
|
||||
#define TWI_WRITE_RTC 9
|
||||
#define TWI_WAIT_RTCSTOP 10
|
||||
#define TWI_WRITE_MFP 11
|
||||
int8_t volumeRequired ;
|
||||
int8_t Rtc_read_pending;
|
||||
uint8_t Rtc_write_pending ;
|
||||
int8_t Rtc_valid ;
|
||||
uint8_t MFPsetting = 0 ;
|
||||
uint8_t CALsetting = 0 ;
|
||||
uint8_t *Twi_read_address ;
|
||||
uint8_t TwiOperation ;
|
||||
#define RTC_RX_BUXSIZE 10
|
||||
#define RTC_SIZE 7
|
||||
uint8_t Rtc_status[RTC_RX_BUXSIZE] ;
|
||||
uint8_t *Rtc_write_ptr ;
|
||||
uint32_t Rtc_write_count ;
|
||||
uint8_t RtcConfig[8] ; // For initial config and writing to RTC
|
||||
// 0x80, 0, 0, 0x08, 0, 0, 0, 0x80
|
||||
|
||||
uint32_t fromBCD(uint8_t bcd_value)
|
||||
{
|
||||
return (((bcd_value & 0xF0) * 10) >> 4) + (bcd_value & 0x0F);
|
||||
}
|
||||
|
||||
uint32_t toBCD(uint32_t value)
|
||||
{
|
||||
div_t qr = div(value, 10);
|
||||
return (qr.quot << 4) + qr.rem;
|
||||
}
|
||||
|
||||
// This is called from an interrupt routine, or
|
||||
// interrupts must be disabled while it is called
|
||||
// from elsewhere.
|
||||
void i2cCheck()
|
||||
{
|
||||
if ( TWI0->TWI_IMR & TWI_IMR_TXCOMP ) {
|
||||
return ; // Busy
|
||||
}
|
||||
|
||||
if ( volumeRequired >= 0 ) // Set volume to this value
|
||||
{
|
||||
TWI0->TWI_MMR = 0x002F0000 ; // Device 5E (>>1) and master is writing
|
||||
TwiOperation = TWI_WRITE_VOL ;
|
||||
TWI0->TWI_THR = volumeRequired ; // Send data
|
||||
volumeRequired = -1 ;
|
||||
TWI0->TWI_IER = TWI_IER_TXCOMP ;
|
||||
TWI0->TWI_CR = TWI_CR_STOP ; // Stop Tx
|
||||
}
|
||||
else if ( Rtc_read_pending )
|
||||
{
|
||||
Rtc_valid = 0 ;
|
||||
Rtc_read_pending = 0 ;
|
||||
TWI0->TWI_MMR = 0x006F1100 ; // Device 6F and master is reading, 1 byte addr
|
||||
TWI0->TWI_IADR = 0 ;
|
||||
TwiOperation = TWI_READ_RTC ;
|
||||
#ifndef SIMU
|
||||
TWI0->TWI_RPR = (uint32_t)&Rtc_status[0] ;
|
||||
#endif
|
||||
TWI0->TWI_RCR = RTC_SIZE - 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 ( Rtc_write_pending )
|
||||
{
|
||||
if ( Rtc_write_pending & (2|4) )
|
||||
{
|
||||
TWI0->TWI_MMR = 0x006F0100 ; // Device 6F and master is writing, 1 byte addr
|
||||
TwiOperation = TWI_WRITE_MFP ;
|
||||
if ( Rtc_write_pending & 2 )
|
||||
{
|
||||
TWI0->TWI_IADR = 7 ;
|
||||
TWI0->TWI_THR = MFPsetting ; // Send data
|
||||
Rtc_write_pending &= ~2 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
TWI0->TWI_IADR = 8 ;
|
||||
TWI0->TWI_THR = CALsetting ; // Send data
|
||||
Rtc_write_pending &= ~4 ;
|
||||
}
|
||||
TWI0->TWI_IER = TWI_IER_TXCOMP ;
|
||||
TWI0->TWI_CR = TWI_CR_STOP ; // Stop Tx
|
||||
}
|
||||
else
|
||||
{
|
||||
Rtc_write_pending &= ~1 ;
|
||||
TWI0->TWI_MMR = 0x006F0100 ; // Device 6F and master is writing, 1 byte addr
|
||||
TWI0->TWI_IADR = 0 ;
|
||||
TwiOperation = TWI_WRITE_RTC ;
|
||||
#ifndef SIMU
|
||||
TWI0->TWI_TPR = (uint32_t)Rtc_write_ptr+1 ;
|
||||
#endif
|
||||
TWI0->TWI_TCR = Rtc_write_count-1 ;
|
||||
TWI0->TWI_THR = *Rtc_write_ptr ; // First byte
|
||||
TWI0->TWI_PTCR = TWI_PTCR_TXTEN ; // Start data transfer
|
||||
TWI0->TWI_IER = TWI_IER_TXBUFE | TWI_IER_TXCOMP ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void writeRTC(uint8_t *ptr)
|
||||
{
|
||||
uint32_t year;
|
||||
RtcConfig[0] = 0x80 | toBCD(*ptr++);
|
||||
RtcConfig[1] = toBCD(*ptr++);
|
||||
RtcConfig[2] = toBCD(*ptr++);
|
||||
RtcConfig[3] = 0x08;
|
||||
RtcConfig[4] = toBCD(*ptr++);
|
||||
RtcConfig[5] = toBCD( *ptr++);
|
||||
year = *ptr++;
|
||||
year |= *ptr << 8;
|
||||
RtcConfig[6] = toBCD(year - 2000);
|
||||
RtcConfig[7] = MFPsetting;
|
||||
Rtc_write_ptr = RtcConfig;
|
||||
Rtc_write_count = 8;
|
||||
__disable_irq();
|
||||
Rtc_write_pending |= 1;
|
||||
i2cCheck();
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
void readRTC()
|
||||
{
|
||||
Rtc_read_pending = 1 ;
|
||||
__disable_irq() ;
|
||||
i2cCheck() ;
|
||||
__enable_irq() ;
|
||||
}
|
||||
|
||||
// TODO should be inside an i2c_driver.cpp
|
||||
#ifndef SIMU
|
||||
extern "C" void TWI0_IRQHandler()
|
||||
{
|
||||
uint32_t status ;
|
||||
status = TWI0->TWI_SR ; // Read only once, some bits cleared on read
|
||||
|
||||
if ( TwiOperation == TWI_READ_RTC )
|
||||
{
|
||||
if ( status & TWI_SR_RXBUFF )
|
||||
{
|
||||
TWI0->TWI_IDR = TWI_IDR_RXBUFF ;
|
||||
TwiOperation = TWI_WAIT_RTCSTOP ;
|
||||
TWI0->TWI_CR = TWI_CR_STOP ; // Stop Rx
|
||||
TWI0->TWI_RCR = 1 ; // Last byte
|
||||
return ;
|
||||
}
|
||||
else
|
||||
{
|
||||
// must be TXCOMP, prob. NAK in data
|
||||
if ( TWI0->TWI_RCR > 0 )
|
||||
{
|
||||
Rtc_valid = -1 ;
|
||||
TWI0->TWI_CR = TWI_CR_STOP ; // Stop Rx
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( TwiOperation == TWI_WAIT_RTCSTOP )
|
||||
{
|
||||
Rtc_valid = 1 ;
|
||||
// Set the date and time
|
||||
struct gtm utm;
|
||||
|
||||
utm.tm_sec = fromBCD( Rtc_status[0] & 0x7F ) ;
|
||||
utm.tm_min = fromBCD( Rtc_status[1] & 0x7F ) ;
|
||||
utm.tm_hour = fromBCD( Rtc_status[2] & 0x3F ) ;
|
||||
utm.tm_mday = fromBCD( Rtc_status[4] & 0x3F ) ;
|
||||
utm.tm_mon = fromBCD( Rtc_status[5] & 0x1F ) - 1;
|
||||
utm.tm_year = fromBCD( Rtc_status[6] ) + 100 ;
|
||||
g_rtcTime = gmktime(&utm);
|
||||
|
||||
TWI0->TWI_PTCR = TWI_PTCR_RXTDIS ; // Stop transfers
|
||||
if ( status & TWI_SR_RXRDY )
|
||||
{
|
||||
(void) TWI0->TWI_RHR ; // Discard any rubbish data
|
||||
}
|
||||
}
|
||||
|
||||
if ( status & TWI_SR_NACK )
|
||||
{
|
||||
TWI0->TWI_CR = TWI_CR_STOP ; // Stop Tx
|
||||
}
|
||||
|
||||
TWI0->TWI_IDR = TWI_IDR_TXCOMP | TWI_IDR_TXBUFE | TWI_IDR_RXBUFF ;
|
||||
TWI0->TWI_PTCR = TWI_PTCR_TXTDIS | TWI_PTCR_RXTDIS ; // Stop transfers
|
||||
if ( ( status & TWI_SR_TXCOMP ) == 0 )
|
||||
{
|
||||
TWI0->TWI_IER = TWI_IER_TXCOMP ;
|
||||
TwiOperation = TWI_WAIT_COMP ;
|
||||
return ;
|
||||
}
|
||||
|
||||
TwiOperation = TWI_NONE ;
|
||||
i2cCheck() ;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct t_i2cTime
|
||||
{
|
||||
uint8_t setCode ;
|
||||
uint8_t Time[7] ;
|
||||
} I2CTime ;
|
||||
|
||||
void rtcSetTime(const struct gtm * t)
|
||||
{
|
||||
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+TM_YEAR_BASE);
|
||||
I2CTime.Time[6] = (t->tm_year+TM_YEAR_BASE) >> 8;
|
||||
#if defined(REVX)
|
||||
writeRTC((uint8_t *)&I2CTime.Time[0]) ;
|
||||
#elif defined(COPROCESSOR)
|
||||
coprocWriteData((uint8_t *) &I2CTime, 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
void rtcInit()
|
||||
{
|
||||
#if defined(REVX)
|
||||
readRTC();
|
||||
#elif defined(COPROCESSOR)
|
||||
coprocReadData();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(REVX)
|
||||
void writeMFP()
|
||||
{
|
||||
__disable_irq();
|
||||
Rtc_write_pending |= 2;
|
||||
i2cCheck();
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
void setMFP()
|
||||
{
|
||||
MFPsetting = 0x80;
|
||||
writeMFP();
|
||||
}
|
||||
|
||||
void clearMFP()
|
||||
{
|
||||
MFPsetting = 0;
|
||||
writeMFP();
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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(REVX)
|
||||
// TODO change this, not the right place
|
||||
#define TWI_NONE 0
|
||||
#define TWI_WRITE_VOL 2
|
||||
#define TWI_WAIT_COMP 7
|
||||
#define TWI_READ_RTC 8
|
||||
#define TWI_WRITE_RTC 9
|
||||
#define TWI_WAIT_RTCSTOP 10
|
||||
#define TWI_WRITE_MFP 11
|
||||
int8_t volumeRequired ;
|
||||
int8_t Rtc_read_pending;
|
||||
uint8_t Rtc_write_pending ;
|
||||
int8_t Rtc_valid ;
|
||||
uint8_t MFPsetting = 0 ;
|
||||
uint8_t CALsetting = 0 ;
|
||||
uint8_t *Twi_read_address ;
|
||||
uint8_t TwiOperation ;
|
||||
#define RTC_RX_BUXSIZE 10
|
||||
#define RTC_SIZE 7
|
||||
uint8_t Rtc_status[RTC_RX_BUXSIZE] ;
|
||||
uint8_t *Rtc_write_ptr ;
|
||||
uint32_t Rtc_write_count ;
|
||||
uint8_t RtcConfig[8] ; // For initial config and writing to RTC
|
||||
// 0x80, 0, 0, 0x08, 0, 0, 0, 0x80
|
||||
|
||||
uint32_t fromBCD(uint8_t bcd_value)
|
||||
{
|
||||
return (((bcd_value & 0xF0) * 10) >> 4) + (bcd_value & 0x0F);
|
||||
}
|
||||
|
||||
uint32_t toBCD(uint32_t value)
|
||||
{
|
||||
div_t qr = div(value, 10);
|
||||
return (qr.quot << 4) + qr.rem;
|
||||
}
|
||||
|
||||
// This is called from an interrupt routine, or
|
||||
// interrupts must be disabled while it is called
|
||||
// from elsewhere.
|
||||
void i2cCheck()
|
||||
{
|
||||
if ( TWI0->TWI_IMR & TWI_IMR_TXCOMP ) {
|
||||
return ; // Busy
|
||||
}
|
||||
|
||||
if ( volumeRequired >= 0 ) // Set volume to this value
|
||||
{
|
||||
TWI0->TWI_MMR = 0x002F0000 ; // Device 5E (>>1) and master is writing
|
||||
TwiOperation = TWI_WRITE_VOL ;
|
||||
TWI0->TWI_THR = volumeRequired ; // Send data
|
||||
volumeRequired = -1 ;
|
||||
TWI0->TWI_IER = TWI_IER_TXCOMP ;
|
||||
TWI0->TWI_CR = TWI_CR_STOP ; // Stop Tx
|
||||
}
|
||||
else if ( Rtc_read_pending )
|
||||
{
|
||||
Rtc_valid = 0 ;
|
||||
Rtc_read_pending = 0 ;
|
||||
TWI0->TWI_MMR = 0x006F1100 ; // Device 6F and master is reading, 1 byte addr
|
||||
TWI0->TWI_IADR = 0 ;
|
||||
TwiOperation = TWI_READ_RTC ;
|
||||
#ifndef SIMU
|
||||
TWI0->TWI_RPR = (uint32_t)&Rtc_status[0] ;
|
||||
#endif
|
||||
TWI0->TWI_RCR = RTC_SIZE - 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 ( Rtc_write_pending )
|
||||
{
|
||||
if ( Rtc_write_pending & (2|4) )
|
||||
{
|
||||
TWI0->TWI_MMR = 0x006F0100 ; // Device 6F and master is writing, 1 byte addr
|
||||
TwiOperation = TWI_WRITE_MFP ;
|
||||
if ( Rtc_write_pending & 2 )
|
||||
{
|
||||
TWI0->TWI_IADR = 7 ;
|
||||
TWI0->TWI_THR = MFPsetting ; // Send data
|
||||
Rtc_write_pending &= ~2 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
TWI0->TWI_IADR = 8 ;
|
||||
TWI0->TWI_THR = CALsetting ; // Send data
|
||||
Rtc_write_pending &= ~4 ;
|
||||
}
|
||||
TWI0->TWI_IER = TWI_IER_TXCOMP ;
|
||||
TWI0->TWI_CR = TWI_CR_STOP ; // Stop Tx
|
||||
}
|
||||
else
|
||||
{
|
||||
Rtc_write_pending &= ~1 ;
|
||||
TWI0->TWI_MMR = 0x006F0100 ; // Device 6F and master is writing, 1 byte addr
|
||||
TWI0->TWI_IADR = 0 ;
|
||||
TwiOperation = TWI_WRITE_RTC ;
|
||||
#ifndef SIMU
|
||||
TWI0->TWI_TPR = (uint32_t)Rtc_write_ptr+1 ;
|
||||
#endif
|
||||
TWI0->TWI_TCR = Rtc_write_count-1 ;
|
||||
TWI0->TWI_THR = *Rtc_write_ptr ; // First byte
|
||||
TWI0->TWI_PTCR = TWI_PTCR_TXTEN ; // Start data transfer
|
||||
TWI0->TWI_IER = TWI_IER_TXBUFE | TWI_IER_TXCOMP ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void writeRTC(uint8_t *ptr)
|
||||
{
|
||||
uint32_t year;
|
||||
RtcConfig[0] = 0x80 | toBCD(*ptr++);
|
||||
RtcConfig[1] = toBCD(*ptr++);
|
||||
RtcConfig[2] = toBCD(*ptr++);
|
||||
RtcConfig[3] = 0x08;
|
||||
RtcConfig[4] = toBCD(*ptr++);
|
||||
RtcConfig[5] = toBCD( *ptr++);
|
||||
year = *ptr++;
|
||||
year |= *ptr << 8;
|
||||
RtcConfig[6] = toBCD(year - 2000);
|
||||
RtcConfig[7] = MFPsetting;
|
||||
Rtc_write_ptr = RtcConfig;
|
||||
Rtc_write_count = 8;
|
||||
__disable_irq();
|
||||
Rtc_write_pending |= 1;
|
||||
i2cCheck();
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
void readRTC()
|
||||
{
|
||||
Rtc_read_pending = 1 ;
|
||||
__disable_irq() ;
|
||||
i2cCheck() ;
|
||||
__enable_irq() ;
|
||||
}
|
||||
|
||||
// TODO should be inside an i2c_driver.cpp
|
||||
#ifndef SIMU
|
||||
extern "C" void TWI0_IRQHandler()
|
||||
{
|
||||
uint32_t status ;
|
||||
status = TWI0->TWI_SR ; // Read only once, some bits cleared on read
|
||||
|
||||
if ( TwiOperation == TWI_READ_RTC )
|
||||
{
|
||||
if ( status & TWI_SR_RXBUFF )
|
||||
{
|
||||
TWI0->TWI_IDR = TWI_IDR_RXBUFF ;
|
||||
TwiOperation = TWI_WAIT_RTCSTOP ;
|
||||
TWI0->TWI_CR = TWI_CR_STOP ; // Stop Rx
|
||||
TWI0->TWI_RCR = 1 ; // Last byte
|
||||
return ;
|
||||
}
|
||||
else
|
||||
{
|
||||
// must be TXCOMP, prob. NAK in data
|
||||
if ( TWI0->TWI_RCR > 0 )
|
||||
{
|
||||
Rtc_valid = -1 ;
|
||||
TWI0->TWI_CR = TWI_CR_STOP ; // Stop Rx
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( TwiOperation == TWI_WAIT_RTCSTOP )
|
||||
{
|
||||
Rtc_valid = 1 ;
|
||||
// Set the date and time
|
||||
struct gtm utm;
|
||||
|
||||
utm.tm_sec = fromBCD( Rtc_status[0] & 0x7F ) ;
|
||||
utm.tm_min = fromBCD( Rtc_status[1] & 0x7F ) ;
|
||||
utm.tm_hour = fromBCD( Rtc_status[2] & 0x3F ) ;
|
||||
utm.tm_mday = fromBCD( Rtc_status[4] & 0x3F ) ;
|
||||
utm.tm_mon = fromBCD( Rtc_status[5] & 0x1F ) - 1;
|
||||
utm.tm_year = fromBCD( Rtc_status[6] ) + 100 ;
|
||||
g_rtcTime = gmktime(&utm);
|
||||
|
||||
TWI0->TWI_PTCR = TWI_PTCR_RXTDIS ; // Stop transfers
|
||||
if ( status & TWI_SR_RXRDY )
|
||||
{
|
||||
(void) TWI0->TWI_RHR ; // Discard any rubbish data
|
||||
}
|
||||
}
|
||||
|
||||
if ( status & TWI_SR_NACK )
|
||||
{
|
||||
TWI0->TWI_CR = TWI_CR_STOP ; // Stop Tx
|
||||
}
|
||||
|
||||
TWI0->TWI_IDR = TWI_IDR_TXCOMP | TWI_IDR_TXBUFE | TWI_IDR_RXBUFF ;
|
||||
TWI0->TWI_PTCR = TWI_PTCR_TXTDIS | TWI_PTCR_RXTDIS ; // Stop transfers
|
||||
if ( ( status & TWI_SR_TXCOMP ) == 0 )
|
||||
{
|
||||
TWI0->TWI_IER = TWI_IER_TXCOMP ;
|
||||
TwiOperation = TWI_WAIT_COMP ;
|
||||
return ;
|
||||
}
|
||||
|
||||
TwiOperation = TWI_NONE ;
|
||||
i2cCheck() ;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct t_i2cTime
|
||||
{
|
||||
uint8_t setCode ;
|
||||
uint8_t Time[7] ;
|
||||
} I2CTime ;
|
||||
|
||||
void rtcSetTime(const struct gtm * t)
|
||||
{
|
||||
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+TM_YEAR_BASE);
|
||||
I2CTime.Time[6] = (t->tm_year+TM_YEAR_BASE) >> 8;
|
||||
#if defined(REVX)
|
||||
writeRTC((uint8_t *)&I2CTime.Time[0]) ;
|
||||
#elif defined(COPROCESSOR)
|
||||
coprocWriteData((uint8_t *) &I2CTime, 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
void rtcInit()
|
||||
{
|
||||
#if defined(REVX)
|
||||
readRTC();
|
||||
#elif defined(COPROCESSOR)
|
||||
coprocReadData();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(REVX)
|
||||
void writeMFP()
|
||||
{
|
||||
__disable_irq();
|
||||
Rtc_write_pending |= 2;
|
||||
i2cCheck();
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
void setMFP()
|
||||
{
|
||||
MFPsetting = 0x80;
|
||||
writeMFP();
|
||||
}
|
||||
|
||||
void clearMFP()
|
||||
{
|
||||
MFPsetting = 0;
|
||||
writeMFP();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,150 +1,150 @@
|
||||
/****************************************************************************
|
||||
* 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.*)
|
||||
|
||||
KEEP (*(.init))
|
||||
KEEP (*(.fini))
|
||||
|
||||
. = 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 **/
|
||||
|
||||
/****************************************************************************
|
||||
* 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.*)
|
||||
|
||||
KEEP (*(.init))
|
||||
KEEP (*(.fini))
|
||||
|
||||
. = 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 **/
|
||||
|
||||
|
||||
@@ -1,154 +1,154 @@
|
||||
/****************************************************************************
|
||||
* 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 :
|
||||
{
|
||||
FILL(0xFFFF)
|
||||
|
||||
CREATE_OBJECT_SYMBOLS
|
||||
|
||||
*(.bootrodata)
|
||||
*(.bootrodata.*)
|
||||
|
||||
. = ALIGN(32768); /* Align the start of the exidx part */
|
||||
_stext = .; /* Provide the name for the start of this section */
|
||||
|
||||
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.*)
|
||||
|
||||
KEEP (*(.init))
|
||||
KEEP (*(.fini))
|
||||
|
||||
. = 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 **/
|
||||
|
||||
/****************************************************************************
|
||||
* 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 :
|
||||
{
|
||||
FILL(0xFFFF)
|
||||
|
||||
CREATE_OBJECT_SYMBOLS
|
||||
|
||||
*(.bootrodata)
|
||||
*(.bootrodata.*)
|
||||
|
||||
. = ALIGN(32768); /* Align the start of the exidx part */
|
||||
_stext = .; /* Provide the name for the start of this section */
|
||||
|
||||
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.*)
|
||||
|
||||
KEEP (*(.init))
|
||||
KEEP (*(.fini))
|
||||
|
||||
. = 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 **/
|
||||
|
||||
|
||||
@@ -1,156 +1,156 @@
|
||||
/****************************************************************************
|
||||
* 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 = 512K
|
||||
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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 :
|
||||
{
|
||||
FILL(0xFFFF)
|
||||
|
||||
CREATE_OBJECT_SYMBOLS
|
||||
|
||||
*(.bootrodata)
|
||||
*(.bootrodata.*)
|
||||
|
||||
. = ALIGN(32768); /* Align the start of the exidx part */
|
||||
_stext = .; /* Provide the name for the start of this section */
|
||||
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.*)
|
||||
|
||||
KEEP (*(.init))
|
||||
KEEP (*(.fini))
|
||||
|
||||
. = 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 **/
|
||||
|
||||
/****************************************************************************
|
||||
* 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 = 512K
|
||||
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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 :
|
||||
{
|
||||
FILL(0xFFFF)
|
||||
|
||||
CREATE_OBJECT_SYMBOLS
|
||||
|
||||
*(.bootrodata)
|
||||
*(.bootrodata.*)
|
||||
|
||||
. = ALIGN(32768); /* Align the start of the exidx part */
|
||||
_stext = .; /* Provide the name for the start of this section */
|
||||
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.*)
|
||||
|
||||
KEEP (*(.init))
|
||||
KEEP (*(.fini))
|
||||
|
||||
. = 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 **/
|
||||
|
||||
|
||||
@@ -1,52 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 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
|
||||
}
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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 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
|
||||
}
|
||||
|
||||
@@ -1,119 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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>
|
||||
|
||||
/** Usart Hw interface used by the console (UART0). */
|
||||
#define SECOND_SERIAL_UART UART0
|
||||
/** Usart Hw ID used by the console (UART0). */
|
||||
#define SECOND_SERIAL_ID ID_UART0
|
||||
/** Pins description corresponding to Rxd,Txd, (UART pins) */
|
||||
#define SECOND_SERIAL_PINS {PINS_UART}
|
||||
|
||||
Fifo<uint8_t, 512> serial2RxFifo;
|
||||
|
||||
#if !defined(SIMU)
|
||||
/*
|
||||
* Outputs a character on the UART line.
|
||||
*
|
||||
* This function is synchronous (i.e. uses polling).
|
||||
* c Character to send.
|
||||
*/
|
||||
void serial2Putc(const char c)
|
||||
{
|
||||
Uart *pUart = SECOND_SERIAL_UART;
|
||||
|
||||
/* Wait for the transmitter to be ready */
|
||||
while ( (pUart->UART_SR & UART_SR_TXEMPTY) == 0 ) ;
|
||||
|
||||
/* Send character */
|
||||
pUart->UART_THR = c;
|
||||
}
|
||||
|
||||
uint8_t serial2TracesEnabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 SECOND_UART_Configure(uint32_t baudrate, uint32_t masterClock)
|
||||
{
|
||||
Uart *pUart = SECOND_SERIAL_UART;
|
||||
|
||||
/* 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 << SECOND_SERIAL_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 SECOND_UART_Stop()
|
||||
{
|
||||
SECOND_SERIAL_UART->UART_IDR = UART_IDR_RXRDY ;
|
||||
NVIC_DisableIRQ(UART0_IRQn) ;
|
||||
}
|
||||
|
||||
extern "C" void UART0_IRQHandler()
|
||||
{
|
||||
serial2RxFifo.push(SECOND_SERIAL_UART->UART_RHR);
|
||||
}
|
||||
#else
|
||||
#define SECOND_UART_Configure(...)
|
||||
#endif
|
||||
|
||||
#if defined(TELEMETRY_FRSKY)
|
||||
void serial2TelemetryInit(unsigned int /*protocol*/)
|
||||
{
|
||||
SECOND_UART_Configure(FRSKY_D_BAUDRATE, Master_frequency);
|
||||
// startPdcUsartReceive();
|
||||
}
|
||||
|
||||
bool telemetrySecondPortReceive(uint8_t & data)
|
||||
{
|
||||
return serial2RxFifo.pop(data);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* 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>
|
||||
|
||||
/** Usart Hw interface used by the console (UART0). */
|
||||
#define SECOND_SERIAL_UART UART0
|
||||
/** Usart Hw ID used by the console (UART0). */
|
||||
#define SECOND_SERIAL_ID ID_UART0
|
||||
/** Pins description corresponding to Rxd,Txd, (UART pins) */
|
||||
#define SECOND_SERIAL_PINS {PINS_UART}
|
||||
|
||||
Fifo<uint8_t, 512> serial2RxFifo;
|
||||
|
||||
#if !defined(SIMU)
|
||||
/*
|
||||
* Outputs a character on the UART line.
|
||||
*
|
||||
* This function is synchronous (i.e. uses polling).
|
||||
* c Character to send.
|
||||
*/
|
||||
void serial2Putc(const char c)
|
||||
{
|
||||
Uart *pUart = SECOND_SERIAL_UART;
|
||||
|
||||
/* Wait for the transmitter to be ready */
|
||||
while ( (pUart->UART_SR & UART_SR_TXEMPTY) == 0 ) ;
|
||||
|
||||
/* Send character */
|
||||
pUart->UART_THR = c;
|
||||
}
|
||||
|
||||
uint8_t serial2TracesEnabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 SECOND_UART_Configure(uint32_t baudrate, uint32_t masterClock)
|
||||
{
|
||||
Uart *pUart = SECOND_SERIAL_UART;
|
||||
|
||||
/* 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 << SECOND_SERIAL_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 SECOND_UART_Stop()
|
||||
{
|
||||
SECOND_SERIAL_UART->UART_IDR = UART_IDR_RXRDY ;
|
||||
NVIC_DisableIRQ(UART0_IRQn) ;
|
||||
}
|
||||
|
||||
extern "C" void UART0_IRQHandler()
|
||||
{
|
||||
serial2RxFifo.push(SECOND_SERIAL_UART->UART_RHR);
|
||||
}
|
||||
#else
|
||||
#define SECOND_UART_Configure(...)
|
||||
#endif
|
||||
|
||||
#if defined(TELEMETRY_FRSKY)
|
||||
void serial2TelemetryInit(unsigned int /*protocol*/)
|
||||
{
|
||||
SECOND_UART_Configure(FRSKY_D_BAUDRATE, Master_frequency);
|
||||
// startPdcUsartReceive();
|
||||
}
|
||||
|
||||
bool telemetrySecondPortReceive(uint8_t & data)
|
||||
{
|
||||
return serial2RxFifo.pop(data);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,162 +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 "../../../usb/common/core/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;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* 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 "../../../usb/common/core/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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,150 +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 "../../../usb/common/core/USBEndpointDescriptor.h"
|
||||
#include "../../../usb/common/core/USBGenericDescriptor.h"
|
||||
#include "../../../usb/common/core/USBInterfaceDescriptor.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
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* 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 "../../../usb/common/core/USBEndpointDescriptor.h"
|
||||
#include "../../../usb/common/core/USBGenericDescriptor.h"
|
||||
#include "../../../usb/common/core/USBInterfaceDescriptor.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
|
||||
|
||||
|
||||
@@ -1,125 +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_lowlevel.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
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* 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_lowlevel.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
|
||||
|
||||
|
||||
@@ -1,89 +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
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* 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
|
||||
|
||||
|
||||
@@ -1,109 +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 "../../../usb/common/core/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;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* 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 "../../../usb/common/core/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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,224 +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
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* 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
|
||||
|
||||
|
||||
@@ -1,70 +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 "../../../usb/common/core/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;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* 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 "../../../usb/common/core/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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,146 +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 "../../../usb/common/core/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
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* 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 "../../../usb/common/core/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
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user