--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="800"
+ height="480"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.3.1 r9886"
+ sodipodi:docname="libam7xxx_test_image_800x480.svg"
+ inkscape:export-filename="/home/ao2/libam7xxx_test_image_800x480.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.98994949"
+ inkscape:cx="350.20761"
+ inkscape:cy="242.81028"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1152"
+ inkscape:window-height="756"
+ inkscape:window-x="0"
+ inkscape:window-y="29"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Background"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-572.36218)"
+ style="display:inline"
+ sodipodi:insensitive="true">
+ <rect
+ style="color:#000000;fill:#000400;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect2982"
+ width="800"
+ height="480"
+ x="0"
+ y="572.36218" />
+ <text
+ xml:space="preserve"
+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0.09px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans Bold"
+ x="274.20743"
+ y="663.45349"
+ id="text3782"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3784"
+ x="274.20743"
+ y="663.45349">libam7xxx test screen</tspan></text>
+ <path
+ sodipodi:type="arc"
+ style="color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path3778"
+ sodipodi:cx="452.54834"
+ sodipodi:cy="296.15222"
+ sodipodi:rx="88.893425"
+ sodipodi:ry="76.771591"
+ d="m 541.44176,296.15222 a 88.893425,76.771591 0 1 1 -177.78685,0 88.893425,76.771591 0 1 1 177.78685,0 z"
+ transform="matrix(1.091899,0,0,1.2643041,-94.13708,437.93571)" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="Original Size"
+ sodipodi:insensitive="true">
+ <rect
+ style="color:#000000;fill:none;stroke:#00ffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect3752"
+ width="799"
+ height="479"
+ x="0.5"
+ y="0.5" />
+ <text
+ xml:space="preserve"
+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0.09px;word-spacing:0px;fill:#00ffff;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans Bold"
+ x="124.24876"
+ y="390.09644"
+ id="text3756"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3758"
+ x="124.24876"
+ y="390.09644">Original Size: 800x480 (aspect ratio 5:3)</tspan></text>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="Zoom 1: H Scale"
+ sodipodi:insensitive="true">
+ <rect
+ style="color:#000000;fill:none;stroke:#ffff00;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect3762"
+ width="589"
+ height="479"
+ x="105.5"
+ y="0.5"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0.09px;word-spacing:0px;fill:#ffff00;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans Bold"
+ x="124.5183"
+ y="419.9223"
+ id="text3768"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3770"
+ x="124.5183"
+ y="419.9223">Zoom 1 (H scale): 590x480</tspan></text>
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer4"
+ inkscape:label="Zoom 2: H/V Scale"
+ style="display:inline"
+ sodipodi:insensitive="true">
+ <rect
+ style="color:#000000;fill:none;stroke:#ff00ff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect3772"
+ width="799"
+ height="459"
+ x="0.5"
+ y="10.5" />
+ <text
+ xml:space="preserve"
+ style="font-size:24px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;line-height:125%;letter-spacing:0.09px;word-spacing:0px;fill:#ff00ff;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans Bold"
+ x="124.5183"
+ y="449.69543"
+ id="text3774"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3776"
+ x="124.5183"
+ y="449.69543">Zoom 2 (H/V Scale): 800x460</tspan></text>
+ </g>
+</svg>
*-l* '<log level>'::
the verbosity level of libam7xxx output (0-5)
-*-p* '<power level>'::
- power level of device, between 0 (off) and 4 (maximum) +
+*-p* '<power mode>'::
+ the power mode of device, between 0 (off) and 4 (turbo) +
WARNING: Level 2 and greater require the master AND
the slave connector to be plugged in.
+*-z* '<zoom mode>'::
+ the display zoom mode, between 0 (original) and 3 (test)
+
*-h*::
this help message
*-l* '<log level>'::
the verbosity level of libam7xxx output (0-5)
-*-p* '<power level>'::
- power level of device, between 0 (off) and 4 (maximum) +
+*-p* '<power mode>'::
+ the power mode of device, between 0 (off) and 4 (turbo) +
WARNING: Level 2 and greater require the master AND
the slave connector to be plugged in.
+*-z* '<zoom mode>'::
+ the display zoom mode, between 0 (original) and 3 (test)
+
*-W* '<image width>'::
the width of the image to upload
printf("\t\t\t\t\t2 - NV12\n");
printf("\t-q <quality>\t\tquality of jpeg sent to the device, between 1 and 100\n");
printf("\t-l <log level>\t\tthe verbosity level of libam7xxx output (0-5)\n");
- printf("\t-p <power level>\tpower level of device, between %x (off) and %x (maximum)\n", AM7XXX_POWER_OFF, AM7XXX_POWER_TURBO);
- printf("\t\t\t\tWARNING: Level 2 and greater require the master AND\n\t\t\t\t\t the slave connector to be plugged in.\n");
+ printf("\t-p <power mode>\t\tthe power mode of device, between %d (off) and %d (turbo)\n",
+ AM7XXX_POWER_OFF, AM7XXX_POWER_TURBO);
+ printf("\t\t\t\tWARNING: Level 2 and greater require the master AND\n");
+ printf("\t\t\t\t the slave connector to be plugged in.\n");
+ printf("\t-z <zoom mode>\t\tthe display zoom mode, between %d (original) and %d (test)\n",
+ AM7XXX_ZOOM_ORIGINAL, AM7XXX_ZOOM_TEST);
printf("\t-h \t\t\tthis help message\n");
printf("\n\nEXAMPLES OF USE:\n");
printf("\t%s -f x11grab -i :0.0 -o video_size=800x480\n", name);
unsigned int quality = 95;
int log_level = AM7XXX_LOG_INFO;
am7xxx_power_mode power_mode = AM7XXX_POWER_LOW;
+ am7xxx_zoom_mode zoom = AM7XXX_ZOOM_ORIGINAL;
int format = AM7XXX_IMAGE_FORMAT_JPEG;
am7xxx_context *ctx;
am7xxx_device *dev;
- while ((opt = getopt(argc, argv, "f:i:o:s:uF:q:l:p:h")) != -1) {
+ while ((opt = getopt(argc, argv, "f:i:o:s:uF:q:l:p:z:h")) != -1) {
switch (opt) {
case 'f':
input_format_string = strdup(optarg);
case AM7XXX_POWER_MIDDLE:
case AM7XXX_POWER_HIGH:
case AM7XXX_POWER_TURBO:
- fprintf(stdout, "Power mode: %x\n", power_mode);
+ fprintf(stdout, "Power mode: %d\n", power_mode);
break;
default:
- fprintf(stderr, "Invalid power mode value, must be between %x and %x\n", AM7XXX_POWER_OFF, AM7XXX_POWER_TURBO);
+ fprintf(stderr, "Invalid power mode value, must be between %d and %d\n",
+ AM7XXX_POWER_OFF, AM7XXX_POWER_TURBO);
ret = -EINVAL;
goto out;
}
break;
+ case 'z':
+ zoom = atoi(optarg);
+ switch(zoom) {
+ case AM7XXX_ZOOM_ORIGINAL:
+ case AM7XXX_ZOOM_H:
+ case AM7XXX_ZOOM_H_V:
+ case AM7XXX_ZOOM_TEST:
+ fprintf(stdout, "Zoom: %d\n", zoom);
+ break;
+ default:
+ fprintf(stderr, "Invalid zoom mode value, must be between %d and %d\n",
+ AM7XXX_ZOOM_ORIGINAL, AM7XXX_ZOOM_TEST);
+ exit(EXIT_FAILURE);
+ }
+ break;
case 'h':
usage(argv[0]);
ret = 0;
goto cleanup;
}
+ ret = am7xxx_set_zoom_mode(dev, zoom);
+ if (ret < 0) {
+ perror("am7xxx_set_zoom_mode");
+ goto cleanup;
+ }
+
ret = am7xxx_set_power_mode(dev, power_mode);
if (ret < 0) {
perror("am7xxx_set_power_mode");
goto cleanup;
}
+ /* When setting AM7XXX_ZOOM_TEST don't display the actual image */
+ if (zoom == AM7XXX_ZOOM_TEST)
+ goto cleanup;
+
ret = am7xxx_play(input_format_string,
&options,
input_path,
printf("\t\t\t\t\t1 - JPEG\n");
printf("\t\t\t\t\t2 - NV12\n");
printf("\t-l <log level>\t\tthe verbosity level of libam7xxx output (0-5)\n");
- printf("\t-p <power level>\tpower level of device, between %x (off) and %x (maximum)\n", AM7XXX_POWER_OFF, AM7XXX_POWER_TURBO);
- printf("\t\t\t\tWARNING: Level 2 and greater require the master AND\n\t\t\t\t\t the slave connector to be plugged in.\n");
+ printf("\t-p <power mode>\t\tthe power mode of device, between %d (off) and %d (turbo)\n",
+ AM7XXX_POWER_OFF, AM7XXX_POWER_TURBO);
+ printf("\t\t\t\tWARNING: Level 2 and greater require the master AND\n");
+ printf("\t\t\t\t the slave connector to be plugged in.\n");
+ printf("\t-z <zoom mode>\t\tthe display zoom mode, between %d (original) and %d (test)\n",
+ AM7XXX_ZOOM_ORIGINAL, AM7XXX_ZOOM_TEST);
printf("\t-W <image width>\tthe width of the image to upload\n");
printf("\t-H <image height>\tthe height of the image to upload\n");
printf("\t-h \t\t\tthis help message\n");
am7xxx_device *dev;
int log_level = AM7XXX_LOG_INFO;
am7xxx_power_mode power_mode = AM7XXX_POWER_LOW;
+ am7xxx_zoom_mode zoom = AM7XXX_ZOOM_ORIGINAL;
int format = AM7XXX_IMAGE_FORMAT_JPEG;
int width = 800;
int height = 480;
unsigned int size;
am7xxx_device_info device_info;
- while ((opt = getopt(argc, argv, "f:F:l:p:W:H:h")) != -1) {
+ while ((opt = getopt(argc, argv, "f:F:l:p:z:W:H:h")) != -1) {
switch (opt) {
case 'f':
if (filename[0] != '\0')
case AM7XXX_POWER_MIDDLE:
case AM7XXX_POWER_HIGH:
case AM7XXX_POWER_TURBO:
- fprintf(stdout, "Power mode: %x\n", power_mode);
+ fprintf(stdout, "Power mode: %d\n", power_mode);
break;
default:
- fprintf(stderr, "Invalid power mode value, must be between %x and %x\n", AM7XXX_POWER_OFF, AM7XXX_POWER_TURBO);
+ fprintf(stderr, "Invalid power mode value, must be between %d and %d\n",
+ AM7XXX_POWER_OFF, AM7XXX_POWER_TURBO);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'z':
+ zoom = atoi(optarg);
+ switch(zoom) {
+ case AM7XXX_ZOOM_ORIGINAL:
+ case AM7XXX_ZOOM_H:
+ case AM7XXX_ZOOM_H_V:
+ case AM7XXX_ZOOM_TEST:
+ fprintf(stdout, "Zoom: %d\n", zoom);
+ break;
+ default:
+ fprintf(stderr, "Invalid zoom mode value, must be between %d and %d\n",
+ AM7XXX_ZOOM_ORIGINAL, AM7XXX_ZOOM_TEST);
exit(EXIT_FAILURE);
}
break;
printf("Native resolution: %dx%d\n",
device_info.native_width, device_info.native_height);
+ ret = am7xxx_set_zoom_mode(dev, zoom);
+ if (ret < 0) {
+ perror("am7xxx_set_zoom_mode");
+ exit_code = EXIT_FAILURE;
+ goto cleanup;
+ }
+
ret = am7xxx_set_power_mode(dev, power_mode);
if (ret < 0) {
perror("am7xxx_set_power_mode");
goto cleanup;
}
+ /* When setting AM7XXX_ZOOM_TEST don't display the actual image */
+ if (zoom == AM7XXX_ZOOM_TEST)
+ goto cleanup;
+
+
if ((unsigned int)width > device_info.native_width ||
(unsigned int)height > device_info.native_height)
fprintf(stderr, "WARNING: image not fitting the native resolution, it may be displayed wrongly!\n");
AM7XXX_PACKET_TYPE_DEVINFO = 0x01,
AM7XXX_PACKET_TYPE_IMAGE = 0x02,
AM7XXX_PACKET_TYPE_POWER = 0x04,
- AM7XXX_PACKET_TYPE_UNKNOWN = 0x05,
+ AM7XXX_PACKET_TYPE_ZOOM = 0x05,
} am7xxx_packet_type;
struct am7xxx_generic_header {
uint32_t bit0;
};
+struct am7xxx_zoom_header {
+ uint32_t bit1;
+ uint32_t bit0;
+};
+
/*
* Examples of packet headers:
*
struct am7xxx_devinfo_header devinfo;
struct am7xxx_image_header image;
struct am7xxx_power_header power;
+ struct am7xxx_zoom_header zoom;
} header_data;
};
debug(ctx, "\tbit0: 0x%08x (%u)\n", p->bit0, p->bit0);
}
+static void debug_dump_zoom_header(am7xxx_context *ctx, struct am7xxx_zoom_header *z)
+{
+ if (ctx == NULL || z == NULL)
+ return;
+
+ debug(ctx, "Zoom header:\n");
+ debug(ctx, "\tbit1: 0x%08x (%u)\n", z->bit1, z->bit1);
+ debug(ctx, "\tbit0: 0x%08x (%u)\n", z->bit0, z->bit0);
+}
+
static void debug_dump_header(am7xxx_context *ctx, struct am7xxx_header *h)
{
if (ctx == NULL || h == NULL)
debug_dump_power_header(ctx, &(h->header_data.power));
break;
+ case AM7XXX_PACKET_TYPE_ZOOM:
+ debug_dump_zoom_header(ctx, &(h->header_data.zoom));
+ break;
+
default:
debug(ctx, "Packet type not supported!\n");
break;
return send_data(dev, image, image_size);
}
-AM7XXX_PUBLIC int am7xxx_set_power_mode(am7xxx_device *dev, am7xxx_power_mode mode)
+AM7XXX_PUBLIC int am7xxx_set_power_mode(am7xxx_device *dev, am7xxx_power_mode power)
{
int ret;
struct am7xxx_header h = {
.unknown3 = 0x10,
};
- switch(mode) {
+ switch(power) {
case AM7XXX_POWER_OFF:
h.header_data.power.bit2 = 0;
h.header_data.power.bit1 = 0;
break;
default:
- error(dev->ctx, "Power mode not supported!\n");
+ error(dev->ctx, "Unsupported power mode.\n");
+ return -EINVAL;
+ };
+
+ ret = send_header(dev, &h);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+AM7XXX_PUBLIC int am7xxx_set_zoom_mode(am7xxx_device *dev, am7xxx_zoom_mode zoom)
+{
+ int ret;
+ struct am7xxx_header h = {
+ .packet_type = AM7XXX_PACKET_TYPE_ZOOM,
+ .direction = AM7XXX_DIRECTION_OUT,
+ .header_data_len = sizeof(struct am7xxx_zoom_header),
+ .unknown2 = 0x3e,
+ .unknown3 = 0x10,
+ };
+
+ switch(zoom) {
+ case AM7XXX_ZOOM_ORIGINAL:
+ h.header_data.zoom.bit1 = 0;
+ h.header_data.zoom.bit0 = 0;
+ break;
+
+ case AM7XXX_ZOOM_H:
+ h.header_data.zoom.bit1 = 0;
+ h.header_data.zoom.bit0 = 1;
+ break;
+
+ case AM7XXX_ZOOM_H_V:
+ h.header_data.zoom.bit1 = 1;
+ h.header_data.zoom.bit0 = 0;
+ break;
+
+ case AM7XXX_ZOOM_TEST:
+ h.header_data.zoom.bit1 = 1;
+ h.header_data.zoom.bit0 = 1;
+ break;
+
+ default:
+ error(dev->ctx, "Unsupported zoom mode.\n");
return -EINVAL;
};
} am7xxx_power_mode;
/**
+ * The display zoom modes.
+ *
+ * An am7xxx device can display images using several zoom modes.
+ *
+ * @note Changing the zoom mode can change the aspect ratio of the displayed
+ * image.
+ *
+ * @note On the zoom test screen the version of the firmware running on the
+ * device is shown as well (e.g SPI_V21.0.0_2011.03.18).
+ */
+typedef enum {
+ AM7XXX_ZOOM_ORIGINAL = 0, /**< Original Size, as retrieved via #am7xxx_device_info. */
+ AM7XXX_ZOOM_H = 1, /**< Zoom 1: H Scale (changes aspect ratio). */
+ AM7XXX_ZOOM_H_V = 2, /**< Zoom 2: H/V Scale (changes aspect ratio). */
+ AM7XXX_ZOOM_TEST = 3, /**< Zoom test screen, the firmware version is shown as well. */
+} am7xxx_zoom_mode;
+
+/**
* Initialize the library context and data structures, and scan for devices.
*
* @param[out] ctx A pointer to the context the library will be used in.
/**
* Set the power mode of an am7xxx device.
*
- * \note If we set the mode to AM7XXX_POWER_OFF we can't turn the
- * display on again by using only am7xxx_set_power_mode(). This needs to be
- * investigated, maybe some other command can reset the device.
+ * @note When setting the mode to AM7XXX_POWER_OFF the display can't be turned
+ * on again by using only am7xxx_set_power_mode(), am7xxx_set_zoom_mode() has
+ * to be called first, the current guess is that the latter performs some
+ * other resets beside setting the zoom mode.
*
- * @param[in] dev A pointer to the structure representing the device to get info of
- * @param[in] mode The power mode to put the device in (see @link am7xxx_power_mode @endlink enum)
+ * @param[in] dev A pointer to the structure representing the device to set power mode to
+ * @param[in] power The power mode to put the device in (see #am7xxx_power_mode enum)
+ *
+ * @return 0 on success, a negative value on error
+ *
+ */
+int am7xxx_set_power_mode(am7xxx_device *dev, am7xxx_power_mode power);
+
+/**
+ * Set the zoom mode of an am7xxx device.
+ *
+ * @note When setting the mode to AM7XXX_ZOOM_TEST, the calling program might
+ * want to skip displaying actual images.
+ *
+ * @note It looks like that power mode and zoom mode are related somehow wrt.
+ * resetting the operational mode after AM7XXX_POWER_OFF, applications can
+ * restore the display properly using this combination:
+ * - Off: power mode 0, zoom mode 3
+ * - On: power mode != 0, zoom mode != 3
+ *
+ * @param[in] dev A pointer to the structure representing the device to set zoom mode to
+ * @param[in] zoom The zoom mode to put the device in (see #am7xxx_zoom_mode enum)
*
* @return 0 on success, a negative value on error
*
*/
-int am7xxx_set_power_mode(am7xxx_device *dev, am7xxx_power_mode mode);
+int am7xxx_set_zoom_mode(am7xxx_device *dev, am7xxx_zoom_mode zoom);
#ifdef __cplusplus
}