Browse Source

Initial revision

master
Raphaël Assénat 8 years ago
commit
c0ea2489c0
35 changed files with 9451 additions and 0 deletions
  1. BIN
      .generate_rxcode.sh.swp
  2. BIN
      .maplebus.c.swp
  3. +85
    -0
      Makefile
  4. +35
    -0
      checksize
  5. +178
    -0
      dc_pad.c
  6. +4
    -0
      dc_pad.h
  7. +27
    -0
      gamepad.h
  8. +12
    -0
      generate_rxcode.sh
  9. +317
    -0
      main.c
  10. +347
    -0
      maplebus.c
  11. +12
    -0
      maplebus.h
  12. +643
    -0
      rxcode.asm
  13. +364
    -0
      usbconfig.h
  14. +329
    -0
      usbdrv/Changelog.txt
  15. +166
    -0
      usbdrv/CommercialLicense.txt
  16. +361
    -0
      usbdrv/License.txt
  17. +172
    -0
      usbdrv/Readme.txt
  18. +149
    -0
      usbdrv/USB-ID-FAQ.txt
  19. +154
    -0
      usbdrv/USB-IDs-for-free.txt
  20. +187
    -0
      usbdrv/asmcommon.inc
  21. +49
    -0
      usbdrv/oddebug.c
  22. +122
    -0
      usbdrv/oddebug.h
  23. +384
    -0
      usbdrv/usbconfig-prototype.h
  24. +628
    -0
      usbdrv/usbdrv.c
  25. +746
    -0
      usbdrv/usbdrv.h
  26. +392
    -0
      usbdrv/usbdrvasm.S
  27. +20
    -0
      usbdrv/usbdrvasm.asm
  28. +392
    -0
      usbdrv/usbdrvasm12.inc
  29. +749
    -0
      usbdrv/usbdrvasm128.inc
  30. +422
    -0
      usbdrv/usbdrvasm15.inc
  31. +345
    -0
      usbdrv/usbdrvasm16.inc
  32. +452
    -0
      usbdrv/usbdrvasm165.inc
  33. +706
    -0
      usbdrv/usbdrvasm18-crc.inc
  34. +359
    -0
      usbdrv/usbdrvasm20.inc
  35. +143
    -0
      usbdrv/usbportability.h

BIN
.generate_rxcode.sh.swp View File


BIN
.maplebus.c.swp View File


+ 85
- 0
Makefile View File

@ -0,0 +1,85 @@
CC=avr-gcc
AS=$(CC)
LD=$(CC)
PROGNAME=dc_usb
CPU=atmega168
CFLAGS=-Wall -Os -Iusbdrv -I. -mmcu=$(CPU) -DF_CPU=16000000L #-DDEBUG_LEVEL=1
LDFLAGS=-Wl,-Map=$(PROGNAME).map -mmcu=$(CPU)
AVRDUDE=avrdude -p m168 -P usb -c avrispmkII
OBJS=usbdrv/usbdrv.o usbdrv/usbdrvasm.o main.o maplebus.o dc_pad.o
HEXFILE=$(PROGNAME).hex
ELFFILE=$(PROGNAME).elf
# symbolic targets:
all: $(HEXFILE)
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
.S.o:
$(CC) $(CFLAGS) -x assembler-with-cpp -c $< -o $@
# "-x assembler-with-cpp" should not be necessary since this is the default
# file type for the .S (with capital S) extension. However, upper case
# characters are not always preserved on Windows. To ensure WinAVR
# compatibility define the file type manually.
.c.s:
$(CC) $(CFLAGS) -S $< -o $@
clean:
rm -f $(HEXFILE) $(PROGNAME).map $(PROGNAME).elf $(PROGNAME).hex *.o usbdrv/*.o main.s usbdrv/oddebug.s usbdrv/usbdrv.s
# file targets:
$(ELFFILE): $(OBJS)
$(LD) $(LDFLAGS) -o $(ELFFILE) $(OBJS)
$(HEXFILE): $(ELFFILE)
rm -f $(HEXFILE)
avr-objcopy -j .text -j .data -O ihex $(ELFFILE) $(HEXFILE)
./checksize $(ELFFILE)
flash: $(HEXFILE)
$(AVRDUDE) -Uflash:w:$(HEXFILE) -B 1.0
# Extended fuse byte (Datasheet Table 28-5)
#
# - - - - - BOOTSZ1 BOOTSZ0 BOOTRST
# 0 0 0 0 0 0 0 1
#
EFUSE=0x01
# Fuse high byte (Datasheet Table 28-6)
#
# RSTDISBL DWEN SPIEN WDTON EESAVE BODLEVEL2 BODLEVEL1 BODLEVEL0
# 1 1 0 1 0 1 0 1
#
HFUSE=0xd5
# Fuse low byte (Datasheet Table 28-7)
#
# CKDIV8 CKOUT SUT1 SUT0 CKSEL3 CKSEL2 CKSEL1 CKSEL0
# 1 1 0 1 0 1 1 1
#
# Full swing crystal oscillator
# 0.4 - 20 MHz : CKSEL3..1 011
#
# Crystal Oscillator, BOD enabled (Table 9-6)
# CKSEL0 : 1
# SUT1..0 : 01
#
LFUSE=0xD7
fuse:
$(AVRDUDE) -e -Uefuse:w:$(EFUSE):m -Uhfuse:w:$(HFUSE):m -Ulfuse:w:$(LFUSE):m -B 20.0 -v
chip_erase:
$(AVRDUDE) -e -B 1.0 -F
reset:
$(AVRDUDE) -B 1.0 -F

+ 35
- 0
checksize View File

@ -0,0 +1,35 @@
#!/bin/sh
# Name: checksize
# Project: AVR-USB
# Author: Christian Starkjohann
# Creation Date: 2004-12-29
# Tabsize: 4
# Copyright: (c) 2005 OBJECTIVE DEVELOPMENT Software GmbH.
# Revision: $Id: checksize,v 1.1 2013-10-13 21:01:08 cvs Exp $
error=0
codelimit=8192
datalimit=960 # leave 64 bytes for stack
if [ $# -gt 1 ]; then
codelimit="$2"
fi
if [ $# -gt 2 ]; then
datalimit="$3"
fi
set -- `avr-size -d "$1" | awk '/[0-9]/ {print $1 + $2, $2 + $3, $2}'`
if [ $1 -gt $codelimit ]; then
echo "*** code size $1 exceeds limit of $codelimit"
error=1
else
echo "ROM: $1 bytes (data=$3)"
fi
if [ $2 -gt $datalimit ]; then
echo "*** data size $2 exceeds limit of $datalimit"
error=1
else
echo "RAM: $2 bytes"
fi
exit $error

+ 178
- 0
dc_pad.c View File

@ -0,0 +1,178 @@
/* Saturn to USB : Sega dc controllers to USB adapter
* Copyright (C) 2011-2013 Raphaël Assénat
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* The author may be contacted at raph@raphnet.net
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <string.h>
#include "usbdrv.h"
#include "gamepad.h"
#include "dc_pad.h"
#include "maplebus.h"
#define MAX_REPORT_SIZE 4
#define NUM_REPORTS 1
// report matching the most recent bytes from the controller
static unsigned char last_built_report[NUM_REPORTS][MAX_REPORT_SIZE];
// the most recently reported bytes
static unsigned char last_sent_report[NUM_REPORTS][MAX_REPORT_SIZE];
static char report_sizes[NUM_REPORTS] = { 4 };
static Gamepad dcGamepad;
static void dcUpdate(void);
/*
* [0] X
* [1] Y
* [2] Btn 0-7
* [3] Btn 8-15
*/
static const unsigned char dcPadReport[] PROGMEM = {
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x05, // USAGE (Game pad)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x10, // USAGE_MAXIMUM (Button 16)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x10, // REPORT_COUNT (16)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
};
const unsigned char dcPadDevDesc[] PROGMEM = { /* USB device descriptor */
18, /* sizeof(usbDescrDevice): length of descriptor in bytes */
USBDESCR_DEVICE, /* descriptor type */
0x01, 0x01, /* USB version supported */
USB_CFG_DEVICE_CLASS,
USB_CFG_DEVICE_SUBCLASS,
0, /* protocol */
8, /* max packet size */
0x9B, 0x28, // Vendor ID
0x08, 0x00, // Product ID
0x00, 0x01, // Version: Minor, Major
1, // Manufacturer String
2, // Product string
3, // Serial number string
1, /* number of configurations */
};
static uint32_t request_device_info[1] = { 0x01200000 };
static uint32_t get_condition[2] = { 0x09200001, 0x00000001 };
static void dcInit(void)
{
dcUpdate();
dcGamepad.reportDescriptor = (void*)dcPadReport;
dcGamepad.reportDescriptorSize = sizeof(dcPadReport);
dcGamepad.deviceDescriptor = (void*)dcPadDevDesc;
dcGamepad.deviceDescriptorSize = sizeof(dcPadDevDesc);
maple_sendFrame(request_device_info, 1);
}
static void dcReadPad(void)
{
unsigned char tmp[30];
static unsigned char a;
int v;
unsigned char lrc = 0;
int i;
again:
maple_sendFrame(get_condition, 2);
v = maple_receivePacket(tmp, 30);
if (v<0)
return;
// 8 : Left trigger
// 9 : Right trigger
// 10 : Buttons
// 11 : Buttons
// 12 : Joy Y 2
// 13 : Joy X 2
// 14 : Y axis
// 15 : X axis
//
last_built_report[0][0] = tmp[15]-1;
last_built_report[0][1] = tmp[14]-1;
last_built_report[0][2] = tmp[10] ^ 0xff;
last_built_report[0][3] = tmp[11] ^ 0xff;
}
static void dcUpdate(void)
{
dcReadPad();
}
static char dcBuildReport(unsigned char *reportBuffer, unsigned char report_id)
{
report_id = 0;
if (reportBuffer != NULL)
{
memcpy(reportBuffer, last_built_report[report_id], report_sizes[report_id]);
}
memcpy(last_sent_report[report_id], last_built_report[report_id],
report_sizes[report_id]);
return report_sizes[report_id];
}
static char dcChanged(unsigned char report_id)
{
report_id = 0;
return memcmp(last_built_report[report_id], last_sent_report[report_id],
report_sizes[report_id]);
}
static Gamepad dcGamepad = {
num_reports: 1,
init: dcInit,
update: dcUpdate,
changed: dcChanged,
buildReport: dcBuildReport
};
Gamepad *dcGetGamepad(void)
{
return &dcGamepad;
}

