mirror of
https://github.com/raphnet/gc_n64_usb-v3
synced 2025-02-07 02:30:14 -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)
|
||||
{
|
||||
// data as input
|
||||
@ -133,8 +85,6 @@ void gcn64protocol_hwinit(void)
|
||||
PORTB &= ~0x10;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \brief Send n data bytes + stop bit, wait for answer.
|
||||
* \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;
|
||||
unsigned char sreg = SREG;
|
||||
int i;
|
||||
|
||||
#ifdef DISABLE_INTS_DURING_COMM
|
||||
cli();
|
||||
#endif
|
||||
gcn64_sendBytes(data_out, data_out_len);
|
||||
//count = gcn64_receive();
|
||||
count = gcn64_receiveBits(gcn64_workbuf, 0);
|
||||
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)
|
||||
return 0;
|
||||
|
||||
@ -168,15 +124,13 @@ int gcn64_transaction(unsigned char *data_out, int data_out_len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
gcn64_decodeWorkbuf(count);
|
||||
|
||||
/* this delay is required on N64 controllers. Otherwise, after sending
|
||||
* 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. */
|
||||
_delay_us(5);
|
||||
* get status fails. This starts to work at 30us. 60us should be safe. */
|
||||
_delay_us(60); // Note that this results in a 100us delay between packets.
|
||||
|
||||
/* return the number of full bits received. */
|
||||
return (count-1) / 2;
|
||||
/* return the number of full bits received, minus the stop bit */
|
||||
return count-1;
|
||||
}
|
||||
|
||||
|
||||
|
61
gcn64txrx.S
61
gcn64txrx.S
@ -10,6 +10,7 @@
|
||||
#define yh r29
|
||||
#define zl r30
|
||||
#define zh r31
|
||||
#define __zero_reg__ r1
|
||||
|
||||
/* the value of the gpio is pre-configured to low. We simulate
|
||||
an open drain output by toggling the direction */
|
||||
@ -29,12 +30,22 @@
|
||||
#error Only 16MHz clock supported
|
||||
#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
|
||||
; start value. Counting from 0 takes hundreads of
|
||||
; microseconds. Because of this, the reception function
|
||||
; "hangs in there" much longer than necessary..
|
||||
#define TIMING_OFFSET 75
|
||||
|
||||
; unsigned int gcn64_receiveBytes(unsigned char *dstbuf, unsigned char max_bytes);
|
||||
; r24,r25 : dstbuf
|
||||
; r22 : max bytes (for fututre use)
|
||||
@ -44,8 +55,9 @@ gcn64_receiveBits:
|
||||
clr xh
|
||||
mov zl, r24
|
||||
mov zh, r25
|
||||
|
||||
clr r18
|
||||
clr r20
|
||||
inc r20
|
||||
initial_wait_low:
|
||||
inc r18
|
||||
breq timeout ; overflow to 0
|
||||
@ -56,33 +68,60 @@ initial_wait_low:
|
||||
rjmp waithigh
|
||||
|
||||
waitlow:
|
||||
mov r21, r18 ; Save the last value
|
||||
ldi r18, TIMING_OFFSET
|
||||
waitlow_lp:
|
||||
inc r18
|
||||
brmi timeout ; > 127 (approx 50uS timeout)
|
||||
brmi timeout_waitlow ; > 127 (approx 50uS timeout)
|
||||
sbic GCN64_DATA_PIN, GCN64_DATA_BIT
|
||||
rjmp waitlow_lp
|
||||
|
||||
adiw xl, 1 ; count this timed low level
|
||||
adiw xl, 1 ; count this bit
|
||||
breq overflow ; > 255
|
||||
|
||||
#if 0
|
||||
st z+, r19
|
||||
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:
|
||||
ldi r18, TIMING_OFFSET
|
||||
ldi r19, TIMING_OFFSET
|
||||
waithigh_lp:
|
||||
inc r18
|
||||
inc r19
|
||||
brmi timeout ; > 127
|
||||
sbis GCN64_DATA_PIN, GCN64_DATA_BIT
|
||||
rjmp waithigh_lp
|
||||
adiw xl, 1 ; count this timed high level
|
||||
|
||||
breq overflow ; > 255
|
||||
st z+,r18
|
||||
|
||||
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:
|
||||
clr xl
|
||||
clr xh
|
||||
timeout:
|
||||
rxdone:
|
||||
; Return the number if received bits in r24,r25
|
||||
mov r24, xl ; yl
|
||||
mov r25, xh ; yh
|
||||
|
Loading…
Reference in New Issue
Block a user