Browse Source

working version

master
Olaf Rempel 13 years ago
parent
commit
8583ff4f02
  1. 2
      at91_init0.s
  2. 2
      at91_init1.c
  3. BIN
      eagle/SAM7_FC.brd
  4. BIN
      eagle/SAM7_FC.sch
  5. BIN
      eagle/sam7fc-bot.png
  6. BIN
      eagle/sam7fc-sch.png
  7. BIN
      eagle/sam7fc-top.png
  8. 29
      include/at91_adc.h
  9. 4
      include/at91_dbgu.h
  10. 1
      include/at91_pitc.h
  11. 2
      include/board.h
  12. 34
      include/fixed.h
  13. 2
      include/pidctrl.h
  14. 103
      include/tdc_proto.h
  15. 152
      include/telemetrie.h
  16. 264
      main.c
  17. 194
      src/at91_adc.c
  18. 28
      src/at91_dbgu.c
  19. 9
      src/at91_exceptions.c
  20. 4
      src/at91_pio.c
  21. 35
      src/at91_pitc.c
  22. 25
      src/at91_rttc_test.c
  23. 30
      src/at91_sysc.c
  24. 20
      src/at91_tc1.c
  25. 2
      src/at91_twi.c
  26. 38
      src/at91_udp.c
  27. 4
      src/fifo.c
  28. 389
      src/fixed.c
  29. 264
      src/flightctrl.c
  30. 2
      src/memalloc.c
  31. 26
      src/pidctrl.c
  32. 279
      src/telemetrie.c

2
at91_init0.s

@ -1,4 +1,6 @@
/***************************************************************************
* sam7fc - stack/bss/data init *
* *
* Copyright (C) 01/2008 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *

2
at91_init1.c

@ -1,4 +1,6 @@
/***************************************************************************
* sam7fc - PLL Init, IRQ/FIQ Vectors *
* *
* Copyright (C) 01/2008 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *

BIN
eagle/SAM7_FC.brd

BIN
eagle/SAM7_FC.sch

BIN
eagle/sam7fc-bot.png

After

Width: 711  |  Height: 757  |  Size: 41 KiB

BIN
eagle/sam7fc-sch.png

After

Width: 3865  |  Height: 2608  |  Size: 203 KiB

BIN
eagle/sam7fc-top.png

After

Width: 711  |  Height: 757  |  Size: 36 KiB

29
include/at91_adc.h

@ -3,21 +3,30 @@
#include <stdint.h>
#define ADC_GYRO_ROLL 0
#define ADC_GYRO_NICK 1
#define ADC_GYRO_YAW 2
#define ADC_ACC_ROLL 3
#define ADC_ACC_NICK 4
#define ADC_ACC_YAW 5
#define ADC_GYRO_NICK 0
#define ADC_GYRO_ROLL 1
#define ADC_GYRO_GIER 2
#define ADC_ACC_NICK 3
#define ADC_ACC_ROLL 4
#define ADC_ACC_GIER 5
#define ADC_VOLTAGE 6
#define ADC_CAL_NONE 0
#define ADC_CAL_GYRO 1
#define ADC_CAL_ACC 2
// TODO: not all flags are public
#define ADC_COMPLETE 0x0001
#define ADC_CAL_GYRO 0x0100
#define ADC_CAL_GYRO_COMPLETE 0x0200
#define ADC_CAL_ACC 0x1000
#define ADC_CAL_ACC_COMPLETE 0x2000
#define ADC_CAL_ACC_LOAD 0x4000
void adc_trigger(void);
void adc_get_results(int16_t *adc_result);
void adc_calibrate(uint32_t mode);
void adc_drift_adjust(int16_t nick, int16_t roll, int16_t yaw);
void at91_adc_init(void);
#endif /*AT91_ADC_H_*/
#endif /* AT91_ADC_H_ */

4
include/at91_dbgu.h

@ -1,12 +1,10 @@
#ifndef AT91_DBGU_H_
#define AT91_DBGU_H_
#include <stddef.h>
void at91_dbgu_init(void);
void at91_dbgu_putc(char c);
void at91_dbgu_puts(const char *p);
int at91_dbgu_write(void *base, const char *buf, size_t len);
#endif /*AT91_DBGU_H_*/
#endif /* AT91_DBGU_H_ */

1
include/at91_pitc.h

@ -17,6 +17,7 @@ struct pitc_timer {
};
void pitc_schedule_timer(struct pitc_timer *timer);
void pitc_remove_timer(struct pitc_timer *timer);
uint32_t pitc_get_ticks(void);
void at91_pitc_init(void);

2
include/board.h

@ -40,4 +40,6 @@
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#define LIMIT(val, min, max) (((val) < (min)) ? (min) : (((val) > (max)) ? (max) : (val)))
#endif /*BOARD_H_*/

34
include/fixed.h

@ -1,34 +0,0 @@
#ifndef _FIXED_H_
#define _FIXED_H_
#include <stdint.h>
typedef int32_t fixed;
fixed itofix(int x);
int fixtoi(fixed x);
fixed ftofix(double x);
double fixtof(fixed x);
fixed fadd(fixed x, fixed y);
fixed fsub(fixed x, fixed y);
fixed fmul(fixed x, fixed y);
fixed fdiv(fixed x, fixed y);
const fixed fixtorad_r;
const fixed radtofix_r;
fixed fcos(fixed x);
fixed fsin(fixed x);
fixed ftan(fixed x);
fixed facos(fixed x);
fixed fasin(fixed x);
fixed fatan(fixed x);
fixed fatan2(fixed y, fixed x);
fixed fsqrt(fixed n);
#endif /* _FIXED_H_ */

2
include/pidctrl.h