+ 4
- 0
dc_pad.h View File

@ -0,0 +1,4 @@
#include "gamepad.h"
Gamepad *dcGetGamepad(void);

+ 27
- 0
gamepad.h View File

@ -0,0 +1,27 @@
#ifndef _gamepad_h__
#define _gamepad_h__
typedef struct {
// size of reports built by buildReport
char num_reports;
int reportDescriptorSize;
void *reportDescriptor; // must be in flash
int deviceDescriptorSize; // if 0, use default
void *deviceDescriptor; // must be in flash
void (*init)(void);
void (*update)(void);
char (*changed)(unsigned char id);
/**
* \param id Controller id (starting at 1 to match report IDs)
* \return The number of bytes written to buf.
* */
char (*buildReport)(unsigned char *buf, unsigned char id);
} Gamepad;
#endif // _gamepad_h__

+ 12
- 0
generate_rxcode.sh View File

@ -0,0 +1,12 @@
#!/bin/bash
NSAMPLES=640
echo "// Generated by generate_rxcode.sh"
echo "// Number of samples: $NSAMPLES"
for i in `seq 0 $NSAMPLES`
do
echo "\" in r16, %1\n st z+, r16 \n\" // sample $i "
#echo "\" in r16, %1\n sbi 0x5, 4\ncbi 0x5, 4 \n\" // sample $i "
done

+ 317
- 0
main.c View File

