mirror of
https://github.com/raphnet/gc_n64_usb-v3
synced 2025-02-11 20:50:20 -05:00
Half the memory footprint for reception code
This commit is contained in:
parent
cb9be3f604
commit
6aaccb0eb3
@ -71,54 +71,6 @@ void gcn64_protocol_getBytes(int offset, int n_bytes, unsigned char *dstbuf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* \brief Decode the received length of low/high states to byte-per-bit format
|
|
||||||
*
|
|
||||||
* The result is in workbuf.
|
|
||||||
*
|
|
||||||
**/
|
|
||||||
static void gcn64_decodeWorkbuf(unsigned int count)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
volatile unsigned char *output = gcn64_workbuf;
|
|
||||||
volatile unsigned char *input = gcn64_workbuf;
|
|
||||||
unsigned char t;
|
|
||||||
|
|
||||||
//
|
|
||||||
// ________
|
|
||||||
// ________/
|
|
||||||
//
|
|
||||||
// [i*2] [i*2+1]
|
|
||||||
//
|
|
||||||
// ________________
|
|
||||||
// 0 : ____/
|
|
||||||
// ____
|
|
||||||
// 1 : ________________/
|
|
||||||
//
|
|
||||||
// The timings on a real N64 are
|
|
||||||
//
|
|
||||||
// 0 : 1 us low, 3 us high
|
|
||||||
// 1 : 3 us low, 1 us high
|
|
||||||
//
|
|
||||||
// However, HORI pads use something similar to
|
|
||||||
//
|
|
||||||
// 0 : 1.5 us low, 4.5 us high
|
|
||||||
// 1 : 4.5 us low, 1.5 us high
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// No64 us = microseconds
|
|
||||||
|
|
||||||
// This operation takes approximately 100uS on 64bit gamecube messages
|
|
||||||
for (i=0; i<count; i++) {
|
|
||||||
t = *input;
|
|
||||||
input++;
|
|
||||||
|
|
||||||
*output = t < *input;
|
|
||||||
|
|
||||||
input++;
|
|
||||||
output++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void gcn64protocol_hwinit(void)
|
void gcn64protocol_hwinit(void)
|
||||||
{
|
{
|
||||||
// data as input
|
// data as input
|
||||||
@ -133,8 +85,6 @@ void gcn64protocol_hwinit(void)
|
|||||||
PORTB &= ~0x10;
|
PORTB &= ~0x10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Send n data bytes + stop bit, wait for answer.
|
* \brief Send n data bytes + stop bit, wait for answer.
|
||||||
* \return The number of bits received, 0 on timeout/error.
|
* \return The number of bits received, 0 on timeout/error.
|
||||||
@ -146,15 +96,21 @@ int gcn64_transaction(unsigned char *data_out, int data_out_len)
|
|||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
unsigned char sreg = SREG;
|
unsigned char sreg = SREG;
|
||||||
|
int i;
|
||||||
|
|
||||||
#ifdef DISABLE_INTS_DURING_COMM
|
#ifdef DISABLE_INTS_DURING_COMM
|
||||||
cli();
|
cli();
|
||||||
#endif
|
#endif
|
||||||
gcn64_sendBytes(data_out, data_out_len);
|
gcn64_sendBytes(data_out, data_out_len);
|
||||||
//count = gcn64_receive();
|
|
||||||
count = gcn64_receiveBits(gcn64_workbuf, 0);
|
count = gcn64_receiveBits(gcn64_workbuf, 0);
|
||||||
SREG = sreg;
|
SREG = sreg;
|
||||||
|
#if 0
|
||||||
|
printf("Count: %d { ", count);
|
||||||
|
for (i=0; i<count; i++) {
|
||||||
|
printf("%02x ", gcn64_workbuf[i]);
|
||||||
|
}
|
||||||
|
printf("}\r\n");
|
||||||
|
#endif
|
||||||
if (!count)
|
if (!count)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -168,15 +124,13 @@ int gcn64_transaction(unsigned char *data_out, int data_out_len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
gcn64_decodeWorkbuf(count);
|
|
||||||
|
|
||||||
/* this delay is required on N64 controllers. Otherwise, after sending
|
/* this delay is required on N64 controllers. Otherwise, after sending
|
||||||
* a rumble-on or rumble-off command (probably init too), the following
|
* a rumble-on or rumble-off command (probably init too), the following
|
||||||
* get status fails. This starts to work at 2us. 5 should be safe. */
|
* get status fails. This starts to work at 30us. 60us should be safe. */
|
||||||
_delay_us(5);
|
_delay_us(60); // Note that this results in a 100us delay between packets.
|
||||||
|
|
||||||
/* return the number of full bits received. */
|
/* return the number of full bits received, minus the stop bit */
|
||||||
return (count-1) / 2;
|
return count-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
61
gcn64txrx.S
61
gcn64txrx.S
@ -10,6 +10,7 @@
|
|||||||
#define yh r29
|
#define yh r29
|
||||||
#define zl r30
|
#define zl r30
|
||||||
#define zh r31
|
#define zh r31
|
||||||
|
#define __zero_reg__ r1
|
||||||
|
|
||||||
/* the value of the gpio is pre-configured to low. We simulate
|
/* the value of the gpio is pre-configured to low. We simulate
|
||||||
an open drain output by toggling the direction */
|
an open drain output by toggling the direction */
|
||||||
@ -29,12 +30,22 @@
|
|||||||
#error Only 16MHz clock supported
|
#error Only 16MHz clock supported
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/************************************************
|
||||||
|
* Function gcn64_receiveBits
|
||||||
|
*
|
||||||
|
* Works by timing the low and high periods of each bit and
|
||||||
|
* then comparing them to know if a 1 or a 0 was on the wire.
|
||||||
|
*
|
||||||
|
* Example timed values:
|
||||||
|
* 54 4e 53 4d 53 4d 53 4e 53 4d 4d 53 53 4e 4c 54 53 4d 54 4d 53 4d 53 4d ...
|
||||||
|
* 0 0 0 0 0 1 0 1 0 0 0 0 ....
|
||||||
|
*/
|
||||||
|
|
||||||
; The bit timeout is a counter to 127. This is the
|
; The bit timeout is a counter to 127. This is the
|
||||||
; start value. Counting from 0 takes hundreads of
|
; start value. Counting from 0 takes hundreads of
|
||||||
; microseconds. Because of this, the reception function
|
; microseconds. Because of this, the reception function
|
||||||
; "hangs in there" much longer than necessary..
|
; "hangs in there" much longer than necessary..
|
||||||
#define TIMING_OFFSET 75
|
#define TIMING_OFFSET 75
|
||||||
|
|
||||||
; unsigned int gcn64_receiveBytes(unsigned char *dstbuf, unsigned char max_bytes);
|
; unsigned int gcn64_receiveBytes(unsigned char *dstbuf, unsigned char max_bytes);
|
||||||
; r24,r25 : dstbuf
|
; r24,r25 : dstbuf
|
||||||
; r22 : max bytes (for fututre use)
|
; r22 : max bytes (for fututre use)
|
||||||
@ -44,8 +55,9 @@ gcn64_receiveBits:
|
|||||||
clr xh
|
clr xh
|
||||||
mov zl, r24
|
mov zl, r24
|
||||||
mov zh, r25
|
mov zh, r25
|
||||||
|
|
||||||
clr r18
|
clr r18
|
||||||
|
clr r20
|
||||||
|
inc r20
|
||||||
initial_wait_low:
|
initial_wait_low:
|
||||||
inc r18
|
inc r18
|
||||||
breq timeout ; overflow to 0
|
breq timeout ; overflow to 0
|
||||||
@ -56,33 +68,60 @@ initial_wait_low:
|
|||||||
rjmp waithigh
|
rjmp waithigh
|
||||||
|
|
||||||
waitlow:
|
waitlow:
|
||||||
|
mov r21, r18 ; Save the last value
|
||||||
ldi r18, TIMING_OFFSET
|
ldi r18, TIMING_OFFSET
|
||||||
waitlow_lp:
|
waitlow_lp:
|
||||||
inc r18
|
inc r18
|
||||||
brmi timeout ; > 127 (approx 50uS timeout)
|
brmi timeout_waitlow ; > 127 (approx 50uS timeout)
|
||||||
sbic GCN64_DATA_PIN, GCN64_DATA_BIT
|
sbic GCN64_DATA_PIN, GCN64_DATA_BIT
|
||||||
rjmp waitlow_lp
|
rjmp waitlow_lp
|
||||||
|
|
||||||
adiw xl, 1 ; count this timed low level
|
adiw xl, 1 ; count this bit
|
||||||
breq overflow ; > 255
|
breq overflow ; > 255
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
st z+, r19
|
||||||
st z+, r18
|
st z+, r18
|
||||||
|
rjmp waithigh
|
||||||
|
#else
|
||||||
|
; Compare the low period and the high period.
|
||||||
|
sub r19, r18
|
||||||
|
brcs got1
|
||||||
|
got0:
|
||||||
|
st z+, __zero_reg__
|
||||||
|
rjmp waithigh
|
||||||
|
got1:
|
||||||
|
st z+,r20
|
||||||
|
#endif
|
||||||
|
|
||||||
waithigh:
|
waithigh:
|
||||||
ldi r18, TIMING_OFFSET
|
ldi r19, TIMING_OFFSET
|
||||||
waithigh_lp:
|
waithigh_lp:
|
||||||
inc r18
|
inc r19
|
||||||
brmi timeout ; > 127
|
brmi timeout ; > 127
|
||||||
sbis GCN64_DATA_PIN, GCN64_DATA_BIT
|
sbis GCN64_DATA_PIN, GCN64_DATA_BIT
|
||||||
rjmp waithigh_lp
|
rjmp waithigh_lp
|
||||||
adiw xl, 1 ; count this timed high level
|
|
||||||
|
|
||||||
breq overflow ; > 255
|
|
||||||
st z+,r18
|
|
||||||
|
|
||||||
rjmp waitlow
|
rjmp waitlow
|
||||||
|
|
||||||
|
timeout_waitlow:
|
||||||
|
adiw xl, 1 ;
|
||||||
|
breq overflow ; > 255
|
||||||
|
|
||||||
|
; Compare the low period and the high period.
|
||||||
|
sub r19, r21
|
||||||
|
brcs lastwas1
|
||||||
|
lastwas0:
|
||||||
|
st z+, __zero_reg__
|
||||||
|
rjmp rxdone
|
||||||
|
lastwas1:
|
||||||
|
st z+,r20
|
||||||
|
rjmp rxdone
|
||||||
|
|
||||||
overflow:
|
overflow:
|
||||||
|
clr xl
|
||||||
|
clr xh
|
||||||
timeout:
|
timeout:
|
||||||
|
rxdone:
|
||||||
; Return the number if received bits in r24,r25
|
; Return the number if received bits in r24,r25
|
||||||
mov r24, xl ; yl
|
mov r24, xl ; yl
|
||||||
mov r25, xh ; yh
|
mov r25, xh ; yh
|
||||||
|
Loading…
Reference in New Issue
Block a user