@ -6,8 +6,6 @@
struct pid_data {
int32_t kp;
int32_t ta;
int32_t ki;
int32_t err_sum;
int32_t err_sum_max;

103
include/tdc_proto.h

@ -0,0 +1,103 @@
#ifndef TDCPROTO_H_
#define TDCPROTO_H_
#include <stdint.h>
/*
* 0: this is a request (host -> board)
* 1: this is a reply (board -> host)
*/
#define TDC_DIR 0x80
#define TDC_REPLY TDC_DIR
/*
* TDC_DIR = 0: destination address
* TDC_DIR = 1: source address
*/
#define TDC_ADDRMASK 0x70
#define TDC_ADDR0 0x00 // host (dynamic!, sends to interface of last hello)
#define TDC_ADDR1 0x10 // flightcontrol
#define TDC_ADDR2 0x20 // missioncontrol
#define TDC_ADDR3 0x30 // videocontrol
#define TDC_ADDR4 0x40
#define TDC_ADDR5 0x50
#define TDC_ADDR6 0x60
#define TDC_ADDR7 0x70
#define TDC_OPCODEMASK 0x0F
#define TDC_HELLO 0x00 // sets the path/interface to the host, reply is a info string
#define TDC_GETVARS 0x01 // request variable names, many replies
#define TDC_GETVALUE 0x02 // get one value, one reply
#define TDC_SETVALUE 0x03 // set one value, no reply
#define TDC_REQVALUES 0x04 // registers a periodic update, timed replies
#define TDC_TERMINAL 0x05 // stdout data
#define TDC_USERDATA 0x0F // user-defined data e.g. between boards
struct tdc_pkt_header {
uint8_t cmd; // TDC_*
uint8_t size; // size including this header
} __attribute__ ((packed));
struct tdc_hello_reply {
uint8_t cmd;
uint8_t size;
char name[32]; // name of device, version string
} __attribute__ ((packed));
struct tdc_getvars_reply {
uint8_t cmd;
uint8_t size;
uint8_t id; // variable ID (max 256 vars / board)
uint32_t flags; // variable parameters (type, size, ro/rw)
uint8_t name_len; // size of variable name
char name[0]; // variable name, excluding '\0'
} __attribute__ ((packed));
struct tdc_getvalue_request {
uint8_t cmd;
uint8_t size;
uint8_t id; // variable ID (max 256 vars / board)
} __attribute__ ((packed));
struct tdc_getvalue_reply {
uint8_t cmd;
uint8_t size;
uint8_t id; // variable ID (max 256 vars / board)
uint8_t data[0]; // variable data 1-8 bytes
} __attribute__ ((packed));
struct tdc_setvalue_request {
uint8_t cmd;
uint8_t size;
uint8_t id; // variable ID (max 256 vars / board)
uint8_t data[0]; // variable data 1-8 bytes
} __attribute__ ((packed));
struct tdc_reqvalues_request {
uint8_t cmd;
uint8_t size;
uint16_t interval; // interval in ms
uint32_t varmap[8]; // bitmap of variables (32 * 8 = 256)
} __attribute__ ((packed));
struct tdc_reqvalues_reply {
uint8_t cmd;
uint8_t size;
uint32_t timestamp; // internal jiffie count
uint8_t cnt; // number of variables
} __attribute__ ((packed));
#define TDC_SIZEMASK 0x000F
#define TDC_TYPEMASK 0x00F0
#define TDC_UNSIGNED 0x0000
#define TDC_SIGNED 0x0010
#define TDC_FP 0x0020
#define TDC_FIXED 0x0040
#define TDC_READONLY 0x0100
#define TDC_GUI_GRAPH 0x8000
#endif /* TDCPROTO_H_ */

152
include/telemetrie.h

@ -1,108 +1,19 @@
#ifndef TELEMETRIE_H_
#define TELEMETRIE_H_
/*
* 0: this is a request (host -> board)
* 1: this is a reply (board -> host)
*/
#define TDC_DIR 0x80
#define TDC_REPLY TDC_DIR
/*
* TDC_DIR = 0: destination address
* TDC_DIR = 1: source address
*/
#define TDC_ADDRMASK 0x70
#define TDC_ADDR0 0x00 // host (dynamic!, sends to interface of last hello)
#define TDC_ADDR1 0x10 // flightcontrol
#define TDC_ADDR2 0x20 // missioncontrol
#define TDC_ADDR3 0x30 // videocontrol
#define TDC_ADDR4 0x40
#define TDC_ADDR5 0x50
#define TDC_ADDR6 0x60
#define TDC_ADDR7 0x70
#define TDC_OPCODEMASK 0x0F
#define TDC_HELLO 0x00 // sets the path/interface to the host, reply is a info string
#define TDC_GETVARS 0x01 // request variable names, many replies
#define TDC_GETVALUE 0x02 // get one value, one reply
#define TDC_SETVALUE 0x03 // set one value, no reply
#define TDC_REQVALUES 0x04 // registers a periodic update, timed replies
#define TDC_TERMINAL 0x05 // stdout data
#define TDC_USERDATA 0x0F // user-defined data e.g. between boards
struct tdc_pkt_header {
uint8_t cmd; // TDC_*
uint8_t size; // bytes after size
} __attribute__ ((packed));
struct tdc_hello_reply {
uint8_t cmd;
uint8_t size;
char name[32]; // name of device, version string
} __attribute__ ((packed));
struct tdc_getvars_reply {
uint8_t cmd;
uint8_t size;
uint8_t id; // variable ID (max 256 vars / board)
uint32_t flags; // variable parameters (type, size, ro/rw)
char name[0]; // variable name, excluding '\0'
} __attribute__ ((packed));
struct tdc_getvalue_request {
uint8_t cmd;
uint8_t size;
uint8_t id; // variable ID (max 256 vars / board)
} __attribute__ ((packed));
struct tdc_getvalue_reply {
uint8_t cmd;
uint8_t size;
uint8_t id; // variable ID (max 256 vars / board)
uint8_t data[0]; // variable data 1-8 bytes
} __attribute__ ((packed));
struct tdc_setvalue_request {
uint8_t cmd;
uint8_t size;
uint8_t id; // variable ID (max 256 vars / board)
uint8_t data[0]; // variable data 1-8 bytes
} __attribute__ ((packed));
struct tdc_reqvalues_request {
uint8_t cmd;
uint8_t size;
uint16_t interval; // interval in ms
uint32_t varmap[8]; // bitmap of variables (32 * 8 = 256)
} __attribute__ ((packed));
struct tdc_reqvalues_reply {
uint8_t cmd;
uint8_t size;
uint32_t timestamp; // internal jiffie count
uint8_t cnt; // number of variables
} __attribute__ ((packed));
#include "tdc_proto.h"
struct comm_device {
struct fifo *rxfifo;
struct fifo *txfifo;
void (*trigger_tx)(void);
};
void tdc_register_device(uint32_t addr, struct comm_device *device);
int32_t tdc_transmit(uint32_t addr, struct tdc_pkt_header *head);
void tdc_receive(struct comm_device *device);
void tdc_check(void);
void tdc_init(void);
struct tdc_value {
void *data;
@ -110,26 +21,45 @@ struct tdc_value {
uint32_t flags;
};
#define TDC_SIZEMASK 0x0F
#define TDC_UNSIGNED 0x00
#define TDC_SIGNED 0x10
#define TDC_FP 0x20
#if 1
#define TDC_VALUE(var, desc, type, flags) \
type * tdc_check_##var(void) { return (&var); } \
#define TDC_VALUE(name, var, desc, type, flags) \
type * tdc_check_##name(void) { return (&var); } \
static struct tdc_value __attribute__((used, section(".tdc_value"))) \
tdc_value_##var = { &var, desc, sizeof(type) | flags }; \
tdc_value_##var = tdc_value_##var;
tdc_value_##name = { &var, desc, sizeof(type) | flags }; \
tdc_value_##name = tdc_value_##name;
#define TDC_UINT8(var, desc) TDC_VALUE(var, desc, uint8_t, TDC_UNSIGNED)
#define TDC_UINT16(var, desc) TDC_VALUE(var, desc, uint16_t, TDC_UNSIGNED)
#define TDC_UINT32(var, desc) TDC_VALUE(var, desc, uint32_t, TDC_UNSIGNED)
#define TDC_UINT64(var, desc) TDC_VALUE(var, desc, uint64_t, TDC_UNSIGNED)
#define TDC_INT8(var, desc) TDC_VALUE(var, desc, int8_t, TDC_SIGNED)
#define TDC_INT16(var, desc) TDC_VALUE(var, desc, int16_t, TDC_SIGNED)
#define TDC_INT32(var, desc) TDC_VALUE(var, desc, int32_t, TDC_SIGNED)
#define TDC_INT64(var, desc) TDC_VALUE(var, desc, int64_t, TDC_SIGNED)
#define TDC_FLOAT(var, desc) TDC_VALUE(var, desc, float, TDC_FP)
#define TDC_DOUBLE(var, desc) TDC_VALUE(var, desc, double, TDC_FP)
#define TDC_PTR(name, ptr, desc, type, flags) \
static struct tdc_value __attribute__((used, section(".tdc_value"))) \
tdc_value_##name = { ptr, desc, sizeof(type) | flags }; \
#else
#define TDC_VALUE(name, var, desc, type, flags)
#define TDC_PTR(name, ptr, desc, type, flags);
#endif
#define TDC_UINT8(var, desc) TDC_VALUE(var, var, desc, uint8_t, TDC_UNSIGNED)
#define TDC_UINT16(var, desc) TDC_VALUE(var, var, desc, uint16_t, TDC_UNSIGNED)
#define TDC_UINT32(var, desc) TDC_VALUE(var, var, desc, uint32_t, TDC_UNSIGNED)
#define TDC_UINT64(var, desc) TDC_VALUE(var, var, desc, uint64_t, TDC_UNSIGNED)
#define TDC_INT8(var, desc) TDC_VALUE(var, var, desc, int8_t, TDC_SIGNED)
#define TDC_INT16(var, desc) TDC_VALUE(var, var, desc, int16_t, TDC_SIGNED)
#define TDC_INT32(var, desc) TDC_VALUE(var, var, desc, int32_t, TDC_SIGNED)
#define TDC_INT64(var, desc) TDC_VALUE(var, var, desc, int64_t, TDC_SIGNED)
#define TDC_FLOAT(var, desc) TDC_VALUE(var, var, desc, float, TDC_FP)
#define TDC_DOUBLE(var, desc) TDC_VALUE(var, var, desc, double, TDC_FP)
#define TDC_UINT8_RO(var, desc) TDC_VALUE(var, var, desc, uint8_t, TDC_UNSIGNED | TDC_READONLY)
#define TDC_UINT16_RO(var, desc) TDC_VALUE(var, var, desc, uint16_t, TDC_UNSIGNED | TDC_READONLY)
#define TDC_UINT32_RO(var, desc) TDC_VALUE(var, var, desc, uint32_t, TDC_UNSIGNED | TDC_READONLY)
#define TDC_UINT64_RO(var, desc) TDC_VALUE(var, var, desc, uint64_t, TDC_UNSIGNED | TDC_READONLY)
#define TDC_INT8_RO(var, desc) TDC_VALUE(var, var, desc, int8_t, TDC_SIGNED | TDC_READONLY)
#define TDC_INT16_RO(var, desc) TDC_VALUE(var, var, desc, int16_t, TDC_SIGNED | TDC_READONLY)
#define TDC_INT32_RO(var, desc) TDC_VALUE(var, var, desc, int32_t, TDC_SIGNED | TDC_READONLY)
#define TDC_INT64_RO(var, desc) TDC_VALUE(var, var, desc, int64_t, TDC_SIGNED | TDC_READONLY)
#define TDC_FLOAT_RO(var, desc) TDC_VALUE(var, var, desc, float, TDC_FP | TDC_READONLY)
#define TDC_DOUBLE_RO(var, desc) TDC_VALUE(var, var, desc, double, TDC_FP | TDC_READONLY)
#endif /*TELEMETRIE_H_*/

264
main.c

@ -1,158 +1,106 @@
/***************************************************************************
* Copyright (C) 01/2008 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; version 2 of the License *
* *
* 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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "AT91SAM7S256.h"
#include "at91_sysc.h"
#include "at91_dbgu.h"
#include "at91_pitc.h"
#include "at91_adc.h"
#include "at91_tests.h"
#include "at91_udp.h"
#include "at91_pio.h"
#include "at91_twi.h"
#include "at91_tc1.h"
#include "memalloc.h"
#include "board.h"
#include <stdio.h>
#include <string.h>
static uint32_t global_state;
#define MOTORS_RUNNING 0x0001
#define STICK_CALIBRATION 0x0002
static uint32_t stick_timer_cb(struct pitc_timer *timer)
{
static uint32_t i;
*AT91C_PIOA_SODR = i;
i = i ^ LED_GREEN;
*AT91C_PIOA_CODR = i;
struct rc_values rc;
uint32_t count = rcontrol_getswitches(&rc);
static uint32_t stick_cal_count;
if (global_state & MOTORS_RUNNING) {
if ((rc.chan[2] < 0 && rc.chan[3] > 0) || count < 4)
global_state &= ~MOTORS_RUNNING;
} else if (global_state & STICK_CALIBRATION) {
stick_cal_count--;
if (stick_cal_count == 0) {
rcontrol_calibrate(RC_CAL_END);
rcontrol_calibrate(RC_CAL_SAVE);
rcontrol_print_cal();
global_state &= ~STICK_CALIBRATION;
}
} else if (count >= 4) {
if (rc.chan[2] < 0 && rc.chan[3] < 0)
global_state |= MOTORS_RUNNING;
if (rc.chan[2] > 0 && rc.chan[3] > 0)
adc_calibrate(ADC_CAL_GYRO);
if (rc.chan[2] > 0 && rc.chan[3] < 0) {
adc_calibrate(ADC_CAL_ACC);
stick_cal_count = 3000;
global_state |= STICK_CALIBRATION;
rcontrol_calibrate(RC_CAL_START);
}
}
rcontrol_getvalues(&rc);
static uint8_t pwm[4];
if (global_state & MOTORS_RUNNING) {
int32_t pitch = rc.chan[2] * 256;
int32_t gier = rc.chan[3] * 64;
int32_t nick = rc.chan[0] * 64;
int32_t roll = rc.chan[1] * 64;
int32_t data[4];
data[0] = (pitch - nick + gier) / 1024;
data[1] = (pitch + nick + gier) / 1024;
data[2] = (pitch + roll - gier) / 1024;
data[3] = (pitch - roll - gier) / 1024;
pwm[0] = (data[0] > 0x0f) ? data[0] : 0x0f;
pwm[1] = (data[1] > 0x0f) ? data[1] : 0x0f;
pwm[2] = (data[2] > 0x0f) ? data[2] : 0x0f;
pwm[3] = (data[3] > 0x0f) ? data[3] : 0x0f;
} else {
pwm[0] = 0x00;
pwm[1] = 0x00;
pwm[2] = 0x00;
pwm[3] = 0x00;
}
// printf("%3d %3d %3d %3d\n\r", pwm[0], pwm[1], pwm[2], pwm[3]);
twi_setpwm(pwm);
// adc_trigger();
return PITC_RESTART_TIMER;
}
static struct pitc_timer stick_timer = {
.interval = 10,
.func = &stick_timer_cb,
};
int main(void)
{
/* LED outputs */
*AT91C_PIOA_PER = LED_GREEN | LED_ORANGE;
*AT91C_PIOA_OER = LED_GREEN | LED_ORANGE;
/* needed for dbgu */
at91_sysc_init();
at91_dbgu_init();
at91_dbgu_puts("==========================================================\n\rGood morning Dave\n\r");
/* triggers pinchange-isrs */
at91_pio_init();
/* timer */
at91_pitc_init();
at91_rttc_test_init();
/* twi */
at91_twi_init();
at91_twi_test();
/* remote control, needs twi */
at91_tc1_init();
/* usb */
at91_udp_init();
/* adc, need timer, twi */
at91_adc_init();
pitc_schedule_timer(&stick_timer);
printf("static alloc: %5ld bytes\n\r", static_alloc_used());
while (1);
}
/***************************************************************************
* sam7fc - main loop *
* *
* Copyright (C) 01/2008 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; version 2 of the License *
* *
* 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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdio.h>
#include <string.h>
#include "AT91SAM7S256.h"
#include "board.h"
#include "at91_sysc.h"
#include "at91_dbgu.h"
#include "at91_pitc.h"
#include "at91_adc.h"
#include "at91_tests.h"
#include "at91_udp.h"
#include "at91_pio.h"
#include "at91_twi.h"
#include "at91_tc1.h"
#include "memalloc.h"
#include "telemetrie.h"
extern void base_ctrl(void);
volatile static uint32_t run_ctrl;
static uint32_t base_ctrl_trigger(struct pitc_timer *timer)
{
/* trigger adc, after ~15us () result should be ready */
adc_trigger();
run_ctrl = 1;
return PITC_RESTART_TIMER;
}
static struct pitc_timer base_timer = {
.interval = 2,
.func = &base_ctrl_trigger,
};
int main(void)
{
/* LED outputs */
*AT91C_PIOA_PER = LED_GREEN | LED_ORANGE;
*AT91C_PIOA_OER = LED_GREEN | LED_ORANGE;
/* needed for dbgu */
at91_sysc_init();
at91_dbgu_init();
at91_dbgu_puts("==========================================================\n\rGood morning Dave\n\r");
/* triggers pinchange-isrs */
at91_pio_init();
/* timer */
at91_pitc_init();
at91_rttc_test_init();
/* twi */
at91_twi_init();
at91_twi_test();
/* remote control, needs twi */
at91_tc1_init();
/* usb */
at91_udp_init();
/* adc, need timer, twi */
at91_adc_init();
pitc_schedule_timer(&base_timer);
tdc_init();
printf("static alloc: %5ld bytes\n\r", static_alloc_used());
while (1) {
if (run_ctrl) {
// TODO: racy?
run_ctrl = 0;
base_ctrl();
}
tdc_check();
}
}