@ -0,0 +1,317 @@
/* Saturn to USB : Sega saturn controllers to USB adapter
* Copyright (C) 2011 Raphaël Assénat
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* The author may be contacted at raph@raphnet.net
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include <string.h>
#include "usbdrv.h"
#include "oddebug.h"
#include "gamepad.h"
#include "dc_pad.h"
static usbMsgPtr_t rt_usbHidReportDescriptor = USB_NO_MSG;
static usbMsgLen_t rt_usbHidReportDescriptorSize = 0;
static usbMsgPtr_t rt_usbDeviceDescriptor = USB_NO_MSG;
static usbMsgLen_t rt_usbDeviceDescriptorSize = 0;
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168A__) || \
defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328__) || \
defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88__) || \
defined(__AVR_ATmega88A__) || defined(__AVR_ATmega88P__) || \
defined(__AVR_ATmega88PA__)
#define AT168_COMPATIBLE
#endif
const PROGMEM int usbDescriptorStringSerialNumber[] = {
USB_STRING_DESCRIPTOR_HEADER(4),
'1','0','0','0'
};
char usbDescriptorConfiguration[] = { 0 }; // dummy
uchar my_usbDescriptorConfiguration[] = { /* USB configuration descriptor */
9, /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */
USBDESCR_CONFIG, /* descriptor type */
18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 9, 0,
/* total length of data returned (including inlined descriptors) */
1, /* number of interfaces in this configuration */
1, /* index of this configuration */
0, /* configuration name string index */
#if USB_CFG_IS_SELF_POWERED
USBATTR_SELFPOWER, /* attributes */
#else
USBATTR_BUSPOWER, /* attributes */
#endif
USB_CFG_MAX_BUS_POWER/2, /* max USB current in 2mA units */
/* interface descriptor follows inline: */
9, /* sizeof(usbDescrInterface): length of descriptor in bytes */
USBDESCR_INTERFACE, /* descriptor type */
0, /* index of this interface */
0, /* alternate setting for this interface */
USB_CFG_HAVE_INTRIN_ENDPOINT, /* endpoints excl 0: number of endpoint descriptors to follow */
USB_CFG_INTERFACE_CLASS,
USB_CFG_INTERFACE_SUBCLASS,
USB_CFG_INTERFACE_PROTOCOL,
0, /* string index for interface */
//#if (USB_CFG_DESCR_PROPS_HID & 0xff) /* HID descriptor */
9, /* sizeof(usbDescrHID): length of descriptor in bytes */
USBDESCR_HID, /* descriptor type: HID */
0x01, 0x01, /* BCD representation of HID version */
0x00, /* target country code */
0x01, /* number of HID Report (or other HID class) Descriptor infos to follow */
0x22, /* descriptor type: report */
USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH, 0, /* total length of report descriptor */
//#endif
#if USB_CFG_HAVE_INTRIN_ENDPOINT /* endpoint descriptor for endpoint 1 */
7, /* sizeof(usbDescrEndpoint) */
USBDESCR_ENDPOINT, /* descriptor type = endpoint */
0x81, /* IN endpoint number 1 */
0x03, /* attrib: Interrupt endpoint */
8, 0, /* maximum packet size */
USB_CFG_INTR_POLL_INTERVAL, /* in ms */
#endif
};
static Gamepad *curGamepad;
/* ----------------------- hardware I/O abstraction ------------------------ */
static void hardwareInit(void)
{
/* PORTB
*
* Bit Description Direction Level/pu
* 0 Jumpers common Out 0
* 1 JP1 In 1
* 2 JP2 In 1
* 3 MOSI In 1
* 4 MISO In 1
* 5 SCK In 1
* 6 -
* 7 -
*/
DDRB = 0x01;
PORTB = 0xFE;
// temporaty debug pin PB4
DDRB |= 0x10;
/*
* PORTC
*
* Bit
* 0 Pin 1
* 1 Pin 5
*/
DDRC = 0x00;
PORTC = 0xff;
/*
* For port D, activate pull-ups on all lines except the D+, D- and bit 1.
*
* For historical reasons (a mistake on an old PCB), bit 1
* is now always connected with bit 0. So bit 1 configured
* as an input without pullup.
*
* Usb pin are init as output, low. (device reset). They are released
* later when usbReset() is called.
*/
PORTD = 0xf8;
DDRD = 0x01 | 0x04;
/* Configure timers */
#if defined(AT168_COMPATIBLE)
TCCR2A= (1<<WGM21);
TCCR2B=(1<<CS22)|(1<<CS21)|(1<<CS20);
OCR2A=196; // for 60 hz
#else
TCCR2 = (1<<WGM21)|(1<<CS22)|(1<<CS21)|(1<<CS20);
OCR2 = 196; // for 60 hz
#endif
}
#if defined(AT168_COMPATIBLE)
#define mustPollControllers() (TIFR2 & (1<<OCF2A))
#define clrPollControllers() do { TIFR2 = 1<<OCF2A; } while(0)
#else
#define mustPollControllers() (TIFR & (1<<OCF2))
#define clrPollControllers() do { TIFR = 1<<OCF2; } while(0)
#endif
static void usbReset(void)
{
/* [...] a single ended zero or SE0 can be used to signify a device
reset if held for more than 10mS. A SE0 is generated by holding
both th D- and D+ low (< 0.3V).
*/
PORTD &= ~(0x01 | 0x04); // Set D+ and D- to 0
DDRD |= 0x01 | 0x04;
_delay_ms(15);
DDRD &= ~(0x01 | 0x04);
}
static uchar reportBuffer[16]; /* buffer for HID reports */
/* ------------------------------------------------------------------------- */
/* ----------------------------- USB interface ----------------------------- */
/* ------------------------------------------------------------------------- */
usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq)
{
if ((rq->bmRequestType & USBRQ_TYPE_MASK) != USBRQ_TYPE_STANDARD)
return 0;
if (rq->bRequest == USBRQ_GET_DESCRIPTOR)
{
// USB spec 9.4.3, high byte is descriptor type
switch (rq->wValue.bytes[1])
{
case USBDESCR_DEVICE:
usbMsgPtr = rt_usbDeviceDescriptor;
return rt_usbDeviceDescriptorSize;
case USBDESCR_HID_REPORT:
usbMsgPtr = rt_usbHidReportDescriptor;
return rt_usbHidReportDescriptorSize;
case USBDESCR_CONFIG:
usbMsgPtr = (usbMsgPtr_t)my_usbDescriptorConfiguration;
return sizeof(my_usbDescriptorConfiguration);
}
}
return 0;
}
usbMsgLen_t usbFunctionSetup(uchar data[8])
{
usbRequest_t *rq = (void *)data;
usbMsgPtr = (usbMsgPtr_t)reportBuffer;
if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */
if(rq->bRequest == USBRQ_HID_GET_REPORT){ /* wValue: ReportType (highbyte), ReportID (lowbyte) */
return curGamepad->buildReport(reportBuffer, rq->wValue.bytes[0]);
}
}else{
/* no vendor specific requests implemented */
}
return 0;
}
/* ------------------------------------------------------------------------- */
int main(void)
{
char must_report = 0;
int i;
hardwareInit();
curGamepad = dcGetGamepad();
// A small delay is required before calling init. Otherwise,
// the shuttlemouse is not ready and the adapter runs
// in joystick mode.
_delay_ms(25);
curGamepad->init();
// configure report descriptor according to
// the current gamepad
rt_usbHidReportDescriptor = (usbMsgPtr_t)curGamepad->reportDescriptor;
rt_usbHidReportDescriptorSize = curGamepad->reportDescriptorSize;
rt_usbDeviceDescriptor = (usbMsgPtr_t)curGamepad->deviceDescriptor;
rt_usbDeviceDescriptorSize = curGamepad->deviceDescriptorSize;
// patch the config descriptor with the HID report descriptor size
my_usbDescriptorConfiguration[25] = rt_usbHidReportDescriptorSize;
usbReset();
usbInit();
set_sleep_mode(SLEEP_MODE_IDLE);
sei();
for(;;){ /* main event loop */
wdt_reset();
// this must be called at each 50 ms or less
usbPoll();
if (mustPollControllers())
{
clrPollControllers();
sleep_enable();
sleep_cpu();
sleep_disable();
_delay_us(100);
curGamepad->update();
for (i=0; i<curGamepad->num_reports; i++) {
if (curGamepad->changed(i+1)) {
must_report |= (1<<i);
}
}
}
if(must_report)
{
for (i=0; i<curGamepad->num_reports; i++) {
int len;
if (!(must_report & (1<<i)))
continue;
len = curGamepad->buildReport(reportBuffer, i+1);
while(!usbInterruptIsReady()) {
usbPoll();
}
usbSetInterrupt(reportBuffer, len);
must_report &= ~(1<<i);
}
}
}
return 0;
}
/* ------------------------------------------------------------------------- */

+ 347
- 0
maplebus.c View File

@ -0,0 +1,347 @@
#include <avr/io.h>
#include <util/delay.h>
#include "usbdrv.h"
//
//
// PORTC0 : Pin 1
// PORTC1 : Pin 5
//
void maple_init(void)
{
}
#define MAPLE_BUF_SIZE 640
static unsigned char maplebuf[MAPLE_BUF_SIZE];
static unsigned char buf_used;
static unsigned char buf_phase;
#define PIN_1 0x01
#define PIN_5 0x02
static void buf_reset(void)
{
buf_used = 0;
buf_phase = 0;
}
static void buf_addBit(char value)
{
if (buf_phase & 0x01) {
maplebuf[buf_used] = PIN_5;
if (value) {
maplebuf[buf_used] |= PIN_1; // prepare data
}
buf_used++;
}
else {
maplebuf[buf_used] = PIN_1;
if (value) {
maplebuf[buf_used] |= PIN_5; // prepare data
}
buf_used++;
}
buf_phase ^= 1;
}
static int maplebus_decode(unsigned char *data, unsigned int maxlen)
{
unsigned char dst_b;
unsigned int dst_pos;
unsigned char last;
unsigned char last_fell;
int i;
// Look for the initial phase 1 (Pin 1 high, Pin 5 low). This
// is to skip what we got of the sync/start of frame sequence.
//
for (i=0; i<MAPLE_BUF_SIZE; i++) {
if ((maplebuf[i]&0x03) == 0x01)
break;
}
if (i==MAPLE_BUF_SIZE) {
return -1; // timeout
}
dst_pos = 0;
data[0] = 0;
dst_b = 0x80;
last = maplebuf[i] & 0x03;
last_fell = 0;
for (; i<MAPLE_BUF_SIZE; i++) {
unsigned char fell;
unsigned char cur = maplebuf[i];
if (cur == last) {
continue; // no change
}
fell = last & (cur ^ last);
if (!fell) {
// pin(s) changed, but none fell.
last = cur;
continue;
}
if (fell == last_fell) {
// two identical consecutive phases marks the end of the packet.
PORTB |= 0x10;
PORTB &= ~0x10;
break;
}
// when any of the two pins fall, the
// other pin is the data.
if (fell) {
if (fell == 0x03) {
// two pins at the same time!
PORTB |= 0x10;
PORTB &= ~0x10;
}
if (cur) {
data[dst_pos] |= dst_b;
}
else {
}
}
dst_b >>= 1;
if (!dst_b) {
dst_b = 0x80;
dst_pos++;
data[dst_pos] = 0;
}
last_fell = fell;
last = cur;
}
#if 0
for (i=0; i<dst_pos; i++) {
int j;
for (j=0; j<8; j++) {
if (data[i] & (0x80 >> j)) {
PORTB |= 0x10;
} else {
PORTB &= ~0x10;
}
_delay_us(5);
}
}
PORTB &= ~0x10;
#endif
return dst_pos;
}
/**
* \param data Destination buffer to store reply (payload + crc + eot)
* \param maxlen The length of the destination buffer
* \return -1 on timeout, -2 lrc/frame error, otherwise the number of bytes received
*/
int maple_receivePacket(unsigned char *data, unsigned int maxlen)
{
unsigned char *tmp = maplebuf;
unsigned char lrc;
int res, i;
//
// __ _ _ _
// |_____| |_| |_| |_
// ___ _ _ _
// |_| |___| |_| |_
// 310022011023102310
// ^ ^ ^ ^^ ^^
//
asm volatile(
" push r30 \n" // 2
" push r31 \n" // 2
// " sbi 0x5, 4 \n" // PB4
// " cbi 0x5, 4 \n"
// Loop until a change is detected.
" in r17, %1 \n"
"wait_start: \n"
" in r16, %1 \n"
" cp r16, r17 \n"
" breq wait_start \n"
" sbi 0x5, 4 \n" // PB4
" cbi 0x5, 4 \n"
// We will loose the first bit(s), but
// it's only the start of frame.
"start_rx: \n"
#include "rxcode.asm"
" sbi 0x5, 4 \n" // PB4
" cbi 0x5, 4 \n"
" pop r31 \n" // 2
" pop r30 \n" // 2
: "=z"(tmp)
: "I" (_SFR_IO_ADDR(PINC))
: "r16","r17") ;
res = maplebus_decode(data, maxlen);
if (res<=0)
return res;
// A packet containts n groups of 4 bytes, plus 1 byte crc.
if (((res-1) & 0x3) != 0) {
return -2; // frame error
}
for (lrc=0, i=0; i<res; i++) {
lrc ^= data[i];
}
if (lrc)
return -2; // LRC error
return res-1; // remove lrc
}
void maple_sendPacket(unsigned char *data, unsigned char len)
{
int i;
unsigned char b;
// SET PINS
// SET PINS
// SET PINS
// DLY
buf_reset();
for (i=0; i<len; i++) {
for (b=0x80; b; b>>=1)
{
buf_addBit(data[i] & b);
}
}
// Output
PORTC |= 0x03;
DDRC |= 0x03;
// DC controller pin 1 and pin 5
#define SET_1 " sbi %0, 0\n"
#define CLR_1 " cbi %0, 0\n"
#define SET_5 " sbi %0, 1\n"
#define CLR_5 " cbi %0, 1\n"
#define DLY_8 " nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n"
#define DLY_4 " nop\nnop\nnop\nnop\n"
asm volatile(
"push r31\n"
"push r30\n"
"mov r19, %1 \n" // Length in bytes
"ldi r20, 0x01 \n" // phase 1 pin 1 high, pin 5 low
"ldi r21, 0x02 \n" // phase 2 pin 1 low, pin 2 high
"ld r16, z+ \n"
// Sync
SET_1 SET_5
DLY_8
CLR_1
DLY_8
CLR_5
DLY_8
SET_5
DLY_8
CLR_5
DLY_8
SET_5
DLY_8
CLR_5
DLY_8
SET_5
DLY_8
CLR_5
DLY_8
SET_5
DLY_8
SET_1
CLR_5
// Pin 5 is low, Pin 1 is high. Ready for 1st phase
// Note: Coded for 16Mhz (8 cycles = 500ns)
"next_byte:\n"
"out %0, r20 \n" // 1 initial phase 1 state
"out %0, r16 \n" // 1 data
"cbi %0, 0 \n" // 1 falling edge on pin 1
"ld r16, z+ \n" // 2 load phase 2 data
"dec r19 \n" // 1 Decrement counter for brne below
"nop \n" // 1
"nop \n" // 1
"out %0, r21 \n" // 1 initial phase 2 state
"out %0, r16 \n" // 1 data
"cbi %0, 1 \n" // 1 falling edge on pin 5
"ld r16, z+ \n" // 2
"nop \n" // 1
"brne next_byte \n" // 2
"done:\n"
// End of transmission
SET_5 DLY_4 CLR_5 DLY_4
CLR_1 DLY_8 SET_1 DLY_8 CLR_1 DLY_8 SET_1 DLY_4 SET_5
"pop r30 \n"
"pop r31 \n"
:
: "I" (_SFR_IO_ADDR(PORTC)), "r"(buf_used/2), "z"(maplebuf)
: "r1","r16","r17","r18","r19","r20","r21"
);
DDRC &= ~0x03;
}
void maple_sendFrame(uint32_t *words, unsigned char nwords)
{
uint8_t data[nwords * 4 + 1];
uint8_t *d;
uint8_t lrc=0;
int i;
d = data;
for (i=0; i<nwords; i++) {
*d = words[i];
lrc ^= *d;
d++;
*d = words[i] >> 8;
lrc ^= *d;
d++;
*d = words[i] >> 16;
lrc ^= *d;
d++;
*d = words[i] >> 24;
lrc ^= *d;
d++;
}
data[nwords *4] = lrc;
maple_sendPacket(data, nwords * 4 + 1);
}