194
src/at91_adc.c

@ -1,4 +1,6 @@
/***************************************************************************
* sam7fc - ADC routines / calibration *
* *
* Copyright (C) 01/2008 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
@ -18,28 +20,35 @@
***************************************************************************/
#include <stdint.h>
#include <stdio.h>
#include "AT91SAM7S256.h"
#include "board.h"
#include "at91_adc.h"
#include "at91_pitc.h"
#include "at91_twi.h"
#include "telemetrie.h"
#define ADC_CAL_COUNT 1024
static uint32_t adc_status;
static uint16_t adc_tmp[7];
static int16_t adc_result[7];
static uint16_t adc_offset[6];
TDC_PTR(adc_offset0, &adc_offset[ADC_GYRO_NICK], "XADC_GYRO_NICK (offset)", int16_t, TDC_UNSIGNED);
TDC_PTR(adc_offset1, &adc_offset[ADC_GYRO_ROLL], "XADC_GYRO_ROLL (offset)", int16_t, TDC_UNSIGNED);
TDC_PTR(adc_offset2, &adc_offset[ADC_GYRO_GIER], "XADC_GYRO_GIER (offset)", int16_t, TDC_UNSIGNED);
TDC_PTR(adc_offset3, &adc_offset[ADC_ACC_NICK], "XADC_ACC_NICK (offset)", int16_t, TDC_UNSIGNED);
TDC_PTR(adc_offset4, &adc_offset[ADC_ACC_ROLL], "XADC_ACC_ROLL (offset)", int16_t, TDC_UNSIGNED);
TDC_PTR(adc_offset5, &adc_offset[ADC_ACC_GIER], "XADC_ACC_GIER (offset)", int16_t, TDC_UNSIGNED);
#define ADC_CAL_COUNT_MAX 1024
static uint32_t adc_cal_count;
static uint32_t adc_cal_data[3];
/* check eeprom parameter size (3x uint16_t) */
#if ((3 * 2) != EE_ACC_CAL_DATA_SIZE)
#error "invalid EE_ACC_CAL_DATA_SIZE"
#endif
static uint32_t adc_cal_count;
volatile static uint32_t adc_cal_mode;
static uint32_t adc_cal_data[3];
static void at91_adc_isr(void)
{
AT91S_PDC *pdc = AT91C_BASE_PDC_ADC;
@ -48,71 +57,50 @@ static void at91_adc_isr(void)
pdc->PDC_PTCR = AT91C_PDC_RXTEN;
/* clear interrupts */
uint32_t status = *AT91C_ADC_SR;
status = status;
uint32_t dummy = *AT91C_ADC_SR;
dummy = dummy;
uint32_t i;
for (i = 0; i < ARRAY_SIZE(adc_offset); i++)
adc_result[i] = adc_tmp[i] - adc_offset[i];
/* (adc / 1024) * 3.3V * (11k / 1k) * 100 */
adc_result[ADC_VOLTAGE] = ((uint32_t)adc_tmp[ADC_VOLTAGE] * 3630) / 1024;
}
static uint32_t adc_calibrate_cb(struct pitc_timer *timer)
{
/* trigger next cycle */
*AT91C_ADC_CR = AT91C_ADC_START;
if (!(adc_status & (ADC_CAL_GYRO | ADC_CAL_ACC)))
return;
if (adc_cal_mode == ADC_CAL_GYRO) {
adc_cal_data[0] += adc_tmp[ADC_GYRO_ROLL];
adc_cal_data[1] += adc_tmp[ADC_GYRO_NICK];
adc_cal_data[2] += adc_tmp[ADC_GYRO_YAW];
if (adc_status & ADC_CAL_GYRO) {
adc_cal_data[0] += adc_tmp[ADC_GYRO_NICK];
adc_cal_data[1] += adc_tmp[ADC_GYRO_ROLL];
adc_cal_data[2] += adc_tmp[ADC_GYRO_GIER];
} else {
adc_cal_data[0] += adc_tmp[ADC_ACC_ROLL];
adc_cal_data[1] += adc_tmp[ADC_ACC_NICK];
adc_cal_data[2] += adc_tmp[ADC_ACC_YAW];
adc_cal_data[0] += adc_tmp[ADC_ACC_NICK];
adc_cal_data[1] += adc_tmp[ADC_ACC_ROLL];
adc_cal_data[2] += adc_tmp[ADC_ACC_GIER];
}
adc_cal_count--;
if (adc_cal_count == 0) {
adc_cal_data[0] /= ADC_CAL_COUNT;
adc_cal_data[1] /= ADC_CAL_COUNT;
adc_cal_data[2] /= ADC_CAL_COUNT;
adc_cal_count++;
}
if (adc_cal_mode == ADC_CAL_GYRO) {
adc_offset[ADC_GYRO_ROLL] = adc_cal_data[0];
adc_offset[ADC_GYRO_NICK] = adc_cal_data[1];
adc_offset[ADC_GYRO_YAW] = adc_cal_data[2];
static uint32_t adc_calibrate_cb(struct pitc_timer *timer)
{
if (adc_cal_count < ADC_CAL_COUNT_MAX) {
/* trigger next cycle */
*AT91C_ADC_CR = AT91C_ADC_START;
return PITC_RESTART_TIMER;
// TODO: check for invalid values (not centered)
} else {
if (adc_status & ADC_CAL_GYRO) {
adc_offset[ADC_GYRO_NICK] = adc_cal_data[0] / ADC_CAL_COUNT_MAX;
adc_offset[ADC_GYRO_ROLL] = adc_cal_data[1] / ADC_CAL_COUNT_MAX;
adc_offset[ADC_GYRO_GIER] = adc_cal_data[2] / ADC_CAL_COUNT_MAX;
printf("GYRO offsets: %4d/%4d/%4d\n\r",
adc_offset[ADC_GYRO_ROLL],
adc_offset[ADC_GYRO_NICK],
adc_offset[ADC_GYRO_YAW]);
adc_calibrate(ADC_CAL_GYRO_COMPLETE);
} else {
adc_offset[ADC_ACC_ROLL] = adc_cal_data[0];
adc_offset[ADC_ACC_NICK] = adc_cal_data[1];
adc_offset[ADC_ACC_NICK] = adc_cal_data[0] / ADC_CAL_COUNT_MAX;
adc_offset[ADC_ACC_ROLL] = adc_cal_data[1] / ADC_CAL_COUNT_MAX;
adc_offset[ADC_ACC_GIER] = adc_cal_data[2] / ADC_CAL_COUNT_MAX;
// TODO: only 1/2 offset?
adc_offset[ADC_ACC_YAW] = adc_cal_data[2];
printf("ACC offsets: %4d/%4d/%4d\n\r",
adc_offset[ADC_ACC_ROLL],
adc_offset[ADC_ACC_NICK],
adc_offset[ADC_ACC_YAW]);
twi_write_eeprom(EE_ACC_CAL_DATA, (uint8_t *)&(adc_offset[ADC_ACC_ROLL]), EE_ACC_CAL_DATA_SIZE);
adc_calibrate(ADC_CAL_ACC_COMPLETE);
}
adc_cal_mode = ADC_CAL_NONE;
return PITC_REMOVE_TIMER;
}
return PITC_RESTART_TIMER;
}
static struct pitc_timer adc_cal_timer = {
@ -122,28 +110,88 @@ static struct pitc_timer adc_cal_timer = {
void adc_trigger(void)
{
printf("R:%4d:%4d N:%4d:%4d Y:%4d:%4d U:%4d\n\r",
adc_result[ADC_GYRO_ROLL], adc_result[ADC_ACC_ROLL],
adc_result[ADC_GYRO_NICK], adc_result[ADC_ACC_NICK],
adc_result[ADC_GYRO_YAW], adc_result[ADC_ACC_YAW],
adc_result[ADC_VOLTAGE]);
// TODO: err in retvalue?
if (!(adc_status & (ADC_CAL_GYRO | ADC_CAL_ACC)))
*AT91C_ADC_CR = AT91C_ADC_START;
}
void adc_get_results(int16_t *adc_result)
{
// TODO: err in retvalue?
if (!(adc_status & (ADC_CAL_GYRO | ADC_CAL_ACC))) {
uint32_t i;
for (i = ADC_GYRO_NICK; i <= ADC_GYRO_GIER; i++)
adc_result[i] = (int16_t)(adc_offset[i]) - (int16_t)(adc_tmp[i]);
for (i = ADC_ACC_NICK; i <= ADC_ACC_GIER; i++)
adc_result[i] = (int16_t)(adc_tmp[i]) - (int16_t)(adc_offset[i]);
*AT91C_ADC_CR = AT91C_ADC_START;
/* (adc / 1024) * 3.3V * (11k / 1k) * 100 */
adc_result[ADC_VOLTAGE] = ((uint32_t)adc_tmp[ADC_VOLTAGE] * 3630) / 1024;
}
}
void adc_calibrate(uint32_t mode)
{
if (adc_cal_mode != ADC_CAL_NONE)
return;
if (mode == ADC_CAL_GYRO || mode == ADC_CAL_ACC) {
adc_cal_count = ADC_CAL_COUNT;
adc_cal_mode = mode;
/* disable interrupt */
*AT91C_ADC_IDR = AT91C_ADC_ENDRX;
switch (mode) {
case ADC_CAL_GYRO_COMPLETE:
adc_status &= ~ADC_CAL_GYRO;
break;
case ADC_CAL_ACC_COMPLETE:
twi_write_eeprom(EE_ACC_CAL_DATA,
(uint8_t *)&(adc_offset[ADC_ACC_NICK]),
EE_ACC_CAL_DATA_SIZE);
adc_status &= ~ADC_CAL_ACC;
break;
case ADC_CAL_ACC_LOAD:
twi_read_eeprom(EE_ACC_CAL_DATA,
(uint8_t *)&(adc_offset[ADC_ACC_NICK]),
EE_ACC_CAL_DATA_SIZE);
break;
case ADC_CAL_GYRO:
case ADC_CAL_ACC:
/* calibration in progress.. */
if (adc_status & (ADC_CAL_GYRO | ADC_CAL_ACC))
break;
adc_status |= mode;
adc_cal_count = 0;
adc_cal_data[0] = 0;
adc_cal_data[1] = 0;
adc_cal_data[2] = 0;
pitc_schedule_timer(&adc_cal_timer);
/* trigger next cycle */
*AT91C_ADC_CR = AT91C_ADC_START;
break;
}
if (!(adc_status & (ADC_CAL_GYRO | ADC_CAL_ACC))) {
printf("ADC offsets: %d/%d/%d %d/%d/%d\n\r",
adc_offset[ADC_GYRO_NICK],
adc_offset[ADC_GYRO_ROLL],
adc_offset[ADC_GYRO_GIER],
adc_offset[ADC_ACC_NICK],
adc_offset[ADC_ACC_ROLL],
adc_offset[ADC_ACC_GIER]);
}
/* enable interrupt */
*AT91C_ADC_IER = AT91C_ADC_ENDRX;
}
void adc_drift_adjust(int16_t nick, int16_t roll, int16_t yaw)
{
adc_offset[ADC_GYRO_NICK] += nick;
adc_offset[ADC_GYRO_ROLL] += roll;
adc_offset[ADC_GYRO_GIER] += yaw;
}
void at91_adc_init(void)
@ -185,12 +233,6 @@ void at91_adc_init(void)
aic->AIC_SVR[AT91C_ID_ADC] = (uint32_t)at91_adc_isr;
aic->AIC_IECR = (1<<AT91C_ID_ADC);
adc_calibrate(ADC_CAL_ACC_LOAD);
adc_calibrate(ADC_CAL_GYRO);
/* load ACC calibration data */
twi_read_eeprom(EE_ACC_CAL_DATA, (uint8_t *)&(adc_offset[ADC_ACC_ROLL]), EE_ACC_CAL_DATA_SIZE);
printf("ACC offsets: %4d/%4d/%4d\n\r",
adc_offset[ADC_ACC_ROLL],
adc_offset[ADC_ACC_NICK],
adc_offset[ADC_ACC_YAW]);
}

28
src/at91_dbgu.c

@ -1,4 +1,6 @@
/***************************************************************************
* sam7fc - Debug Unit RS232 Port *
* *
* Copyright (C) 01/2008 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
@ -24,27 +26,18 @@
#include "at91_sysc.h"
#include "fifo.h"
#define DBGU_BAUDRATE 115200
#define DBGU_FIFO_SIZE 1024
#define DBGU_TX_CHUNKS 16
static struct fifo *txfifo;
static void dbgu_isr(uint32_t status)
{
/* only enabled interrupts */
status &= *AT91C_DBGU_IMR;
/*
if (status & AT91C_US_TXEMPTY) {
static char c;
if (c == '\n') {
*AT91C_DBGU_THR = '\r';
c = 0;
} else if (fifo_getbyte(&txfifo, &c) == 1)
*AT91C_DBGU_THR = c;
else
*AT91C_DBGU_IDR = AT91C_US_TXEMPTY;
}
*/
if (status & AT91C_US_TXBUFE)
if (fifo_txpdc(txfifo, AT91C_BASE_PDC_DBGU, 16) == 0)
if (fifo_txpdc(txfifo, AT91C_BASE_PDC_DBGU, DBGU_TX_CHUNKS) == 0)
*AT91C_DBGU_IDR = AT91C_US_TXBUFE;
}
@ -55,11 +48,11 @@ void at91_dbgu_init(void)
/* enable Debug Port with 115200 Baud (+0.16%) */
AT91S_DBGU *dbgu = AT91C_BASE_DBGU;
dbgu->DBGU_BRGR = BAUD_TO_DIV(115200);
dbgu->DBGU_BRGR = BAUD_TO_DIV(DBGU_BAUDRATE);
dbgu->DBGU_MR = AT91C_US_PAR_NONE | AT91C_US_CHMODE_NORMAL;
dbgu->DBGU_CR = AT91C_US_RXEN | AT91C_US_TXEN | AT91C_US_RSTSTA;
txfifo = fifo_alloc(1024);
txfifo = fifo_alloc(DBGU_FIFO_SIZE);
/* enable TX PDC */
dbgu->DBGU_PTCR = AT91C_PDC_TXTEN;
@ -70,21 +63,18 @@ void at91_dbgu_init(void)
void at91_dbgu_putc(char c)
{
fifo_putbyte(txfifo, c);
// *AT91C_DBGU_IER = AT91C_US_TXEMPTY;
*AT91C_DBGU_IER = AT91C_US_TXBUFE;
}
void at91_dbgu_puts(const char *p)
{
fifo_put(txfifo, (char *)p, strlen(p));
// *AT91C_DBGU_IER = AT91C_US_TXEMPTY;
*AT91C_DBGU_IER = AT91C_US_TXBUFE;
}
int at91_dbgu_write(void *base, const char *buf, size_t len)
{
int retval = fifo_put(txfifo, (char *)buf, len);
// *AT91C_DBGU_IER = AT91C_US_TXEMPTY;
*AT91C_DBGU_IER = AT91C_US_TXBUFE;
return retval;
}

9
src/at91_exceptions.c

@ -1,4 +1,6 @@
/***************************************************************************
* sam7fc - Abort Handler with Register/Stackdump *
* *
* Copyright (C) 01/2008 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
@ -181,9 +183,8 @@ __attribute__((naked)) void ABT_Handler(void)
"mov r3, lr \n\t"
/* enter previous mode and get lr(r14), sp(r13) */
/* TODO: interrupts might be enabled? */
/* TODO: thumb mode enabled? */
"msr CPSR_c, r0 \n\t"
"orr r1, r0, #I_BIT | F_BIT \n\t"
"msr CPSR_c, r1 \n\t"
"mov r1, sp \n\t"
"mov r2, lr \n\t"
@ -194,7 +195,7 @@ __attribute__((naked)) void ABT_Handler(void)
"stmfd sp!, { r1-r3 } \n\t"
"mov r1, sp \n\t"
/* execute C Handler (cpsr, registers) */
/* execute C Handler (cpsr, *registers) */
"ldr r5, =at91_abt_handler \n\t"
"mov lr, pc \n\t"
"bx r5 \n\t"

4
src/at91_pio.c

@ -1,4 +1,6 @@
/***************************************************************************
* sam7fc - Pinchange Interrupt Handler *
* *
* Copyright (C) 01/2008 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
@ -55,7 +57,7 @@ void at91_pio_init(void)
/* enable pinchange interrupts */
struct pio_pinchange_isr *isr;
for (isr = &_pio_isr_table; isr < &_pio_isr_table_end; isr++)
*AT91C_PIOA_IER = isr->mask;
*AT91C_PIOA_IER = isr->mask;
/* dummy read to clear interrupts */
uint32_t dummy = *AT91C_PIOA_ISR;

35
src/at91_pitc.c

@ -1,4 +1,6 @@
/***************************************************************************
* sam7fc - Periodic Timer Handling *
* *
* Copyright (C) 01/2008 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
@ -21,13 +23,15 @@
#include "at91_sysc.h"
#include "board.h"
#define PITC_HZ 1000
/* PIV is 20bit -> min. 3Hz @48MHz MCK */
#define HZ_TO_PIV(HZ) (MCK / (16 * HZ))
static LIST_HEAD(timer_list);
volatile static uint32_t pitc_ticks;
void pitc_schedule_timer(struct pitc_timer *timer)
static void _pitc_schedule_timer(struct pitc_timer *timer)
{
timer->nextrun = timer->interval + pitc_ticks;
@ -39,6 +43,26 @@ void pitc_schedule_timer(struct pitc_timer *timer)
list_add_tail(&timer->list, &search->list);
}
void pitc_schedule_timer(struct pitc_timer *timer)
{
/* disable PITC interrupt */
*AT91C_PITC_PIMR &= ~AT91C_PITC_PITIEN;
/* check it timer is already running */
if (timer->nextrun == 0 && timer->interval > 0)
_pitc_schedule_timer(timer);
// TODO: if timer is running, interval changes are delayed
/* enable PITC interrupt */
*AT91C_PITC_PIMR |= AT91C_PITC_PITIEN;
}
void pitc_remove_timer(struct pitc_timer *timer)
{
timer->interval = 0;
}
static void pitc_isr(uint32_t status)
{
/* get Ticks and clear interrupt */
@ -54,13 +78,14 @@ static void pitc_isr(uint32_t status)
list_del(&search->list);
/* exec handler */
if (search->func(search) == PITC_REMOVE_TIMER) {
if ((search->interval == 0) || search->func(search) == PITC_REMOVE_TIMER) {
/* one-shot timer, mark as completed */
search->nextrun = 0x00;
search->nextrun = 0;
continue;
}
/* interval timer, reschedule it */
pitc_schedule_timer(search);
_pitc_schedule_timer(search);
}
}
@ -73,7 +98,7 @@ void at91_pitc_init(void)
{
sysc_register_isr(AT91_SYSIRQ_PIT, &pitc_isr);
*AT91C_PITC_PIMR = (AT91C_PITC_PIV & HZ_TO_PIV(1000)) |
*AT91C_PITC_PIMR = (AT91C_PITC_PIV & HZ_TO_PIV(PITC_HZ)) |
AT91C_PITC_PITEN |
AT91C_PITC_PITIEN;
}

25
src/at91_rttc_test.c

@ -1,3 +1,23 @@
/***************************************************************************
* sam7fc - Real Time Clock Calibration *
* *
* Copyright (C) 02/2008 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; version 2 of the License *
* *
* 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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdio.h>
#include "AT91SAM7S256.h"
#include "at91_sysc.h"
@ -6,11 +26,6 @@
static void rtt_isr(uint32_t status)
{
*AT91C_RTTC_RTAR = *AT91C_RTTC_RTVR +1;
static uint32_t i;
*AT91C_PIOA_SODR = i;
i = i ^ LED_ORANGE;
*AT91C_PIOA_CODR = i;
}
void at91_rttc_test_init(void)

30
src/at91_sysc.c

@ -1,4 +1,6 @@
/***************************************************************************
* sam7fc - System Interrupt Dispatcher *
* *
* Copyright (C) 01/2008 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
@ -31,15 +33,15 @@ struct _irq_regs {
/* same IDs as sysc_isrs enum! */
static const struct _irq_regs irq_regs[] = {
/*
/*
* PIT (Periodic Intervall Timer)
* ISR must read AT91C_PITC_PIVR to clear interrupt
* - PITIEN (Periodic Intervall Timer Interrupt Enable)
*/
*/
{ AT91C_PITC_PIMR, AT91C_PITC_PITIEN,
AT91C_PITC_PISR, AT91C_PITC_PITS
},
/*
* DBGU (Debug Unit)
* TODO: must use AT91C_DBGU_IDR to fault disable interrupt
@ -58,12 +60,12 @@ static const struct _irq_regs irq_regs[] = {
AT91C_US_TXBUFE | AT91C_US_RXBUFF |
AT91C_US_COMM_TX | AT91C_US_COMM_RX)
},
/*
* EFC (Embedded Flash Controller / Memory Controller)
*/
{ AT91C_MC_FMR, (AT91C_MC_FRDY | AT91C_MC_LOCKE | AT91C_MC_PROGE),
AT91C_MC_FSR, (AT91C_MC_FRDY | AT91C_MC_LOCKE | AT91C_MC_PROGE)
AT91C_MC_FSR, (AT91C_MC_FRDY | AT91C_MC_LOCKE | AT91C_MC_PROGE)
},
/*
@ -84,7 +86,7 @@ static const struct _irq_regs irq_regs[] = {
{ AT91C_RTTC_RTMR, (AT91C_RTTC_ALMIEN | AT91C_RTTC_RTTINCIEN),
AT91C_RTTC_RTSR, (AT91C_RTTC_ALMS | AT91C_RTTC_RTTINC)
},
/*
* RSTC (Reset Controller)
* - AT91C_RSTC_URSTIEN (User Reset Interrupt Enable)
@ -104,27 +106,27 @@ static const struct _irq_regs irq_regs[] = {
AT91C_PMC_PCK1RDY | AT91C_PMC_PCK2RDY),
AT91C_PMC_SR, (AT91C_PMC_MOSCS | AT91C_PMC_LOCK |
AT91C_PMC_MCKRDY | AT91C_PMC_PCK0RDY |
AT91C_PMC_PCK1RDY | AT91C_PMC_PCK2RDY)
AT91C_PMC_PCK1RDY | AT91C_PMC_PCK2RDY)
},
};
};
/* check Interrupts from internal hardware */
static void at91_sysc_isr(void)
{
uint32_t id;
for (id = 0; id < AT91_SYSIRQ_COUNT; id++) {
/* check if interrups are enabled */
if (*(irq_regs[id].mask_register) & irq_regs[id].mask) {
/* check if interrupts are active */
uint32_t status = *(irq_regs[id].status_register);
if (status & irq_regs[id].status) {
/* execute handler */
if (sysc_isrs[id]) {
sysc_isrs[id](status);
} else {
/* disable interrupts */
*(irq_regs[id].mask_register) &= ~irq_regs[id].mask;
@ -138,9 +140,9 @@ void at91_sysc_init(void)
{
/* high priority, level triggered, own vector */
AT91S_AIC *aic = AT91C_BASE_AIC;
aic->AIC_SMR[AT91C_ID_SYS] = IRQPRIO_SYSC |
aic->AIC_SMR[AT91C_ID_SYS] = IRQPRIO_SYSC |
AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL;
aic->AIC_SVR[AT91C_ID_SYS] = (uint32_t)at91_sysc_isr;
aic->AIC_IECR = (1<<AT91C_ID_SYS);
}
@ -149,6 +151,6 @@ void sysc_register_isr(enum syscirqs irq, SYSCISR *isr)
{
if (irq >= AT91_SYSIRQ_COUNT)
return;
sysc_isrs[irq] = isr;
}

20
src/at91_tc1.c

@ -1,4 +1,6 @@
/***************************************************************************
* sam7fc - RC-PPM Signal decoder *
* *
* Copyright (C) 01/2008 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
@ -133,15 +135,9 @@ uint32_t rcontrol_getvalues(struct rc_values *rc)
int32_t tmp = (uint32_t)(width - ch_data[i].mid) * VALUE_RANGE;
tmp = tmp / ((tmp > 0) ? (ch_data[i].max - ch_data[i].mid) : (ch_data[i].mid - ch_data[i].min));
/* keep result in range */
if (tmp > VALUE_RANGE)
tmp = VALUE_RANGE;
if (tmp < -VALUE_RANGE)
tmp = -VALUE_RANGE;
// TODO: stick mapping
rc->chan[i] = tmp;
/* keep result in range */
rc->chan[i] = LIMIT(tmp, -VALUE_RANGE, +VALUE_RANGE);
}
return cnt;
}
@ -189,11 +185,11 @@ void rcontrol_calibrate(uint32_t mode)
/* treat current position as center */
ch_data[i].mid = ch_data[i].width_slow;
/* if center is near minimum, clamp output to 0..+1024 */
/* if center is near minimum, clamp output to 0..+RANGE */
if (ch_data[i].mid - ch_data[i].min < PULSE_MID_DIFF)
ch_data[i].mid = ch_data[i].min;
/* if center is near maximum, clamp output to -1024..0 */
/* if center is near maximum, clamp output to -RANGE..0 */
if (ch_data[i].max - ch_data[i].mid < PULSE_MID_DIFF)
ch_data[i].mid = ch_data[i].max;
}
@ -204,7 +200,7 @@ void rcontrol_calibrate(uint32_t mode)
for (i = 0; i < ARRAY_SIZE(ch_data); i++) {
ch_data[i].min = *ptr++;
ch_data[i].mid = *ptr++;
ch_data[i].min = *ptr++;
ch_data[i].max = *ptr++;
}
break;
@ -212,7 +208,7 @@ void rcontrol_calibrate(uint32_t mode)
for (i = 0; i < ARRAY_SIZE(ch_data); i++) {
*ptr++ = ch_data[i].min;
*ptr++ = ch_data[i].mid;
*ptr++ = ch_data[i].min;
*ptr++ = ch_data[i].max;
}
twi_write_eeprom(EE_RC_CAL_DATA, buf, EE_RC_CAL_DATA_SIZE);
break;

2
src/at91_twi.c

@ -1,4 +1,6 @@
/***************************************************************************
* sam7fc - TWI/I2C Handling *
* *
* Copyright (C) 02/2008 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *

38
src/at91_udp.c

@ -1,4 +1,6 @@
/***************************************************************************
* sam7fc - USB Device Port with logical Serial Port *
* *
* Copyright (C) 01/2008 by Olaf Rempel *
* razzor@kopf-tisch.de *
* *
@ -21,6 +23,7 @@
#include "at91_pio.h"
#include "board.h"
#include "fifo.h"
#include "telemetrie.h"
#include "usb_ch9.h"
#include "usb_cdc.h"
@ -66,6 +69,8 @@ static uint16_t current_address;
static uint16_t current_config;
static uint16_t current_interface;
static struct comm_device usb_comm;
static const struct usb_device_descriptor dev_descriptor = {
.bLength = sizeof(struct usb_device_descriptor),
.bDescriptorType = USB_DT_DEVICE,
@ -317,6 +322,12 @@ static void udp_txcb_setconfig(void)
udp_configure_ep(&cfg_descriptor.datain_ep);
udp_configure_ep(&cfg_descriptor.dataout_ep);
ep_ctx[1].fifo = usb_comm.rxfifo;
ep_ctx[1].flags |= CTX_FIFO;
ep_ctx[2].fifo = usb_comm.txfifo;
ep_ctx[2].flags |= CTX_FIFO;
/* set UDP to "configured" */
*AT91C_UDP_GLBSTATE = AT91C_UDP_CONFG;
udp_print_config();
@ -473,9 +484,13 @@ static void udp_handle_ep(uint32_t ep)
if (ctx->flags & CTX_FIFO) {
/* get data from fifo */
if (fifo_txudp(ctx->fifo, ep, ctx->maxpktsize))
if (fifo_txudp(ctx->fifo, ep, ctx->maxpktsize)) {
AT91C_UDP_CSR[ep] |= AT91C_UDP_TXPKTRDY;
} else {
ctx->flags &= ~CTX_IN;
}
} else if ((ctx->flags & (CTX_TRANSFER | CTX_IN)) == (CTX_TRANSFER | CTX_IN)) {
/* transfer not complete */
struct ep_transfer *transfer = ctx->transfer;
@ -599,6 +614,21 @@ static void udp_isr(void)
AT91C_UDP_ENDBUSRES | AT91C_UDP_WAKEUP);
}
static void trigger_fifo_tx(void)
{
struct ep_ctx *ctx = &ep_ctx[2];
/* currently transmitting, no need to trigger */
// TODO: racy?
if (ctx->flags & CTX_IN)
return;
if (fifo_txudp(ctx->fifo, 2, ctx->maxpktsize)) {
ctx->flags |= CTX_IN;
AT91C_UDP_CSR[2] |= AT91C_UDP_TXPKTRDY;
}
}
void at91_udp_init(void)
{
/* configure & disable Pullup, disable Pullup von VBUS */
@ -631,6 +661,12 @@ void at91_udp_init(void)
aic->AIC_SVR[AT91C_ID_UDP] = (uint32_t)udp_isr;
aic->AIC_IECR = (1 << AT91C_ID_UDP);
usb_comm.rxfifo = fifo_alloc(1024);
usb_comm.txfifo = fifo_alloc(1024);
usb_comm.trigger_tx = trigger_fifo_tx;
tdc_register_device(0, &usb_comm);
pio_trigger_isr(UDP_VBUS_MON);
}

4
src/fifo.c