+ 12
- 0
maplebus.h View File

@ -0,0 +1,12 @@
#ifndef _maplebus_h__
#define _maplebus_h__
#include <stdint.h>
void maple_init(void);
void maple_sendPacket(unsigned char *data, unsigned char len);
void maple_sendFrame(uint32_t *words, unsigned char nwords);
int maple_receivePacket(unsigned char *data, unsigned int maxlen);
#endif // _maplebus_h__

+ 643
- 0
rxcode.asm View File

@ -0,0 +1,643 @@
// Generated by generate_rxcode.sh
// Number of samples: 640
" in r16, %1\n st z+, r16 \n" // sample 0
" in r16, %1\n st z+, r16 \n" // sample 1
" in r16, %1\n st z+, r16 \n" // sample 2
" in r16, %1\n st z+, r16 \n" // sample 3
" in r16, %1\n st z+, r16 \n" // sample 4
" in r16, %1\n st z+, r16 \n" // sample 5
" in r16, %1\n st z+, r16 \n" // sample 6
" in r16, %1\n st z+, r16 \n" // sample 7
" in r16, %1\n st z+, r16 \n" // sample 8
" in r16, %1\n st z+, r16 \n" // sample 9
" in r16, %1\n st z+, r16 \n" // sample 10
" in r16, %1\n st z+, r16 \n" // sample 11
" in r16, %1\n st z+, r16 \n" // sample 12
" in r16, %1\n st z+, r16 \n" // sample 13
" in r16, %1\n st z+, r16 \n" // sample 14
" in r16, %1\n st z+, r16 \n" // sample 15
" in r16, %1\n st z+, r16 \n" // sample 16
" in r16, %1\n st z+, r16 \n" // sample 17
" in r16, %1\n st z+, r16 \n" // sample 18
" in r16, %1\n st z+, r16 \n" // sample 19
" in r16, %1\n st z+, r16 \n" // sample 20
" in r16, %1\n st z+, r16 \n" // sample 21
" in r16, %1\n st z+, r16 \n" // sample 22
" in r16, %1\n st z+, r16 \n" // sample 23
" in r16, %1\n st z+, r16 \n" // sample 24
" in r16, %1\n st z+, r16 \n" // sample 25
" in r16, %1\n st z+, r16 \n" // sample 26
" in r16, %1\n st z+, r16 \n" // sample 27
" in r16, %1\n st z+, r16 \n" // sample 28
" in r16, %1\n st z+, r16 \n" // sample 29
" in r16, %1\n st z+, r16 \n" // sample 30
" in r16, %1\n st z+, r16 \n" // sample 31
" in r16, %1\n st z+, r16 \n" // sample 32
" in r16, %1\n st z+, r16 \n" // sample 33
" in r16, %1\n st z+, r16 \n" // sample 34
" in r16, %1\n st z+, r16 \n" // sample 35
" in r16, %1\n st z+, r16 \n" // sample 36
" in r16, %1\n st z+, r16 \n" // sample 37
" in r16, %1\n st z+, r16 \n" // sample 38
" in r16, %1\n st z+, r16 \n" // sample 39
" in r16, %1\n st z+, r16 \n" // sample 40
" in r16, %1\n st z+, r16 \n" // sample 41
" in r16, %1\n st z+, r16 \n" // sample 42
" in r16, %1\n st z+, r16 \n" // sample 43
" in r16, %1\n st z+, r16 \n" // sample 44
" in r16, %1\n st z+, r16 \n" // sample 45
" in r16, %1\n st z+, r16 \n" // sample 46
" in r16, %1\n st z+, r16 \n" // sample 47
" in r16, %1\n st z+, r16 \n" // sample 48
" in r16, %1\n st z+, r16 \n" // sample 49
" in r16, %1\n st z+, r16 \n" // sample 50
" in r16, %1\n st z+, r16 \n" // sample 51
" in r16, %1\n st z+, r16 \n" // sample 52
" in r16, %1\n st z+, r16 \n" // sample 53
" in r16, %1\n st z+, r16 \n" // sample 54
" in r16, %1\n st z+, r16 \n" // sample 55
" in r16, %1\n st z+, r16 \n" // sample 56
" in r16, %1\n st z+, r16 \n" // sample 57
" in r16, %1\n st z+, r16 \n" // sample 58
" in r16, %1\n st z+, r16 \n" // sample 59
" in r16, %1\n st z+, r16 \n" // sample 60
" in r16, %1\n st z+, r16 \n" // sample 61
" in r16, %1\n st z+, r16 \n" // sample 62
" in r16, %1\n st z+, r16 \n" // sample 63
" in r16, %1\n st z+, r16 \n" // sample 64
" in r16, %1\n st z+, r16 \n" // sample 65
" in r16, %1\n st z+, r16 \n" // sample 66
" in r16, %1\n st z+, r16 \n" // sample 67
" in r16, %1\n st z+, r16 \n" // sample 68
" in r16, %1\n st z+, r16 \n" // sample 69
" in r16, %1\n st z+, r16 \n" // sample 70
" in r16, %1\n st z+, r16 \n" // sample 71
" in r16, %1\n st z+, r16 \n" // sample 72
" in r16, %1\n st z+, r16 \n" // sample 73
" in r16, %1\n st z+, r16 \n" // sample 74
" in r16, %1\n st z+, r16 \n" // sample 75
" in r16, %1\n st z+, r16 \n" // sample 76
" in r16, %1\n st z+, r16 \n" // sample 77
" in r16, %1\n st z+, r16 \n" // sample 78
" in r16, %1\n st z+, r16 \n" // sample 79
" in r16, %1\n st z+, r16 \n" // sample 80
" in r16, %1\n st z+, r16 \n" // sample 81
" in r16, %1\n st z+, r16 \n" // sample 82
" in r16, %1\n st z+, r16 \n" // sample 83
" in r16, %1\n st z+, r16 \n" // sample 84
" in r16, %1\n st z+, r16 \n" // sample 85
" in r16, %1\n st z+, r16 \n" // sample 86
" in r16, %1\n st z+, r16 \n" // sample 87
" in r16, %1\n st z+, r16 \n" // sample 88
" in r16, %1\n st z+, r16 \n" // sample 89
" in r16, %1\n st z+, r16 \n" // sample 90
" in r16, %1\n st z+, r16 \n" // sample 91
" in r16, %1\n st z+, r16 \n" // sample 92
" in r16, %1\n st z+, r16 \n" // sample 93
" in r16, %1\n st z+, r16 \n" // sample 94
" in r16, %1\n st z+, r16 \n" // sample 95
" in r16, %1\n st z+, r16 \n" // sample 96
" in r16, %1\n st z+, r16 \n" // sample 97
" in r16, %1\n st z+, r16 \n" // sample 98
" in r16, %1\n st z+, r16 \n" // sample 99
" in r16, %1\n st z+, r16 \n" // sample 100
" in r16, %1\n st z+, r16 \n" // sample 101
" in r16, %1\n st z+, r16 \n" // sample 102
" in r16, %1\n st z+, r16 \n" // sample 103
" in r16, %1\n st z+, r16 \n" // sample 104
" in r16, %1\n st z+, r16 \n" // sample 105
" in r16, %1\n st z+, r16 \n" // sample 106
" in r16, %1\n st z+, r16 \n" // sample 107
" in r16, %1\n st z+, r16 \n" // sample 108
" in r16, %1\n st z+, r16 \n" // sample 109
" in r16, %1\n st z+, r16 \n" // sample 110
" in r16, %1\n st z+, r16 \n" // sample 111
" in r16, %1\n st z+, r16 \n" // sample 112
" in r16, %1\n st z+, r16 \n" // sample 113
" in r16, %1\n st z+, r16 \n" // sample 114
" in r16, %1\n st z+, r16 \n" // sample 115
" in r16, %1\n st z+, r16 \n" // sample 116
" in r16, %1\n st z+, r16 \n" // sample 117
" in r16, %1\n st z+, r16 \n" // sample 118
" in r16, %1\n st z+, r16 \n" // sample 119
" in r16, %1\n st z+, r16 \n" // sample 120
" in r16, %1\n st z+, r16 \n" // sample 121
" in r16, %1\n st z+, r16 \n" // sample 122
" in r16, %1\n st z+, r16 \n" // sample 123
" in r16, %1\n st z+, r16 \n" // sample 124
" in r16, %1\n st z+, r16 \n" // sample 125
" in r16, %1\n st z+, r16 \n" // sample 126
" in r16, %1\n st z+, r16 \n" // sample 127
" in r16, %1\n st z+, r16 \n" // sample 128
" in r16, %1\n st z+, r16 \n" // sample 129
" in r16, %1\n st z+, r16 \n" // sample 130
" in r16, %1\n st z+, r16 \n" // sample 131
" in r16, %1\n st z+, r16 \n" // sample 132
" in r16, %1\n st z+, r16 \n" // sample 133
" in r16, %1\n st z+, r16 \n" // sample 134
" in r16, %1\n st z+, r16 \n" // sample 135
" in r16, %1\n st z+, r16 \n" // sample 136
" in r16, %1\n st z+, r16 \n" // sample 137
" in r16, %1\n st z+, r16 \n" // sample 138
" in r16, %1\n st z+, r16 \n" // sample 139
" in r16, %1\n st z+, r16 \n" // sample 140
" in r16, %1\n st z+, r16 \n" // sample 141
" in r16, %1\n st z+, r16 \n" // sample 142
" in r16, %1\n st z+, r16 \n" // sample 143
" in r16, %1\n st z+, r16 \n" // sample 144
" in r16, %1\n st z+, r16 \n" // sample 145
" in r16, %1\n st z+, r16 \n" // sample 146
" in r16, %1\n st z+, r16 \n" // sample 147
" in r16, %1\n st z+, r16 \n" // sample 148
" in r16, %1\n st z+, r16 \n" // sample 149
" in r16, %1\n st z+, r16 \n" // sample 150
" in r16, %1\n st z+, r16 \n" // sample 151
" in r16, %1\n st z+, r16 \n" // sample 152
" in r16, %1\n st z+, r16 \n" // sample 153
" in r16, %1\n st z+, r16 \n" // sample 154
" in r16, %1\n st z+, r16 \n" // sample 155
" in r16, %1\n st z+, r16 \n" // sample 156
" in r16, %1\n st z+, r16 \n" // sample 157
" in r16, %1\n st z+, r16 \n" // sample 158
" in r16, %1\n st z+, r16 \n" // sample 159
" in r16, %1\n st z+, r16 \n" // sample 160
" in r16, %1\n st z+, r16 \n" // sample 161
" in r16, %1\n st z+, r16 \n" // sample 162
" in r16, %1\n st z+, r16 \n" // sample 163
" in r16, %1\n st z+, r16 \n" // sample 164
" in r16, %1\n st z+, r16 \n" // sample 165
" in r16, %1\n st z+, r16 \n" // sample 166
" in r16, %1\n st z+, r16 \n" // sample 167
" in r16, %1\n st z+, r16 \n" // sample 168
" in r16, %1\n st z+, r16 \n" // sample 169
" in r16, %1\n st z+, r16 \n" // sample 170
" in r16, %1\n st z+, r16 \n" // sample 171
" in r16, %1\n st z+, r16 \n" // sample 172
" in r16, %1\n st z+, r16 \n" // sample 173
" in r16, %1\n st z+, r16 \n" // sample 174
" in r16, %1\n st z+, r16 \n" // sample 175
" in r16, %1\n st z+, r16 \n" // sample 176
" in r16, %1\n st z+, r16 \n" // sample 177
" in r16, %1\n st z+, r16 \n" // sample 178
" in r16, %1\n st z+, r16 \n" // sample 179
" in r16, %1\n st z+, r16 \n" // sample 180
" in r16, %1\n st z+, r16 \n" // sample 181
" in r16, %1\n st z+, r16 \n" // sample 182
" in r16, %1\n st z+, r16 \n" // sample 183
" in r16, %1\n st z+, r16 \n" // sample 184
" in r16, %1\n st z+, r16 \n" // sample 185
" in r16, %1\n st z+, r16 \n" // sample 186
" in r16, %1\n st z+, r16 \n" // sample 187
" in r16, %1\n st z+, r16 \n" // sample 188
" in r16, %1\n st z+, r16 \n" // sample 189
" in r16, %1\n st z+, r16 \n" // sample 190
" in r16, %1\n st z+, r16 \n" // sample 191
" in r16, %1\n st z+, r16 \n" // sample 192
" in r16, %1\n st z+, r16 \n" // sample 193
" in r16, %1\n st z+, r16 \n" // sample 194
" in r16, %1\n st z+, r16 \n" // sample 195
" in r16, %1\n st z+, r16 \n" // sample 196
" in r16, %1\n st z+, r16 \n" // sample 197
" in r16, %1\n st z+, r16 \n" // sample 198
" in r16, %1\n st z+, r16 \n" // sample 199
" in r16, %1\n st z+, r16 \n" // sample 200
" in r16, %1\n st z+, r16 \n" // sample 201
" in r16, %1\n st z+, r16 \n" // sample 202
" in r16, %1\n st z+, r16 \n" // sample 203
" in r16, %1\n st z+, r16 \n" // sample 204
" in r16, %1\n st z+, r16 \n" // sample 205
" in r16, %1\n st z+, r16 \n" // sample 206
" in r16, %1\n st z+, r16 \n" // sample 207
" in r16, %1\n st z+, r16 \n" // sample 208
" in r16, %1\n st z+, r16 \n" // sample 209
" in r16, %1\n st z+, r16 \n" // sample 210
" in r16, %1\n st z+, r16 \n" // sample 211
" in r16, %1\n st z+, r16 \n" // sample 212
" in r16, %1\n st z+, r16 \n" // sample 213
" in r16, %1\n st z+, r16 \n" // sample 214
" in r16, %1\n st z+, r16 \n" // sample 215
" in r16, %1\n st z+, r16 \n" // sample 216
" in r16, %1\n st z+, r16 \n" // sample 217
" in r16, %1\n st z+, r16 \n" // sample 218
" in r16, %1\n st z+, r16 \n" // sample 219
" in r16, %1\n st z+, r16 \n" // sample 220
" in r16, %1\n st z+, r16 \n" // sample 221
" in r16, %1\n st z+, r16 \n" // sample 222
" in r16, %1\n st z+, r16 \n" // sample 223
" in r16, %1\n st z+, r16 \n" // sample 224
" in r16, %1\n st z+, r16 \n" // sample 225
" in r16, %1\n st z+, r16 \n" // sample 226
" in r16, %1\n st z+, r16 \n" // sample 227
" in r16, %1\n st z+, r16 \n" // sample 228
" in r16, %1\n st z+, r16 \n" // sample 229
" in r16, %1\n st z+, r16 \n" // sample 230
" in r16, %1\n st z+, r16 \n" // sample 231
" in r16, %1\n st z+, r16 \n" // sample 232
" in r16, %1\n st z+, r16 \n" // sample 233
" in r16, %1\n st z+, r16 \n" // sample 234
" in r16, %1\n st z+, r16 \n" // sample 235
" in r16, %1\n st z+, r16 \n" // sample 236
" in r16, %1\n st z+, r16 \n" // sample 237
" in r16, %1\n st z+, r16 \n" // sample 238
" in r16, %1\n st z+, r16 \n" // sample 239
" in r16, %1\n st z+, r16 \n" // sample 240
" in r16, %1\n st z+, r16 \n" // sample 241
" in r16, %1\n st z+, r16 \n" // sample 242
" in r16, %1\n st z+, r16 \n" // sample 243
" in r16, %1\n st z+, r16 \n" // sample 244
" in r16, %1\n st z+, r16 \n" // sample 245
" in r16, %1\n st z+, r16 \n" // sample 246
" in r16, %1\n st z+, r16 \n" // sample 247
" in r16, %1\n st z+, r16 \n" // sample 248
" in r16, %1\n st z+, r16 \n" // sample 249
" in r16, %1\n st z+, r16 \n" // sample 250
" in r16, %1\n st z+, r16 \n" // sample 251
" in r16, %1\n st z+, r16 \n" // sample 252
" in r16, %1\n st z+, r16 \n" // sample 253
" in r16, %1\n st z+, r16 \n" // sample 254
" in r16, %1\n st z+, r16 \n" // sample 255
" in r16, %1\n st z+, r16 \n" // sample 256
" in r16, %1\n st z+, r16 \n" // sample 257
" in r16, %1\n st z+, r16 \n" // sample 258
" in r16, %1\n st z+, r16 \n" // sample 259
" in r16, %1\n st z+, r16 \n" // sample 260
" in r16, %1\n st z+, r16 \n" // sample 261
" in r16, %1\n st z+, r16 \n" // sample 262
" in r16, %1\n st z+, r16 \n" // sample 263
" in r16, %1\n st z+, r16 \n" // sample 264
" in r16, %1\n st z+, r16 \n" // sample 265
" in r16, %1\n st z+, r16 \n" // sample 266
" in r16, %1\n st z+, r16 \n" // sample 267
" in r16, %1\n st z+, r16 \n" // sample 268
" in r16, %1\n st z+, r16 \n" // sample 269
" in r16, %1\n st z+, r16 \n" // sample 270
" in r16, %1\n st z+, r16 \n" // sample 271
" in r16, %1\n st z+, r16 \n" // sample 272
" in r16, %1\n st z+, r16 \n" // sample 273
" in r16, %1\n st z+, r16 \n" // sample 274
" in r16, %1\n st z+, r16 \n" // sample 275
" in r16, %1\n st z+, r16 \n" // sample 276
" in r16, %1\n st z+, r16 \n" // sample 277
" in r16, %1\n st z+, r16 \n" // sample 278
" in r16, %1\n st z+, r16 \n" // sample 279
" in r16, %1\n st z+, r16 \n" // sample 280
" in r16, %1\n st z+, r16 \n" // sample 281
" in r16, %1\n st z+, r16 \n" // sample 282
" in r16, %1\n st z+, r16 \n" // sample 283
" in r16, %1\n st z+, r16 \n" // sample 284
" in r16, %1\n st z+, r16 \n" // sample 285
" in r16, %1\n st z+, r16 \n" // sample 286
" in r16, %1\n st z+, r16 \n" // sample 287
" in r16, %1\n st z+, r16 \n" // sample 288
" in r16, %1\n st z+, r16 \n" // sample 289
" in r16, %1\n st z+, r16 \n" // sample 290
" in r16, %1\n st z+, r16 \n" // sample 291
" in r16, %1\n st z+, r16 \n" // sample 292
" in r16, %1\n st z+, r16 \n" // sample 293
" in r16, %1\n st z+, r16 \n" // sample 294
" in r16, %1\n st z+, r16 \n" // sample 295
" in r16, %1\n st z+, r16 \n" // sample 296
" in r16, %1\n st z+, r16 \n" // sample 297
" in r16, %1\n st z+, r16 \n" // sample 298
" in r16, %1\n st z+, r16 \n" // sample 299
" in r16, %1\n st z+, r16 \n" // sample 300
" in r16, %1\n st z+, r16 \n" // sample 301
" in r16, %1\n st z+, r16 \n" // sample 302
" in r16, %1\n st z+, r16 \n" // sample 303
" in r16, %1\n st z+, r16 \n" // sample 304
" in r16, %1\n st z+, r16 \n" // sample 305
" in r16, %1\n st z+, r16 \n" // sample 306
" in r16, %1\n st z+, r16 \n" // sample 307
" in r16, %1\n st z+, r16 \n" // sample 308
" in r16, %1\n st z+, r16 \n" // sample 309
" in r16, %1\n st z+, r16 \n" // sample 310
" in r16, %1\n st z+, r16 \n" // sample 311
" in r16, %1\n st z+, r16 \n" // sample 312
" in r16, %1\n st z+, r16 \n" // sample 313
" in r16, %1\n st z+, r16 \n" // sample 314
" in r16, %1\n st z+, r16 \n" // sample 315
" in r16, %1\n st z+, r16 \n" // sample 316
" in r16, %1\n st z+, r16 \n" // sample 317
" in r16, %1\n st z+, r16 \n" // sample 318
" in r16, %1\n st z+, r16 \n" // sample 319
" in r16, %1\n st z+, r16 \n" // sample 320
" in r16, %1\n st z+, r16 \n" // sample 321
" in r16, %1\n st z+, r16 \n" // sample 322
" in r16, %1\n st z+, r16 \n" // sample 323
" in r16, %1\n st z+, r16 \n" // sample 324
" in r16, %1\n st z+, r16 \n" // sample 325
" in r16, %1\n st z+, r16 \n" // sample 326
" in r16, %1\n st z+, r16 \n" // sample 327
" in r16, %1\n st z+, r16 \n" // sample 328
" in r16, %1\n st z+, r16 \n" // sample 329
" in r16, %1\n st z+, r16 \n" // sample 330
" in r16, %1\n st z+, r16 \n" // sample 331
" in r16, %1\n st z+, r16 \n" // sample 332
" in r16, %1\n st z+, r16 \n" // sample 333
" in r16, %1\n st z+, r16 \n" // sample 334
" in r16, %1\n st z+, r16 \n" // sample 335
" in r16, %1\n st z+, r16 \n" // sample 336
" in r16, %1\n st z+, r16 \n" // sample 337
" in r16, %1\n st z+, r16 \n" // sample 338
" in r16, %1\n st z+, r16 \n" // sample 339
" in r16, %1\n st z+, r16 \n" // sample 340
" in r16, %1\n st z+, r16 \n" // sample 341
" in r16, %1\n st z+, r16 \n" // sample 342
" in r16, %1\n st z+, r16 \n" // sample 343
" in r16, %1\n st z+, r16 \n" // sample 344
" in r16, %1\n st z+, r16 \n" // sample 345
" in r16, %1\n st z+, r16 \n" // sample 346
" in r16, %1\n st z+, r16 \n" // sample 347
" in r16, %1\n st z+, r16 \n" // sample 348
" in r16, %1\n st z+, r16 \n" // sample 349
" in r16, %1\n st z+, r16 \n" // sample 350
" in r16, %1\n st z+, r16 \n" // sample 351
" in r16, %1\n st z+, r16 \n" // sample 352
" in r16, %1\n st z+, r16 \n" // sample 353
" in r16, %1\n st z+, r16 \n" // sample 354
" in r16, %1\n st z+, r16 \n" // sample 355
" in r16, %1\n st z+, r16 \n" // sample 356
" in r16, %1\n st z+, r16 \n" // sample 357
" in r16, %1\n st z+, r16 \n" // sample 358
" in r16, %1\n st z+, r16 \n" // sample 359
" in r16, %1\n st z+, r16 \n" // sample 360
" in r16, %1\n st z+, r16 \n" // sample 361
" in r16, %1\n st z+, r16 \n" // sample 362
" in r16, %1\n st z+, r16 \n" // sample 363
" in r16, %1\n st z+, r16 \n" // sample 364
" in r16, %1\n st z+, r16 \n" // sample 365
" in r16, %1\n st z+, r16 \n" // sample 366
" in r16, %1\n st z+, r16 \n" // sample 367
" in r16, %1\n st z+, r16 \n" // sample 368
" in r16, %1\n st z+, r16 \n" // sample 369
" in r16, %1\n st z+, r16 \n" // sample 370
" in r16, %1\n st z+, r16 \n" // sample 371
" in r16, %1\n st z+, r16 \n" // sample 372
" in r16, %1\n st z+, r16 \n" // sample 373
" in r16, %1\n st z+, r16 \n" // sample 374
" in r16, %1\n st z+, r16 \n" // sample 375
" in r16, %1\n st z+, r16 \n" // sample 376
" in r16, %1\n st z+, r16 \n" // sample 377
" in r16, %1\n st z+, r16 \n" // sample 378
" in r16, %1\n st z+, r16 \n" // sample 379
" in r16, %1\n st z+, r16 \n" // sample 380
" in r16, %1\n st z+, r16 \n" // sample 381
" in r16, %1\n st z+, r16 \n" // sample 382
" in r16, %1\n st z+, r16 \n" // sample 383
" in r16, %1\n st z+, r16 \n" // sample 384
" in r16, %1\n st z+, r16 \n" // sample 385
" in r16, %1\n st z+, r16 \n" // sample 386
" in r16, %1\n st z+, r16 \n" // sample 387
" in r16, %1\n st z+, r16 \n" // sample 388
" in r16, %1\n st z+, r16 \n" // sample 389
" in r16, %1\n st z+, r16 \n" // sample 390
" in r16, %1\n st z+, r16 \n" // sample 391
" in r16, %1\n st z+, r16 \n" // sample 392
" in r16, %1\n st z+, r16 \n" // sample 393
" in r16, %1\n st z+, r16 \n" // sample 394
" in r16, %1\n st z+, r16 \n" // sample 395
" in r16, %1\n st z+, r16 \n" // sample 396
" in r16, %1\n st z+, r16 \n" // sample 397
" in r16, %1\n st z+, r16 \n" // sample 398
" in r16, %1\n st z+, r16 \n" // sample 399
" in r16, %1\n st z+, r16 \n" // sample 400
" in r16, %1\n st z+, r16 \n" // sample 401
" in r16, %1\n st z+, r16 \n" // sample 402
" in r16, %1\n st z+, r16 \n" // sample 403
" in r16, %1\n st z+, r16 \n" // sample 404
" in r16, %1\n st z+, r16 \n" // sample 405
" in r16, %1\n st z+, r16 \n" // sample 406
" in r16, %1\n st z+, r16 \n" // sample 407
" in r16, %1\n st z+, r16 \n" // sample 408
" in r16, %1\n st z+, r16 \n&#